From 6c2b7882ce681cc1fb22f33d699e661b573ac397 Mon Sep 17 00:00:00 2001 From: Jiri Kuncar <jiri.kuncar@gmail.com> Date: Mon, 30 Oct 2017 12:38:23 +0100 Subject: [PATCH] global: cleaned code style and doctests --- tests/conftest.py => conftest.py | 33 ++++++++- docs/app.rst | 1 - docs/driver.rst | 15 ++-- docs/glv.rst | 14 ++-- docs/index.rst | 21 +++--- docs/ogm.rst | 117 ++++++++++++++++-------------- goblin/__init__.py | 3 + goblin/element.py | 10 ++- goblin/mapper.py | 2 +- setup.py | 3 +- tests/test_client.py | 3 +- tests/test_config.py | 3 +- tests/test_connection.py | 12 ++- tests/test_connection_protocol.py | 90 ++++++++++++++--------- tests/test_graph.py | 3 +- tests/test_pool.py | 6 +- tests/test_properties.py | 19 +++-- tests/test_provider_conf.py | 74 +++++++++++-------- tests/test_session.py | 2 +- 19 files changed, 263 insertions(+), 168 deletions(-) rename tests/conftest.py => conftest.py (88%) diff --git a/tests/conftest.py b/conftest.py similarity index 88% rename from tests/conftest.py rename to conftest.py index c612b6d..1e49646 100644 --- a/tests/conftest.py +++ b/conftest.py @@ -24,7 +24,8 @@ def pytest_addoption(parser): parser.addoption('--gremlin-port', default='8182') -db_name_factory = lambda x, y: "{}__{}".format(y, x) +def db_name_factory(x, y): + return "{}__{}".format(y, x) class HistoricalName(element.VertexProperty): @@ -77,8 +78,8 @@ def provider(request): import goblin_dse except ImportError: raise RuntimeError( - "Couldn't run tests with DSEGraph provider: the goblin_dse package " - "must be installed") + "Couldn't run tests with DSEGraph provider: the goblin_dse " + "package must be installed") else: return goblin_dse.DSEGraph @@ -317,3 +318,29 @@ def flt_class(): @pytest.fixture def boolean_class(): return properties.Boolean + + +@pytest.fixture(autouse=True) +def add_doctest_default(doctest_namespace, tmpdir, event_loop, app): + doctest_namespace['Person'] = Person + doctest_namespace['loop'] = event_loop + doctest_namespace['app'] = app + config = tmpdir.join('config.yml') + config.write( + "scheme: 'ws'\n" + "hosts: ['localhost']\n" + "port': 8182\n" + "ssl_certfile: ''\n" + "ssl_keyfile: ''\n" + "ssl_password: ''\n" + "username: ''\n" + "password: ''\n" + "response_timeout: None\n" + "max_conns: 4\n" + "min_conns: 1\n" + "max_times_acquired: 16\n" + "max_inflight: 64\n" + "message_serializer: 'goblin.driver.GraphSONMessageSerializer'\n" + ) + with tmpdir.as_cwd(): + yield diff --git a/docs/app.rst b/docs/app.rst index dbf1bf4..f5b504a 100644 --- a/docs/app.rst +++ b/docs/app.rst @@ -14,7 +14,6 @@ be passed as keyword arguments, or loaded from a config file:: >>> import asyncio >>> from goblin import Goblin - >>> loop = asyncio.get_event_loop() >>> app = loop.run_until_complete(Goblin.open(loop)) diff --git a/docs/driver.rst b/docs/driver.rst index c3e8637..bbf0ebe 100644 --- a/docs/driver.rst +++ b/docs/driver.rst @@ -11,12 +11,15 @@ To take advantage of the higher level features of the clients that leverage connection pooling and sharing. Its interface is based on the TinkerPop Java driver:: - >>> cluster = await driver.Cluster.open() # opens a cluster with default config - >>> client = await cluster.connect() - >>> resp = await client.submit(gremlin='1 + 1') # round robin requests to available hosts - >>> async for msg in resp: - ... print(msg) - >>> await cluster.close() # Close all connections to all hosts + >>> async def print_results(gremlin='1+1'): + ... # opens a cluster with default config + ... cluster = await driver.Cluster.open('') + ... client = await cluster.connect() + ... # round robin requests to available hosts + ... resp = await client.submit(gremlin=gremlin) + ... async for msg in resp: + ... print(msg) + ... await cluster.close() # Close all connections to all hosts And that is it. While :py:class:`Cluster<goblin.driver.Cluster>` is simple to learn and use, it provides a wide variety of configuration options. diff --git a/docs/glv.rst b/docs/glv.rst index 30e3b93..527f610 100644 --- a/docs/glv.rst +++ b/docs/glv.rst @@ -15,9 +15,9 @@ connection class, either >>> loop = asyncio.get_event_loop() >>> remote_conn = loop.run_until_complete( ... goblin.DriverRemoteConnection.open( - ... "http://localhost:8182/gremlin", loop)) - >>> graph = driver.Graph() - >>> g = goblin.traversal().withRemote(remote_conn) + ... "http://localhost:8182/gremlin", 'g')) + >>> graph = goblin.driver.Graph() + >>> g = graph.traversal().withRemote(remote_conn) Once you have a traversal source, it's all Gremlin...:: @@ -28,10 +28,11 @@ Once you have a traversal source, it's all Gremlin...:: implements the Python 3.5 asynchronous iterator protocol:: >>> async def iterate_traversal(traversal): - >>> async for msg in traversal: - >>> print(msg) + ... async for msg in traversal: + ... print(msg) >>> loop.run_until_complete(iterate_traversal(traversal)) + v[...] :py:class:`AsyncGraphTraversal<aiogremlin.process.graph_traversal.AsyncGraphTraversal>` also provides several convenience coroutine methods to help iterate over results: @@ -56,6 +57,7 @@ class. This allows side effects to be retrieved after executing the traversal:: >>> traversal = g.V().aggregate('a') >>> loop.run_until_complete(traversal.iterate()) + [['V'], ['aggregate', 'a']] Calling :py:meth:`keys<aiogremlin.driver_remote_side_effects.AsyncRemoteTraversalSideEffects.keys>` @@ -67,6 +69,7 @@ side effects: ... print(keys) >>> loop.run_until_complete(get_side_effect_keys(traversal)) + {'a'} Then calling :py:meth:`get<aiogremlin.driver_remote_side_effects.AsyncRemoteTraversalSideEffects.get>` @@ -78,6 +81,7 @@ using a valid key will return the cached side effects:: >>> loop.run_until_complete(get_side_effects(traversal)) + {v[1]: 1, ...} And that's it! For more information on Gremlin Language Variants, please visit the `Apache TinkerPop GLV Documentation`_. diff --git a/docs/index.rst b/docs/index.rst index fbdd7a1..a5d5a83 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -103,8 +103,8 @@ database:: ... print(person) >>> loop.run_until_complete(go(app)) - # <__main__.Person object at 0x7fba0b7fa6a0> - # <__main__.Person object at 0x7fba0b7fae48> + <__main__.Person object at ...> + ... Note that a :py:mod:`Goblin` session does not necessarily correspond to a Gremlin Server session. Instead, all elements created using a session are 'live' in the sense that if the @@ -122,7 +122,7 @@ Generate and submit Gremlin traversals in native Python:: >>> async def go(loop): ... remote_connection = await DriverRemoteConnection.open( - ... 'ws://localhost:8182/gremlin', 'g') + ... 'http://localhost:8182/gremlin', 'g') ... g = Graph().traversal().withRemote(remote_connection) ... vertices = await g.V().toList() ... await remote_connection.close() @@ -130,11 +130,11 @@ Generate and submit Gremlin traversals in native Python:: >>> results = loop.run_until_complete(go(loop)) >>> results - # [v[1], v[2], v[3], v[4], v[5], v[6]] + [v[...], ...] - >>> loop.run_until_complete(go(g)) - # {'properties': {'name': [{'value': 'Leif', 'id': 3}]}, 'label': 'developer', 'id': 2, 'type': 'vertex'} + >>> loop.run_until_complete(go(loop)) + [v[...], ...] For more information on using the :py:class:`Graph<aiogremlin.structure.graph.Graph>`, see the `aiogremlin`_ documentation or the :doc:`GLV docs</glv>` @@ -151,16 +151,17 @@ Submit scripts and bindings to the `Gremlin Server`_:: >>> loop = asyncio.get_event_loop() >>> async def go(loop): - ... cluster = await Cluster.open('ws://localhost:8182/gremlin', loop) + ... cluster = await Cluster.open(loop) ... client = await cluster.connect() ... resp = await client.submit( ... "g.addV('developer').property(k1, v1)", ... bindings={'k1': 'name', 'v1': 'Leif'}) - ... async for msg in resp: - ... print(msg) - ... await cluster.close() + ... async for msg in resp: + ... print(msg) + ... await cluster.close() >>> loop.run_until_complete(go(loop)) + v[...] For more information on using the driver, see the `aiogremlin`_ documentation or the :doc:`Driver docs</driver>` diff --git a/docs/ogm.rst b/docs/ogm.rst index 34c948e..7eb07e2 100644 --- a/docs/ogm.rst +++ b/docs/ogm.rst @@ -58,20 +58,14 @@ currently ships with 4 data types: :py:class:`String<goblin.properties.String>`, :py:class:`Boolean<goblin.properties.Boolean>`. Example property definition:: - import goblin - - - class Person(goblin.Vertex): - name = goblin.Property(goblin.String) - - - class City(goblin.Vertex): - name = goblin.Property(goblin.String) - population = goblin.Property(goblin.Integer) - - - class BornIn(goblin.Edge): - pass + >>> import goblin + >>> class Person(goblin.Vertex): + ... name = goblin.Property(goblin.String) + >>> class City(goblin.Vertex): + ... name = goblin.Property(goblin.String) + ... population = goblin.Property(goblin.Integer) + >>> class BornIn(goblin.Edge): + ... pass :py:mod:`Goblin` :py:mod:`properties<goblin.properties.Property>` can also @@ -79,8 +73,8 @@ be created with a default value, set by using the kwarg `default` in the class definition:: - class BornIn(goblin.Edge): - date = goblin.Property(goblin.String, default='unknown') + >>> class BornIn(goblin.Edge): + ... date = goblin.Property(goblin.String, default='unknown') Creating Elements and Setting Property Values @@ -105,8 +99,10 @@ In the case that an invalid property value is set, the validator will raise a :py:class:`ValidationError<goblin.exception.ValidationError>` immediately:: - >>> detroit.population = 'a lot of people' - ValidationError: Not a valid integer: a lot of people + >>> detroit.population = 'a lot of people' + Traceback (most recent call last): + ... + goblin.exception.ValidationError: Not a valid integer: a lot of people Creating Edges @@ -119,7 +115,7 @@ below in the :ref:`Session<session>` section. Source and target vertices may be passed to the edge on instantiation, or added using the property interface:: >>> leif_born_in_detroit = BornIn(leif, detroit) - # or + >>> # or >>> leif_born_in_detroit = BornIn() >>> leif_born_in_detroit.source = leif >>> leif_born_in_detroit.target = detroit @@ -136,10 +132,11 @@ meta-properties. To accommodate this, :py:mod:`Goblin` provides a class :py:class:`VertexProperty<goblin.element.VertexProperty>` that can be used directly to create multi-cardinality properties:: - class Person(goblin.Vertex): - name = goblin.Property(goblin.String) - nicknames = goblin.VertexProperty( - goblin.String, card=Cardinality.list_) + >>> from gremlin_python.process.traversal import Cardinality + >>> class Person(goblin.Vertex): + ... name = goblin.Property(goblin.String) + ... nicknames = goblin.VertexProperty( + ... goblin.String, card=Cardinality.list_) >>> david = Person() @@ -164,17 +161,14 @@ and provide a simple API for accessing and appending vertex properties. To conti with the previous example, we see the `dave` element's nicknames:: >>> david.nicknames - [<VertexProperty(type=<goblin.properties.String object at 0x7f87a67a3048>, value=Dave), - <VertexProperty(type=<goblin.properties.String object at 0x7f87a67a3048>, value=davebshow)] + [<VertexProperty(type=<...>, value=Dave), <VertexProperty(type=<...>, value=davebshow)] To add a nickname without replacing the earlier values, we simple :py:meth:`append` as if the manager were a Python :py:class:`list`:: >>> david.nicknames.append('db') >>> david.nicknames - [<VertexProperty(type=<goblin.properties.String object at 0x7f87a67a3048>, value=Dave), - <VertexProperty(type=<goblin.properties.String object at 0x7f87a67a3048>, value=davebshow), - <VertexProperty(type=<goblin.properties.String object at 0x7f87a67a3048>, value=db)] + [<VertexProperty(type=<...>, value=Dave), <VertexProperty(type=<...>, value=davebshow), <VertexProperty(type=<...>, value=db)] If this were a :py:class:`VertexProperty<goblin.element.VertexProperty>` with a set cardinality, we would simply use :py:meth:`add` to achieve similar functionality. @@ -184,13 +178,12 @@ Both :py:class:`ListVertexPropertyManager<goblin.manager.ListVertexPropertyManag way to access a specific :py:class:`VertexProperty<goblin.element.VertexProperty>`. You simply call the manager, passing the value of the vertex property to be accessed: - >>> db = dave.nicknames('davebshow') - <VertexProperty(type=<goblin.properties.String object at 0x7f87a67a3048>, value=davebshow) + >>> db = david.nicknames('db') The value of the vertex property can be accessed using the `value` property:: >>> db.value - 'davebshow' + 'db' Meta-properties @@ -201,17 +194,17 @@ a base classes for user defined vertex properties that contain meta-properties. To create meta-properties, define a custom vertex property class just like you would any other element, adding as many simple (non-vertex) properties as needed:: - class HistoricalName(goblin.VertexProperty): - notes = goblin.Property(goblin.String) + >>> class HistoricalName(goblin.VertexProperty): + ... notes = goblin.Property(goblin.String) Now, the custom :py:class:`VertexProperty<goblin.element.VertexProperty>` can be added to a vertex class, using any cardinality:: - class City(goblin.Vertex): - name = goblin.Property(goblin.String) - population = goblin.Property(goblin.Integer) - historical_name = HistoricalName( - goblin.String, card=Cardinality.list_) + >>> class City(goblin.Vertex): + ... name = goblin.Property(goblin.String) + ... population = goblin.Property(goblin.Integer) + ... historical_name = HistoricalName( + ... goblin.String, card=Cardinality.list_) Now, meta-properties can be set on the :py:class:`VertexProperty<goblin.element.VertexProperty>` using the descriptor protocol:: @@ -241,12 +234,16 @@ must be wrapped in coroutines and ran using the :py:class:`asyncio.BaseEventLoop but, for convenience, they are shown as if they were run in a Python interpreter. To use a :py:class:`Session<goblin.session.Session>`, first create a :py:class:`Goblin App <goblin.app.Goblin>` using -:py:meth:`Goblin.open<goblin.app.Goblin.open>`, then register the defined element -classes:: +:py:meth:`Goblin.open<goblin.app.Goblin.open>`, + +.. code-block:: python + + app = await goblin.Goblin.open(loop) + + +then register the defined element classes:: - >>> app = await goblin.Goblin.open(loop) >>> app.register(Person, City, BornIn) - >>> session = await app.session() Goblin application support a variety of configuration options, for more information see :doc:`the Goblin application documentation</app>`. @@ -258,8 +255,12 @@ in which they are added. Therefore, when creating edges, it is important to add source and target nodes before the edge (if they don't already exits). Using the previously created elements:: - >>> session.add(leif, detroit, leif_born_in_detroit) - >>> await session.flush() + >>> async def create_elements(app): + ... session = await app.session() + ... session.add(leif, detroit, leif_born_in_detroit) + ... await session.flush() + >>> loop.run_until_complete(create_elements(app)) + And that is it. To see that these elements have actually been created in the db, check that they now have unique ids assigned to them:: @@ -286,12 +287,14 @@ custom Gremlin traversals using the official gremlin-python Gremlin Language Var positional argument. This is merely for convenience, and generates this equivalent Gremlin:: + >>> session = loop.run_until_complete(app.session()) >>> session.traversal(Person) - g.V().hasLabel('person') + [['V'], ['hasLabel', 'person']] Or, simply use the property :py:attr:`g<goblin.session.Session.g>`:: - >>> session.g.V().hasLabel('person')... + >>> session.g.V().hasLabel('person') + [['V'], ['hasLabel', 'person']] In general property names are mapped directly from the OGM to the database. @@ -306,6 +309,7 @@ as class attributes:: So, to write a traversal:: >>> session.traversal(Person).has(Person.name, 'Leifur') + [['V'], ['hasLabel', 'person'], ['has', 'name', 'Leifur']] Also, it is important to note that certain data types could be transformed @@ -313,7 +317,8 @@ before they are written to the database. Therefore, the data type method `to_db` may be required:: >>> session.traversal(Person).has( - ... Person.name, goblin.String.to_db('Leifur')) + ... Person.name, goblin.String().to_db('Leifur')) + [['V'], ['hasLabel', 'person'], ['has', 'name', 'Leifur']] While this is not the case with any of the simple data types shipped with :py:mod:`Goblin`, custom data types or future additions may require this kind of operation. Because of @@ -321,24 +326,30 @@ this, :py:mod:`Goblin` includes the convenience function :py:func:`bindprop<goblin.traversal.bindprop>`, which also allows an optional binding for the value to be specified:: + >>> from goblin.session import bindprop >>> traversal = session.traversal(Person) >>> traversal.has(bindprop(Person, 'name', 'Leifur', binding='v1')) + [['V'], ['hasLabel', 'person'], ['has', binding[name=binding[v1=Leifur]]]] Finally, there are a variety of ways to to submit a traversal to the server. First of all, all traversals are themselve asynchronous iterators, and using them as such will cause a traversal to be sent on the wire: - >>> async for msg in session.g.V().hasLabel('person'): - ... print(msg) +.. code-block:: python + + async for msg in session.g.V().hasLabel('person'): + print(msg) Furthermore, :py:mod:`Goblin` provides several convenience methods that submit a traversal as well as process the results :py:meth:`toList`, :py:meth:`toSet` and :py:meth:`next`. These methods both submit a script to the server and iterate over the results. Remember to `await` the traversal -when calling these methods:: +when calling these methods: - >>> traversal = session.traversal(Person) - >>> leif = await traversal.has( - ... bindprop(Person, 'name', 'Leifur', binding='v1')).next() +.. code-block:: python + + traversal = session.traversal(Person) + leif = await traversal.has( + bindprop(Person, 'name', 'Leifur', binding='v1')).next() And that is pretty much it. We hope you enjoy the :py:mod:`Goblin` OGM. diff --git a/goblin/__init__.py b/goblin/__init__.py index 5929242..20352b0 100644 --- a/goblin/__init__.py +++ b/goblin/__init__.py @@ -1,3 +1,6 @@ +# -*- coding: utf-8 -*- +"""Python toolkit for Tinker Pop 3 Gremlin Server.""" + from goblin.app import Goblin from goblin.driver import AsyncGraph, Cluster, DriverRemoteConnection, Graph from goblin.element import Edge, Vertex, VertexProperty diff --git a/goblin/element.py b/goblin/element.py index 0f3ae62..66ef28e 100644 --- a/goblin/element.py +++ b/goblin/element.py @@ -1,3 +1,6 @@ +# -*- coding: utf-8 -*- +"""Module defining graph elements.""" + import logging import inflection @@ -11,8 +14,8 @@ logger = logging.getLogger(__name__) class ElementMeta(type): """ Metaclass for graph elements. Responsible for creating the - :py:class:`Mapping<goblin.mapper.Mapping>` object and replacing user defined - :py:class:`goblin.properties.Property` with + :py:class:`Mapping<goblin.mapper.Mapping>` object and replacing user + defined :py:class:`goblin.properties.Property` with :py:class:`goblin.properties.PropertyDescriptor`. """ @@ -112,7 +115,8 @@ class VertexProperty(Element, abc.BaseProperty): card=None, db_name_factory=None): if not db_name_factory: - db_name_factory = lambda x, y: None # noop + def db_name_factory(x, y): + pass if isinstance(data_type, type): data_type = data_type() self._db_name_factory = db_name_factory diff --git a/goblin/mapper.py b/goblin/mapper.py index 71c9f6f..69332cd 100644 --- a/goblin/mapper.py +++ b/goblin/mapper.py @@ -89,7 +89,7 @@ def map_vertex_to_ogm(result, props, element, *, mapping=None): # temp hack def get_hashable_id(val): - #Use the value "as-is" by default. + """Use the value "as-is" by default.""" if isinstance(val, dict) and "@type" in val and "@value" in val: if val["@type"] == "janusgraph:RelationIdentifier": val = val["@value"]["value"] diff --git a/setup.py b/setup.py index 6298dcf..b4df897 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -"""Python toolkit for Tinker Pop 3 Gremlin Server""" +"""Python toolkit for Tinker Pop 3 Gremlin Server.""" import os @@ -48,6 +48,7 @@ with open(os.path.join('goblin', 'version.py'), 'rt') as fp: exec(fp.read(), g) version = g['__version__'] +print(packages) setup( name='goblin', diff --git a/tests/test_client.py b/tests/test_client.py index 28dbdee..1d9559b 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -33,7 +33,8 @@ async def test_alias(cluster): # session = str(uuid.uuid4()) # client = await cluster.connect(session=session) # assert isinstance(client.cluster, GremlinServer) -# resp = await client.submit("v = g.addV('person').property('name', 'joe').next(); v") +# resp = await client.submit("v = g.addV('person').property( +# name', 'joe').next(); v") # async for msg in resp: # try: # assert msg['properties']['name'][0]['value'] == 'joe' diff --git a/tests/test_config.py b/tests/test_config.py index 888f261..9337d7c 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -98,7 +98,8 @@ def test_cluster_config_from_module(event_loop, cluster_class, conf_module): assert cluster.config['scheme'] == 'wss' assert cluster.config['hosts'] == ['localhost'] assert cluster.config['port'] == 8183 - assert cluster.config['message_serializer'] is driver.GraphSONMessageSerializer + assert cluster.config['message_serializer'] is \ + driver.GraphSONMessageSerializer @pytest.mark.asyncio diff --git a/tests/test_connection.py b/tests/test_connection.py index a301c66..49d9cc3 100644 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -151,14 +151,17 @@ async def test_connection_response_timeout(connection): # aiohttp_app = web.Application(loop=event_loop) # aiohttp_app.router.add_route('GET', '/gremlin', fake_auth) # handler = aiohttp_app.make_handler() -# srv = await event_loop.create_server(handler, '0.0.0.0', unused_tcp_port) +# srv = await event_loop.create_server(handler, '0.0.0.0', +# unused_tcp_port) # # async with aiohttp.ClientSession(loop=event_loop) as session: # url = 'ws://0.0.0.0:{}/gremlin'.format(unused_tcp_port) # async with session.ws_connect(url) as ws_client: # connection = driver.Connection( -# url=url, ws=ws_client, loop=event_loop, client_session=session, -# username=username, password=password, max_inflight=64, response_timeout=None, +# url=url, ws=ws_client, loop=event_loop, +# client_session=session, +# username=username, password=password, max_inflight=64, +# response_timeout=None, # message_serializer=driver.GraphSONMessageSerializer, # provider=provider.TinkerGraph # ) @@ -170,7 +173,8 @@ async def test_connection_response_timeout(connection): # auth_request = await authentication_request_queue.get() # print(auth_request) # auth_str = auth_request['args']['sasl'] -# assert base64.b64decode(auth_str).decode().split('\x00')[1:] == [username, password] +# assert base64.b64decode(auth_str).decode().split( +# '\x00')[1:] == [username, password] # assert auth_request['requestId'] == initial_request['requestId'] # resp = await task # resp.close() diff --git a/tests/test_connection_protocol.py b/tests/test_connection_protocol.py index f631c0b..47dc4f3 100644 --- a/tests/test_connection_protocol.py +++ b/tests/test_connection_protocol.py @@ -1,20 +1,3 @@ -# # Copyright 2016 David M. Brown -# # -# # 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/>. -# # import asyncio # import uuid # import pytest @@ -26,11 +9,16 @@ # @pytest.mark.asyncio # async def test_eval(remote_graph, connection, aliases): # async with connection: -# connection._message_serializer = serializer.GraphSONMessageSerializer() +# connection._message_serializer = \ +# serializer.GraphSONMessageSerializer() # g = remote_graph.traversal() # traversal = "g.addV('person').property('name', 'leifur')" # resp = await connection.submit( -# processor='', op='eval', gremlin=traversal, scriptEvalTimeout=1, aliases=aliases) +# processor='', +# op='eval', +# gremlin=traversal, +# scriptEvalTimeout=1, +# aliases=aliases) # # async for msg in resp: # assert msg['label'] == 'person' @@ -39,21 +27,31 @@ # @pytest.mark.asyncio # async def test_bytecode(remote_graph, connection, aliases): # async with connection: -# connection._message_serializer = serializer.GraphSONMessageSerializer() +# connection._message_serializer = \ +# serializer.GraphSONMessageSerializer() # g = remote_graph.traversal() # traversal = g.addV('person').property('name', 'leifur') # resp = await connection.submit( -# processor='traversal', op='bytecode', gremlin=traversal.bytecode, aliases=aliases) +# processor='traversal', +# op='bytecode', +# gremlin=traversal.bytecode, +# aliases=aliases) # async for msg in resp: # vid = msg.id # traversal = g.V(vid).label() # resp = await connection.submit( -# processor='traversal', op='bytecode', gremlin=traversal.bytecode, aliases=aliases) +# processor='traversal', +# op='bytecode', +# gremlin=traversal.bytecode, +# aliases=aliases) # async for msg in resp: # assert msg == 'person' # traversal = g.V(vid).name # resp = await connection.submit( -# processor='traversal', op='bytecode', gremlin=traversal.bytecode, aliases=aliases) +# processor='traversal', +# op='bytecode', +# gremlin=traversal.bytecode, +# aliases=aliases) # async for msg in resp: # assert msg == 'leifur' # @@ -61,42 +59,61 @@ # @pytest.mark.asyncio # async def test_side_effects(remote_graph, connection, aliases): # async with connection: -# connection._message_serializer = serializer.GraphSONMessageSerializer() +# connection._message_serializer = \ +# serializer.GraphSONMessageSerializer() # g = remote_graph.traversal() # # Add some nodes # traversal = g.addV('person').property('name', 'leifur') # resp = await connection.submit( -# processor='traversal', op='bytecode', gremlin=traversal.bytecode, aliases=aliases) +# processor='traversal', +# op='bytecode', +# gremlin=traversal.bytecode, +# aliases=aliases) # async for msg in resp: # pass # traversal = g.addV('person').property('name', 'dave') # resp = await connection.submit( -# processor='traversal', op='bytecode', gremlin=traversal.bytecode, aliases=aliases) +# processor='traversal', +# op='bytecode', +# gremlin=traversal.bytecode, +# aliases=aliases) # async for msg in resp: # pass # traversal = g.addV('person').property('name', 'jonathan') # resp = await connection.submit( -# processor='traversal', op='bytecode', gremlin=traversal.bytecode, aliases=aliases) +# processor='traversal', +# op='bytecode', +# gremlin=traversal.bytecode, +# aliases=aliases) # async for msg in resp: # pass # # # # Make a query # traversal = g.V().aggregate('a').aggregate('b') # resp = await connection.submit( -# processor='traversal', op='bytecode', gremlin=traversal.bytecode, aliases=aliases) +# processor='traversal', +# op='bytecode', +# gremlin=traversal.bytecode, +# aliases=aliases) # request_id = resp.request_id # async for msg in resp: # pass -# resp = await connection.submit(processor='traversal', op='keys', -# sideEffect=request_id, aliases=aliases) +# resp = await connection.submit( +# processor='traversal', +# op='keys', +# sideEffect=request_id, +# aliases=aliases) # keys = [] # async for msg in resp: # keys.append(msg) # assert keys == ['a', 'b'] # -# resp = await connection.submit(processor='traversal', op='gather', -# sideEffect=request_id, -# sideEffectKey='a', aliases=aliases) +# resp = await connection.submit( +# processor='traversal', +# op='gather', +# sideEffect=request_id, +# sideEffectKey='a', +# aliases=aliases) # side_effects = [] # async for msg in resp: # side_effects.append(msg) @@ -112,10 +129,13 @@ # @pytest.mark.asyncio # async def test_session(connection, aliases): # async with connection: -# connection._message_serializer = serializer.GraphSONMessageSerializer() +# connection._message_serializer = \ +# serializer.GraphSONMessageSerializer() # session = str(uuid.uuid4()) # resp = await connection.submit( -# gremlin="v = g.addV('person').property('name', 'unused_name').next(); v", +# gremlin= +# "v = g.addV('person').property('name', +# 'unused_name').next(); v", # processor='session', # op='eval', # session=session, diff --git a/tests/test_graph.py b/tests/test_graph.py index 0bc99c3..20e0432 100644 --- a/tests/test_graph.py +++ b/tests/test_graph.py @@ -34,7 +34,8 @@ async def test_submit_traversal(remote_graph, remote_connection): @pytest.mark.asyncio async def test_side_effects(remote_graph, remote_connection): async with remote_connection: - remote_connection._message_serializer = driver.GraphSONMessageSerializer + remote_connection._message_serializer = \ + driver.GraphSONMessageSerializer g = remote_graph.traversal().withRemote(remote_connection) # create some nodes resp = g.addV('person').property('name', 'leifur') diff --git a/tests/test_pool.py b/tests/test_pool.py index f1af1de..cb93cb3 100644 --- a/tests/test_pool.py +++ b/tests/test_pool.py @@ -27,7 +27,7 @@ async def test_acquire_release(connection_pool): async def test_acquire_multiple(connection_pool): conn1 = await connection_pool.acquire() conn2 = await connection_pool.acquire() - assert not conn1 is conn2 + assert conn1 is not conn2 assert len(connection_pool._acquired) == 2 await connection_pool.close() @@ -48,10 +48,10 @@ async def test_acquire_multiple_and_share(connection_pool): connection_pool._max_times_acquired = 2 conn1 = await connection_pool.acquire() conn2 = await connection_pool.acquire() - assert not conn1 is conn2 + assert conn1 is not conn2 conn3 = await connection_pool.acquire() conn4 = await connection_pool.acquire() - assert not conn3 is conn4 + assert conn3 is not conn4 assert conn3 is conn1 assert conn4 is conn2 await connection_pool.close() diff --git a/tests/test_properties.py b/tests/test_properties.py index 932a4a3..6e2e9cc 100644 --- a/tests/test_properties.py +++ b/tests/test_properties.py @@ -1,3 +1,6 @@ +# -*- coding: utf-8 -*- +"""Test model properties.""" + import pytest from gremlin_python.statics import long @@ -222,27 +225,27 @@ class TestFloat: class TestBoolean: def test_validation_true(self, boolean): - assert boolean.validate(True) == True + assert boolean.validate(True) def test_validation_false(self, boolean): - assert boolean.validate(False) == False + assert not boolean.validate(False) def test_to_db_true(self, boolean): - assert boolean.to_db(True) == True + assert boolean.to_db(True) def test_to_db_false(self, boolean): - assert boolean.to_db(False) == False + assert not boolean.to_db(False) def test_to_ogm_true(self, boolean): - assert boolean.to_ogm(True) == True + assert boolean.to_ogm(True) def test_to_ogm_false(self, boolean): - assert boolean.to_ogm(False) == False + assert not boolean.to_ogm(False) def test_initval_to_db_true(self, boolean_class): boolean = boolean_class(True) - assert boolean.to_db() == True + assert boolean.to_db() def test_initval_to_db_true(self, boolean_class): boolean = boolean_class(False) - assert boolean.to_db() == False + assert not boolean.to_db() diff --git a/tests/test_provider_conf.py b/tests/test_provider_conf.py index 87d2f4c..10cb433 100644 --- a/tests/test_provider_conf.py +++ b/tests/test_provider_conf.py @@ -14,10 +14,12 @@ # from goblin import driver # from goblin import provider # -# request_id = uuid.UUID(int=215449331521667564889692237976543325869, version=4) +# request_id = uuid.UUID(int=215449331521667564889692237976543325869, +# version=4) # # -# # based on this handy tip on SO: http://stackoverflow.com/a/29905620/6691423 +# # based on this handy tip on SO: +# # http://stackoverflow.com/a/29905620/6691423 # def get_mock_coro(return_value): # async def mock_coro(*args, **kwargs): # return return_value @@ -50,7 +52,6 @@ # 'eval': { # 'manageTransaction': True # }, -# # } # } # @@ -65,50 +66,56 @@ # return json.loads(payload.decode()) # # -# @pytest.fixture(params=( -# driver.GraphSONMessageSerializer, -# driver.GraphSONMessageSerializer -# )) +# @pytest.fixture(params=(driver.GraphSONMessageSerializer, +# driver.GraphSONMessageSerializer)) # def message_serializer(request): # return request.param # # -# @pytest.mark.parametrize('processor_name,key,value', ( -# ('standard', 'fictional_argument', 'fictional_value'), -# ('session', 'manageTransaction', True) -# )) +# @pytest.mark.parametrize( +# 'processor_name,key,value', +# (('standard', 'fictional_argument', 'fictional_value'), +# ('session', 'manageTransaction', True))) # def test_get_processor_provider_default_args(processor_name, key, value): -# processor = driver.GraphSONMessageSerializer.get_processor(TestProvider, processor_name) -# assert processor._default_args == TestProvider.DEFAULT_OP_ARGS[processor_name] +# processor = driver.GraphSONMessageSerializer.get_processor( +# TestProvider, processor_name) +# assert processor._default_args == TestProvider.DEFAULT_OP_ARGS[ +# processor_name] # eval_args = processor.get_op_args('eval', {'gremlin': 'g.V()'}) # assert eval_args['gremlin'] == 'g.V()' # assert eval_args[key] == value # # -# @pytest.mark.parametrize('processor,key,value', ( -# ('', 'fictional_argument', 'fictional_value'), -# ('session', 'manageTransaction', True) -# )) -# def test_serializer_default_op_args(message_serializer, processor, key, value): +# @pytest.mark.parametrize('processor,key,value', +# (('', 'fictional_argument', 'fictional_value'), +# ('session', 'manageTransaction', True))) +# def test_serializer_default_op_args(message_serializer, processor, key, +# value): # g = driver.AsyncGraph().traversal() # traversal = g.V().hasLabel('stuff').has('foo', 'bar') # serialized_message = message_serializer.serialize_message( -# TestProvider, str(uuid.uuid4()), processor=processor, op='eval', gremlin=traversal.bytecode) +# TestProvider, +# str(uuid.uuid4()), +# processor=processor, +# op='eval', +# gremlin=traversal.bytecode) # message = deserialize_json_request(serialized_message) # assert message['args'][key] == value # # -# @pytest.mark.parametrize('processor,key,value', ( -# ('', 'fictional_argument', 'fictional_value'), -# ('session', 'manageTransaction', True) -# )) +# @pytest.mark.parametrize('processor,key,value', +# (('', 'fictional_argument', 'fictional_value'), +# ('session', 'manageTransaction', True))) # @pytest.mark.asyncio -# async def test_conn_default_op_args(event_loop, monkeypatch, processor, key, value): +# async def test_conn_default_op_args(event_loop, monkeypatch, processor, +# key, value): # mock_client_session = mock.Mock(spec=aiohttp.ClientSession) # mock_client_session_instance = mock.Mock(spec=aiohttp.ClientSession) # mock_client_session.return_value = mock_client_session_instance -# mock_client_session_instance.ws_connect = mock.Mock(wraps=mock_ws_connect) -# mock_client_session_instance.close = get_mock_coro(None) # otherwise awaiting ws.close is an error +# mock_client_session_instance.ws_connect = mock.Mock( +# wraps=mock_ws_connect) +# mock_client_session_instance.close = get_mock_coro( +# None) # otherwise awaiting ws.close is an error # # monkeypatch.setattr(aiohttp, 'ClientSession', mock_client_session) # monkeypatch.setattr(uuid, 'uuid4', mock.Mock(return_value=request_id)) @@ -117,11 +124,12 @@ # 'some_url', # event_loop, # message_serializer=driver.GraphSONMessageSerializer, -# provider=TestProvider -# ) +# provider=TestProvider) # # resp = await conn.submit( -# gremlin='g.V().hasLabel("foo").count()', processor=processor, op='eval') +# gremlin='g.V().hasLabel("foo").count()', +# processor=processor, +# op='eval') # # submitted_bytes = conn._ws.send_bytes.call_args[0][0] # submitted_json = submitted_bytes[17:].decode() @@ -134,9 +142,13 @@ # # # @pytest.mark.asyncio -# async def test_cluster_conn_provider(event_loop, gremlin_host, gremlin_port): +# async def test_cluster_conn_provider(event_loop, gremlin_host, +# gremlin_port): # cluster = await driver.Cluster.open( -# event_loop, provider=TestProvider, hosts=[gremlin_host], port=gremlin_port) +# event_loop, +# provider=TestProvider, +# hosts=[gremlin_host], +# port=gremlin_port) # assert cluster.config['provider'] == TestProvider # # pooled_conn = await cluster.get_connection() diff --git a/tests/test_session.py b/tests/test_session.py index d4d56f0..8235ff3 100644 --- a/tests/test_session.py +++ b/tests/test_session.py @@ -395,7 +395,7 @@ class TestTraversalApi: 'y').select('x', 'y').fold() resp = await traversal.next() for item in resp: - #BROKEN + # FIXME BROKEN # assert isinstance(item['x'], person_class) assert isinstance(item['y'], dict) await app.close() -- GitLab