1
# -*- coding: utf8 - *-
2 2
"""Cihai core functionality."""
3 2
from __future__ import absolute_import, print_function, unicode_literals
4

5 2
import logging
6 2
import os
7

8 2
import kaptan
9 2
from appdirs import AppDirs
10

11 2
from . import exc, extend
12 2
from ._compat import string_types
13 2
from .config import expand_config
14 2
from .constants import DEFAULT_CONFIG, UNIHAN_CONFIG
15 2
from .db import Database
16 2
from .utils import import_string, merge_dict
17

18 2
log = logging.getLogger(__name__)
19

20

21 2
class Cihai(object):
22
    """
23
    Central application object.
24

25
    By default, this automatically adds the UNIHAN dataset.
26

27
    Attributes
28
    ----------
29
    config : dict
30

31
    Notes
32
    -----
33
    Inspired by the early pypa/warehouse applicaton object [1]_.
34

35
    **Configuration templates**
36

37
    The ``config`` :py:class:`dict` parameter supports a basic template system
38
    for replacing :term:`XDG Base Directory` directory variables, tildes
39
    and environmentas variables. This is done by passing the option dict
40
    through :func:`cihai.config.expand_config` during initialization.
41

42
    Examples
43
    --------
44
    To use cihai programatically, invoke and install the UNIHAN [2]_ dataset:
45

46
    .. literalinclude:: ../examples/basic_usage.py
47
        :language: python
48

49
    Above: :attr:`~cihai.data.unihan.bootstrap.is_bootstrapped` can check if the system
50
    has the database installed.
51

52
    References
53
    ----------
54
    .. [1] PyPA Warehouse on GitHub. https://github.com/pypa/warehouse.
55
       Accessed sometime in 2013.
56
    .. [2] UNICODE HAN DATABASE (UNIHAN) documentation.
57
       https://www.unicode.org/reports/tr38/. Accessed March 31st, 2018.
58
    """
59

60
    #: :py:class:`dict` of default config, can be monkey-patched during tests
61 2
    default_config = DEFAULT_CONFIG
62

63 2
    def __init__(self, config=None, unihan=True):
64
        """
65
        Parameters
66
        ----------
67
        config : dict, optional
68
        unihan : boolean, optional
69
            Bootstrap the core UNIHAN dataset (recommended)
70
        """
71 2
        if config is None:
72 2
            config = {}
73

74
        # Merges custom configuration settings on top of defaults
75
        #: Configuration dictionary
76 2
        self.config = merge_dict(self.default_config, config)
77

78 2
        if unihan:
79 2
            self.config = merge_dict(UNIHAN_CONFIG, self.config)
80

81
        #: XDG App directory locations
82 2
        dirs = AppDirs("cihai", "cihai team")  # appname  # app author
83

84
        #: Expand template variables
85 2
        expand_config(self.config, dirs)
86

87 2
        if not os.path.exists(dirs.user_data_dir):
88 2
            os.makedirs(dirs.user_data_dir)
89

90
        #: :class:`cihai.db.Database` : Database instance
91 2
        self.sql = Database(self.config)
92

93 2
        self.bootstrap()
94

95 2
    def bootstrap(self):
96 2
        for namespace, class_string in self.config.get('datasets', {}).items():
97 2
            self.add_dataset(class_string, namespace)
98

99 2
        for dataset, plugins in self.config.get('plugins', {}).items():
100 0
            for namespace, class_string in plugins.items():
101 0
                getattr(self, dataset).add_plugin(class_string, namespace)
102

103 2
    def add_dataset(self, _cls, namespace):
104 2
        if isinstance(_cls, string_types):
105 2
            _cls = import_string(_cls)
106

107 2
        setattr(self, namespace, _cls())
108 2
        dataset = getattr(self, namespace)
109

110 2
        if isinstance(dataset, extend.SQLAlchemyMixin):
111 2
            dataset.sql = self.sql
112

113 2
    @classmethod
114 2
    def from_file(cls, config_path=None, *args, **kwargs):
115
        """
116
        Create a Cihai instance from a JSON or YAML config.
117

118
        Parameters
119
        ----------
120
        config_path : str, optional
121
            path to custom config file
122

123
        Returns
124
        -------
125
        :class:`Cihai` :
126
            application object
127
        """
128

129 2
        config_reader = kaptan.Kaptan()
130

131 2
        config = {}
132

133 2
        if config_path:
134 2
            if not os.path.exists(config_path):
135 0
                raise exc.CihaiException(
136
                    '{0} does not exist.'.format(os.path.abspath(config_path))
137
                )
138 2
            if not any(
139
                config_path.endswith(ext) for ext in ('json', 'yml', 'yaml', 'ini')
140
            ):
141 0
                raise exc.CihaiException(
142
                    '{0} does not have a yaml,yml,json,ini extend.'.format(
143
                        os.path.abspath(config_path)
144
                    )
145
                )
146
            else:
147 2
                custom_config = config_reader.import_config(config_path).get()
148 2
                config = merge_dict(config, custom_config)
149

150 2
        return cls(config)

Read our documentation on viewing source code .

Loading