app.py 5.43 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Copyright 2016 ZEROFAIL
#
# This file is part of Goblin.
#
# Goblin is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Goblin is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with Goblin.  If not, see <http://www.gnu.org/licenses/>.

18
"""Goblin application class and class constructor"""
19

20
21
22
import collections
import logging

23
from gremlin_python import process
davebshow's avatar
davebshow committed
24
from goblin import driver, element, session
25
26
27
28
29


logger = logging.getLogger(__name__)


30
async def create_app(url, loop, get_hashable_id=None, **config):
31
32
33
34
35
36
37
38
39
40
41
    """
    Constructor function for :py:class:`Goblin`. Connect to database and
    build a dictionary of relevant vendor implmentation features.

    :param str url: Database url
    :param asyncio.BaseEventLoop loop: Event loop implementation
    :param dict config: Config parameters for application

    :returns: :py:class:`Goblin` object
    """

42
43
44
    features = {}
    async with await driver.GremlinServer.open(url, loop) as conn:
        # Propbably just use a parser to parse the whole feature list
45
        aliases = config.get('aliases', {})
46
        stream = await conn.submit(
47
            'graph.features().graph().supportsComputer()', aliases=aliases)
48
        msg = await stream.fetch_data()
49
        features['computer'] = msg
50
        stream = await conn.submit(
51
            'graph.features().graph().supportsTransactions()', aliases=aliases)
52
        msg = await stream.fetch_data()
53
        features['transactions'] = msg
54
        stream = await conn.submit(
55
            'graph.features().graph().supportsPersistence()', aliases=aliases)
56
        msg = await stream.fetch_data()
57
        features['persistence'] = msg
58
        stream = await conn.submit(
59
            'graph.features().graph().supportsConcurrentAccess()', aliases=aliases)
60
        msg = await stream.fetch_data()
61
        features['concurrent_access'] = msg
62
        stream = await conn.submit(
63
            'graph.features().graph().supportsThreadedTransactions()', aliases=aliases)
64
        msg = await stream.fetch_data()
65
        features['threaded_transactions'] = msg
66
67
    return Goblin(url, loop, get_hashable_id=get_hashable_id,
                  features=features, **config)
68
69
70


# Main API classes
davebshow's avatar
davebshow committed
71
class Goblin:
72
73
74
75
76
77
78
79
80
81
82
    """
    Class used to encapsulate database connection configuration and generate
    database connections Used as a factory to create
    :py:class:`Session<goblin.session.Session>` objects.

    :param str url: Database url
    :param asyncio.BaseEventLoop loop: Event loop implementation
    :param dict features: Vendor implementation specific database features
    :param dict config: Config parameters for application
    """

83
84
85
86
    DEFAULT_CONFIG = {
        'translator': process.GroovyTranslator('g')
    }

87
88
    def __init__(self, url, loop, *, get_hashable_id=None, features=None,
                 **config):
89
90
91
92
93
        self._url = url
        self._loop = loop
        self._features = features
        self._config = self.DEFAULT_CONFIG
        self._config.update(config)
davebshow's avatar
davebshow committed
94
        self._vertices = collections.defaultdict(
davebshow's avatar
davebshow committed
95
96
            lambda: element.GenericVertex)
        self._edges = collections.defaultdict(lambda: element.GenericEdge)
97
98
99
        if not get_hashable_id:
            get_hashable_id = lambda x: x
        self._get_hashable_id = get_hashable_id
100
101
102

    @property
    def vertices(self):
103
        """Registered vertex classes"""
104
105
106
107
        return self._vertices

    @property
    def edges(self):
108
        """Registered edge classes"""
109
110
        return self._edges

davebshow's avatar
davebshow committed
111
112
    @property
    def features(self):
113
        """Vendor specific database implementation features"""
davebshow's avatar
davebshow committed
114
115
        return self._features

116
    def from_file(filepath):
117
118
        """Load config from filepath. Not implemented"""
        raise NotImplementedError
119
120

    def from_obj(obj):
121
122
        """Load config from object. Not implemented"""
        raise NotImplementedError
123
124
125

    @property
    def translator(self):
126
        """gremlin-python translator class"""
127
128
129
130
        return self._config['translator']

    @property
    def url(self):
131
        """Database url"""
132
133
134
        return self._url

    def register(self, *elements):
135
136
137
138
139
        """
        Register user created Element classes.

        :param goblin.element.Element elements: User defined Element classes
        """
140
141
142
143
144
145
146
        for element in elements:
            if element.__type__ == 'vertex':
                self._vertices[element.__label__] = element
            if element.__type__ == 'edge':
                self._edges[element.__label__] = element

    async def session(self, *, use_session=False):
147
148
149
150
151
152
153
        """
        Create a session object.

        :param bool use_session: Create a database session. Not implemented

        :returns: :py:class:`Session<goblin.session.Session>` object
        """
154
        aliases = self._config.get('aliases', None)
155
156
157
        conn = await driver.GremlinServer.open(self.url, self._loop)
        return session.Session(self,
                               conn,
158
                               self._get_hashable_id,
159
160
                               use_session=use_session,
                               aliases=aliases)