zerofail / goblin-legacy Goto Github PK
View Code? Open in Web Editor NEWOGM for TinkerPop3 Gremlin Server
License: Apache License 2.0
OGM for TinkerPop3 Gremlin Server
License: Apache License 2.0
Hello everyone! I would like to discuss some plans for moving forward with goblin. The are some implementation details that still need some work, like error handling, logging, etc., but the library is basically up and running. The next big hurdle will be figuring out how to implement some tools for working with Titan's modelling API. I noticed that Cody implemented some model syncing functionality in the original mogwai library, but I haven't looked too closely at it, and I don't know if it ever was actually integrated into the main library.
My initial thought is to provide a series of functions that can perform schema definitions supported by Titan:db [1]. Basically, we would be able to:
Regarding the implementation of this functionality, I want to do something like already suggested by the original mogwai design. The process would be something like this:
>>> generate_specfile(path_to_model_definition="models.py", ...)
The generate_specfile
function inspects the file containing the goblin
model definition and creates a simple JSON style data structure that contains the vertices, edges, and associated properties, which is dumped to a file current_spec.json
.
"[{
"verticies": [{"label": "person", ..., "properties": []}]
"edges": ...
}]"
We then check to see if there is already a spec file associated with the app. If there is, we do a series of simple comparisons to check if there are:
>>> sync_spec(new_specfile, old_specfile)
If there are missing properties, we add this to a list of unused properties that can be reused. Missing vertices/edges are cataloged as unused elements. If there are "new properties" (could be an old property with a name change), we look through the unused properties. If there is an unused property with the proper data type and cardinality, we can recycle it by changing its name using Titan's API. If there are new vertices/edges, they will be created. Optionally, we could allow the user to pass element renaming mappings to allow name changes on vertices and edges, or other functionality to help the process along.
Finally, we output a new spec file that reflects the current state of the Schema, which includes the name changes made during the sync, as well as all of the unused elements.
Of course, if this is the first sync, we simply create the schema based on the specfile,
While this system isn't perfect, it could be pretty handy, especially for adding new models or simple property name changes.
Regarding indices [3], I assume we would like to allow the user to define their own indices on the models, which will be created on model sync. Elements created before index definition can be easily reindexed.
Any ideas @jsenecal or @leifurhauks?
Used conda to create the environment (python3.5)
ran pip install git+https://github.com/ZEROFAIL/goblin.git@dev#egg=goblin
tried running the basic example code (all imports work)
ERROR:tornado.application:Exception in callback <function execute_query..on_connect at 0x104f01158> for <tornado.concurrent.Future object at 0x104a814e0>
Traceback (most recent call last):
ile "/Users/blurb/miniconda3/envs/titan/lib/python3.5/site-packages/tornado/concurrent.py", line 317, in _set_done
cb(self)
File "/Users/blurb/miniconda3/envs/titan/lib/python3.5/site-packages/goblin/connection.py", line 80, in on_connect
request_id=request_id)
TypeError: send() got an unexpected keyword argument 'request_id'
Later on i've did some reading, edited titan-1.0.0-hadoop1/conf/gremlin-server/gremlin-server.yaml
changed channelizer to :
channelizer: org.apache.tinkerpop.gremlin.server.channel.HttpChannelizer
restarted titan server and response:
Traceback (most recent call last):
File "basic.py", line 30, in
followers = loop.run_sync(go)
File "/Users/blurb/miniconda3/envs/titan/lib/python3.5/site-packages/tornado/ioloop.py", line 453, in run_sync
return future_cell[0].result()
File "/Users/blurb/miniconda3/envs/titan/lib/python3.5/site-packages/tornado/concurrent.py", line 232, in result
raise_exc_info(self._exc_info)
File "", line 3, in raise_exc_info
File "/Users/blurb/miniconda3/envs/titan/lib/python3.5/site-packages/tornado/gen.py", line 1014, in run
yielded = self.gen.throw(*exc_info)
File "basic.py", line 18, in go
goblin = yield User.create(name="Goblin")
File "/Users/blurb/miniconda3/envs/titan/lib/python3.5/site-packages/tornado/gen.py", line 1008, in run
value = future.result()
File "/Users/blurb/miniconda3/envs/titan/lib/python3.5/site-packages/tornado/concurrent.py", line 232, in result
raise_exc_info(self._exc_info)
File "", line 3, in raise_exc_info
File "/Users/blurb/miniconda3/envs/titan/lib/python3.5/site-packages/goblin/models/vertex.py", line 368, in on_save
stream = f.result()
File "/Users/blurb/miniconda3/envs/titan/lib/python3.5/site-packages/tornado/concurrent.py", line 232, in result
raise_exc_info(self._exc_info)
File "", line 3, in raise_exc_info
File "/Users/blurb/miniconda3/envs/titan/lib/python3.5/site-packages/goblin/gremlin/base.py", line 291, in on_call
stream = f.result()
File "/Users/blurb/miniconda3/envs/titan/lib/python3.5/site-packages/tornado/concurrent.py", line 232, in result
raise_exc_info(self._exc_info)
File "", line 3, in raise_exc_info
File "/Users/blurb/miniconda3/envs/titan/lib/python3.5/site-packages/goblin/connection.py", line 73, in on_connect
conn = f.result()
File "/Users/blurb/miniconda3/envs/titan/lib/python3.5/site-packages/tornado/concurrent.py", line 232, in result
raise_exc_info(self._exc_info)
File "", line 3, in raise_exc_info
File "/Users/blurb/miniconda3/envs/titan/lib/python3.5/site-packages/gremlinclient/pool.py", line 124, in cb
conn = f.result()
File "/Users/blurb/miniconda3/envs/titan/lib/python3.5/site-packages/tornado/concurrent.py", line 232, in result
raise_exc_info(self._exc_info)
File "", line 3, in raise_exc_info
File "/Users/blurb/miniconda3/envs/titan/lib/python3.5/site-packages/gremlinclient/tornado_client/client.py", line 116, in get_conn
conn = f.result()
File "/Users/blurb/miniconda3/envs/titan/lib/python3.5/site-packages/tornado/concurrent.py", line 232, in result
raise_exc_info(self._exc_info)
File "", line 3, in raise_exc_info
tornado.httpclient.HTTPError: HTTP 400: Bad Request
So, I am working on deriving a class from the Goblin Vertex class. In the source code, it seems to indicate that the .label property will be automatically set from the class name, but I haven’t found this to be the case.
Here is my source:
from goblin import properties
from goblin import connection
from goblin.models import Vertex
import asyncio
from tornado.platform.asyncio import AsyncIOMainLoop
class TestVertex(Vertex):
prop1 = properties.String()
@asyncio.coroutine
def drop():
stream = yield from TestVertex.all()
vertices = yield from stream.read()
for vertex in vertices:
yield from vertex.delete()
@asyncio.coroutine
def create():
yield from TestVertex.create(prop1='A')
yield from TestVertex.create(prop1='B')
@asyncio.coroutine
def report():
stream = yield from TestVertex.all()
vertices = yield from stream.read()
for vertex in vertices:
print(vertex.label)
print(vertex)
if __name__ == '__main__':
connection.setup('ws://localhost:8182', future_class=asyncio.Future)
AsyncIOMainLoop().install()
loop = asyncio.get_event_loop()
try:
print("dropping")
loop.run_until_complete(drop())
print("creating")
loop.run_until_complete(create())
print("reporting")
loop.run_until_complete(report())
print("ending")
except Exception as err:
print("Caught an errror: {}".format(err))
raise err
finally:
connection.tear_down()
loop.close()
And the output:
$ python test.py
dropping
creating
reporting
None
TestVertex(label=test_vertex, id=20560, values={'prop1': 'B'})
None
TestVertex(label=test_vertex, id=12384, values={'prop1': 'A'})
ending
I would expect that the line above that says 'None' should say 'TestVertex'
I noticed that the second code example seems to be out of date. In particular, the 'future' keyword argument to connection.setup should be 'future_class'
I don't know if there are other issues or not; this was the only one I discovered
Hello all,
I wanted to discuss the implementation of time based versioning and get your feedback. After looking through Ian Robinson's Neo4j Time-Based Versioned Graphs blog [1], I think that his approach can be adapted to fit goblin.
I'm not going to summarize the contents of the article, but here are the different options he proposes:
These options can be combined in a variety of different ways, but not all combinations are possible. All use the Basic Model as a base. Linked Lists can optionally be combined with any possible combination. Possible combos:
Therefore, to implement these combinations, I propose that we provide: a) a new set of kwargs representing these options that will be passed to Vertex
methods create
, delete
, save
; and b) a subclass of Vertex
, VersionedVertex
that is versioned by default.
The kwargs and defaults would be as follows:
versioned=False
linked=False
overload_current=False
overload_initial=False
current_state=False
In the case that restricted combinations occur, kwargs will be treated as follows:
versioned=False
overrides all other args
overload_current=True
overrides current_state=True
if overload_current and overload_initial:
raise Exception
What else do we need? Feedback?
It's time to update Goblin's property management to improve integration with Titan.
To review there are currently a wide variety of properties that map between Python and Titan as follows:
Goblin | Python 2/3 | Titan |
---|---|---|
String | String | String |
Short | Int | Short |
Integer | Long/Integer | Integer |
Positive Integer | Long/Integer | Integer |
Long | Long/Integer | Long |
Positive Long | Long/Integer | Long |
Double | Float | Double |
Float | Float | Float |
UUID | String | String |
Decimal | Decimal | Decimal/Precision (3/6 dig) |
Dictionary | Dictionary | N/A |
List | List | N/A |
URL | String | String |
DateTimeNaive | Datetime | Date? |
DateTime | Datetime | Date? |
Boolean | Boolean | Boolean |
Slug | String | String |
IPV4/6/4w/6 | String | String |
Most of these properties map simply and only needed to be tested against a graph db with appropriate schema definition. However, there are a few things to consider:
You may note that dictionary and list no longer have corresponding data types in Titan, instead, you can define a property data type as well as a cardinality--single, list, or set. We'll need to provide an API that allows the user to set the cardinality.
Furthermore, the current Titan native data types make a distinction between 3/6 digit decimals (Decimal and Precision), and we should probably reflect this either by providing kwarg options or separate property classes.
The slug property doesn't do any slugification, something that may be of interest...
Also, the geoshape type will need to be implemented.
I haven't double checked yet how Titan handles the Date data type. Mogwai sent unix timestamps. Any input on the API, needed properties, anything...?
On line 433, the _simple_traversal method does not return anything. It definitely seems like it should return the future_results variable that has nothing assigned to it
future_results = connection.execute_query(
'g.e(id).%s()' % operation, {'id': self.id},
handler=edge_traversal_handler, **kwargs)
return
We are seeking input from the community about the need for goblin to support python 2.7. Are you using goblin with python2? If you are using, or planning to use, goblin, please comment below and let us know what version of python you are using.
We are seriously considering dropping support for python 2.7 for several reasons, including (but not limited to) the following:
I am a former Mogwai user and am excited to try out goblin. When I pip-ed into my python environment, discovered the VERSION file was not present. I added it manually and am moving forward, but thought you should know.
Upon further examination, it appears all of the files considered Unix executables - edge.groovy, vertex.groovy, LICENSE, Makefile, MANIFEST.in ... are all missing.
Here is a simple code sample:
from goblin import properties
from goblin.models import Vertex, Edge, V
from goblin.connection import setup, close_global_pool
from datetime import datetime
class myVx(Vertex):
someString = properties.String()
someDateTime = properties.DateTime()
setup("localhost")
myDT = datetime.now()
myNewVx = myVx.create(someString = "Hello World",
someDateTime = myDT)
I was surprised when I got this exception:
Traceback (most recent call last):
File "vxtest.py", line 17, in <module>
someDateTime = myDT)
File "/some/path/.virtualenvs/goblin/lib/python3.5/site-packages/goblin/models/element.py", line 258, in create
return cls(*args, **kwargs).save(**query_kwargs)
File "/some/path/.virtualenvs/goblin/lib/python3.5/site-packages/goblin/models/element.py", line 69, in __init__
value = prop.to_python(value)
File "/some/path.virtualenvs/goblin/lib/python3.5/site-packages/goblin/properties/properties.py", line 227, in to_python
float(value)).replace(tzinfo=utc)
TypeError: float() argument must be a string or a number, not 'datetime.datetime'
When I look at the relevant block of code in properties.py:
def to_python(self, value):
try:
if isinstance(value, datetime.datetime):
if value.tzinfo == utc:
return self.validator(value) # .astimezone(tz=utc)
else:
return self.validator(value).astimezone(tz=utc)
except Exception as e: # pragma: no cover
# this shouldn't happen unless the validator has changed
pass
return datetime.datetime.utcfromtimestamp(
float(value)).replace(tzinfo=utc)
If I expose the exception that is actually being thrown:
File "/some/path/.virtualenvs/goblin/lib/python3.5/site-packages/goblin/properties/validators.py", line 170, in __call__
self.message.format(value), code=self.code)
goblin.exceptions.ValidationError: Not a valid UTC DateTime: 2016-03-21 17:08:39.149907
So, looking at that block of code, I end up in this try/except chain:
# print_("Got value with timezone: {} - {}".format(value, value.tzinfo))
try:
value = value.astimezone(tz=utc)
except ValueError: # last ditch effort
try:
value = value.replace(tz=utc)
except (AttributeError, TypeError):
raise ValidationError(
self.message.format(value), code=self.code)
except AttributeError: # pragma: no cover
# This should never happen, unless it isn't a datetime object
raise ValidationError(self.message % (value, ), code=self.code)
value.astimezone(tz=utc) fails with the exception:
ValueError: astimezone() cannot be applied to a naive datetime
So that drops to value.replace(tz=utc), which fails with the exception:
TypeError: 'tz' is an invalid keyword argument for this function
And that is probably because the keyword is supposed to be tzinfo .
All of that analysis makes me wonder if the default behavior, when passing in a timezone-naive datetime, should be to assume UTC, or should it assume "Local Timezone" before stashing it in the database? Perhaps a warning could be issued?
FWIW, to default to the local timezone I, usually do this quick and dirty approach:
from tzlocal import get_localzone
from datetime import datetime
myDT = datetime.now()
myDT = myDT.replace(tzinfo = get_localzone())
... and when I add that to my example above, the new vertex is successfully created (because it bypasses the faulty validator code).
Before I add the new functionality for schema and indices management, I think we should provide some simple documentation that covers goblin's core functionality, both to help our current users get going and attract new users/contributors. The first step in getting going will be updating the gremlinclient docs, as I would like to provide good cross referencing to help goblin users understand how to customize their goblin app. This will be relatively quick, but the goblin docs will be a bit more work. Before I put the time in, I want to make sure we are all on the same page.
I plan on using Sphinx to generate the documentation and host the docs on readthedocs, pretty standard, but there are other options for hosting as well...I usually use the alabaster theme, but I am open to suggestions here...
Relevant API documentation will be auto-generated by Sphinx from the docstrings, but I think it is important to include hand written docs with examples as well. I was thinking a basic structure like this:
Comments or suggestions @jsenecal @leifurhauks?
Calling Vertex.get with a nonexistent ID doesn't raise a DoesNotExist as expected.
When I run this script:
https://gist.github.com/leifurhauks/34c8e4d28025cd579af6
I get the following output:
leifurpc% python silly_script.py
INFO:__main__:set up goblin connection
INFO:__main__:Created person: Person(label=person, id=40972480, values={'name': 'Margaretta Heathcote DDS', 'url': 'http://www.jenkins.info/', 'email': '[email protected]'})
INFO:__main__:ID: 40972480
INFO:__main__:Got a copy of person by id: Person(label=person, id=40972480, values={'name': 'Margaretta Heathcote DDS', 'url': 'http://www.jenkins.info/', 'email': '[email protected]'})
ERROR:asyncio:Exception in callback Stream._read.<locals>.parser.<locals>.<lambda>(<Task finishe...> result=None>) at /home/lasgeirsson/.virtualenvs/noss-graphdb/lib/python3.5/site-packages/gremlinclient/connection.py:330
handle: <Handle Stream._read.<locals>.parser.<locals>.<lambda>(<Task finishe...> result=None>) at /home/lasgeirsson/.virtualenvs/noss-graphdb/lib/python3.5/site-packages/gremlinclient/connection.py:330>
Traceback (most recent call last):
File "/usr/lib/python3.5/asyncio/events.py", line 125, in _run
self._callback(*self._args)
File "/home/lasgeirsson/.virtualenvs/noss-graphdb/lib/python3.5/site-packages/gremlinclient/connection.py", line 330, in <lambda>
lambda f: future.set_exception(e))
NameError: free variable 'e' referenced before assignment in enclosing scope
Using the following model definition:
class Foo(models.Vertex):
foo = properties.String(db_field='bar')
I have a 'foo' vertex in the database already with 'bar' = 'testing123'.
The following retrieves it and correctly prints 'testing123':
async def foo_property():
foo = await Foo.get('4312')
print(foo.bar)
If I now change foo.bar and save it:
async def set_foo_property(new_value):
foo = await Foo.get('4312')
foo.bar = new_value
await foo.save()
The foo_property
coroutine now prints 'different value' as expected. But now the 'bar' property appears to be mapped to a new property, 'foo_bar' in titan:
gremlin> g.V(4312).properties()
==>vp[bar->testing123]
==>vp[foo_bar->different value]
gremlin>
I just started trying out goblin as my python binding to titan and with it the tinkerpop3 stack. I tried out a few simple operations and was able to get it working fairly easily. I was just about to start writing (re-writing from py2neo in fact) my models to use goblin, but ran into this error. It seems to be coming from gremlin, and I slimmed down my code to the essentials to test it out.
Here is the code:
from goblin import properties
from goblin import connection
from goblin.models import Vertex
from tornado import gen
from tornado.ioloop import IOLoop
class TestVertex(Vertex):
prop1 = properties.String()
@gen.coroutine
def go():
yield TestVertex.create(prop1='A')
yield TestVertex.create(prop1='B')
stream = yield TestVertex.all()
vertices = yield stream.read()
for vertex in vertices:
print(vertex)
if __name__ == '__main__':
connection.setup('ws://localhost:8182')
loop = IOLoop.current()
try:
print("start")
loop.run_sync(go)
print("end")
except Exception as err:
print("Caught an errror: {}".format(err))
raise err
finally:
connection.tear_down()
loop.close()
And here is the error:
$ python test.py
start
Caught an errror: 597 No such property: V for class: org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource
Traceback (most recent call last):
File "test.py", line 32, in <module>
raise err
File "test.py", line 28, in <module>
loop.run_sync(go)
File "/home/tbeck/.virtualenvs/goblin/lib/python3.5/site-packages/tornado/ioloop.py", line 453, in run_sync
return future_cell[0].result()
File "/home/tbeck/.virtualenvs/goblin/lib/python3.5/site-packages/tornado/concurrent.py", line 232, in result
raise_exc_info(self._exc_info)
File "<string>", line 3, in raise_exc_info
File "/home/tbeck/.virtualenvs/goblin/lib/python3.5/site-packages/tornado/gen.py", line 1014, in run
yielded = self.gen.throw(*exc_info)
File "test.py", line 18, in go
vertices = yield stream.read()
File "/home/tbeck/.virtualenvs/goblin/lib/python3.5/site-packages/tornado/gen.py", line 1008, in run
value = future.result()
File "/home/tbeck/.virtualenvs/goblin/lib/python3.5/site-packages/tornado/concurrent.py", line 232, in result
raise_exc_info(self._exc_info)
File "<string>", line 3, in raise_exc_info
RuntimeError: 597 No such property: V for class: org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource
I need some of these basic ORM type methods to be working well before I can use goblin. Is this a problem with my implementation or with goblin's interface to gremlin?
I'm creating this issue to track what still needs to be done for Goblin to have full support of multi-properties. In Titan, this means properties with cardinality LIST or SET.
Currently, updating a multi-property from Goblin appends the new value. Deleting values from a multi-property doesn't seem to be possible yet.
The all() method results in a value of None from the stream future if no results are found.
Here is an example piece of code:
from goblin import properties
from goblin import connection
from goblin.models import Vertex, Edge
import inflection
import asyncio
from tornado.platform.asyncio import AsyncIOMainLoop
@asyncio.coroutine
def drop():
stream = yield from Vertex.all()
vertices = yield from stream.read()
for vertex in vertices:
yield from vertex.delete()
if __name__ == '__main__':
connection.setup('ws://localhost:8182', future_class=asyncio.Future)
AsyncIOMainLoop().install()
loop = asyncio.get_event_loop()
try:
print("dropping")
loop.run_until_complete(drop())
loop.run_until_complete(drop())
print("ending")
except Exception as err:
print("Caught an errror: {}".format(err))
raise err
finally:
connection.tear_down()
loop.close()
Executing this code will result in the follow exception:
TypeError: 'NoneType' object is not iterable
The result from the all method's stream should be an empty list so that an iteration over results where no matches are found does not raise an exception
I've found that the all() method raises an exception dependably when there are more than 64 vertices of one type in the graph db. I stripped my code down to the bare minimum and created an executable python script to demonstrate the issue
Here is the source code
#!/usr/bin/env python
import asyncio
from tornado.platform.asyncio import AsyncIOMainLoop
from goblin import properties, connection
from goblin.models import Vertex
class MyVertex(Vertex):
prop1 = properties.Integer()
connection.setup('ws://localhost:8182', future_class=asyncio.Future)
AsyncIOMainLoop().install()
@asyncio.coroutine
def clear():
result = yield from connection.execute_query('g.V().drop().iterate()')
stream = yield from result.read()
return stream
@asyncio.coroutine
def create(i):
result = yield from MyVertex.create(prop1=i)
return result
@asyncio.coroutine
def find():
result = yield from MyVertex.all()
stream = yield from result.read()
return stream
loop = asyncio.get_event_loop()
def smash(n):
print("Clearing old vertices")
loop.run_until_complete(clear())
print("Smashing {} vertices".format(n))
for i in range(n):
loop.run_until_complete(create(i))
loop.run_until_complete(find())
n = 1
while True:
smash(n)
n += 1
And here is the output:
$ bin/smash
Clearing old vertices
Smashing 1 vertices
Clearing old vertices
Smashing 2 vertices
Clearing old vertices
Smashing 3 vertices
Clearing old vertices
Smashing 4 vertices
Clearing old vertices
Smashing 5 vertices
Clearing old vertices
Smashing 6 vertices
Clearing old vertices
Smashing 7 vertices
Clearing old vertices
Smashing 8 vertices
Clearing old vertices
Smashing 9 vertices
Clearing old vertices
Smashing 10 vertices
Clearing old vertices
Smashing 11 vertices
Clearing old vertices
Smashing 12 vertices
Clearing old vertices
Smashing 13 vertices
Clearing old vertices
Smashing 14 vertices
Clearing old vertices
Smashing 15 vertices
Clearing old vertices
Smashing 16 vertices
Clearing old vertices
Smashing 17 vertices
Clearing old vertices
Smashing 18 vertices
Clearing old vertices
Smashing 19 vertices
Clearing old vertices
Smashing 20 vertices
Clearing old vertices
Smashing 21 vertices
Clearing old vertices
Smashing 22 vertices
Clearing old vertices
Smashing 23 vertices
Clearing old vertices
Smashing 24 vertices
Clearing old vertices
Smashing 25 vertices
Clearing old vertices
Smashing 26 vertices
Clearing old vertices
Smashing 27 vertices
Clearing old vertices
Smashing 28 vertices
Clearing old vertices
Smashing 29 vertices
Clearing old vertices
Smashing 30 vertices
Clearing old vertices
Smashing 31 vertices
Clearing old vertices
Smashing 32 vertices
Clearing old vertices
Smashing 33 vertices
Clearing old vertices
Smashing 34 vertices
Clearing old vertices
Smashing 35 vertices
Clearing old vertices
Smashing 36 vertices
Clearing old vertices
Smashing 37 vertices
Clearing old vertices
Smashing 38 vertices
Clearing old vertices
Smashing 39 vertices
Clearing old vertices
Smashing 40 vertices
Clearing old vertices
Smashing 41 vertices
Clearing old vertices
Smashing 42 vertices
Clearing old vertices
Smashing 43 vertices
Clearing old vertices
Smashing 44 vertices
Clearing old vertices
Smashing 45 vertices
Clearing old vertices
Smashing 46 vertices
Clearing old vertices
Smashing 47 vertices
Clearing old vertices
Smashing 48 vertices
Clearing old vertices
Smashing 49 vertices
Clearing old vertices
Smashing 50 vertices
Clearing old vertices
Smashing 51 vertices
Clearing old vertices
Smashing 52 vertices
Clearing old vertices
Smashing 53 vertices
Clearing old vertices
Smashing 54 vertices
Clearing old vertices
Smashing 55 vertices
Clearing old vertices
Smashing 56 vertices
Clearing old vertices
Smashing 57 vertices
Clearing old vertices
Smashing 58 vertices
Clearing old vertices
Smashing 59 vertices
Clearing old vertices
Smashing 60 vertices
Clearing old vertices
Smashing 61 vertices
Clearing old vertices
Smashing 62 vertices
Clearing old vertices
Smashing 63 vertices
Clearing old vertices
Smashing 64 vertices
Clearing old vertices
Smashing 65 vertices
Traceback (most recent call last):
File "bin/smash", line 43, in <module>
smash(n)
File "bin/smash", line 39, in smash
loop.run_until_complete(find())
File "/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/asyncio/base_events.py", line 337, in run_until_complete
return future.result()
File "/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/asyncio/futures.py", line 274, in result
raise self._exception
File "/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/asyncio/tasks.py", line 241, in _step
result = coro.throw(exc)
File "bin/smash", line 29, in find
stream = yield from result.read()
File "/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/asyncio/futures.py", line 358, in __iter__
yield self # This tells Task to wait for completion.
File "/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/asyncio/tasks.py", line 290, in _wakeup
future.result()
File "/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/asyncio/futures.py", line 274, in result
raise self._exception
RuntimeError: 599 Error during serialization: Could not execute operation due to backend exception (through reference chain: java.util.ArrayList[0]
Regardless of how many
This is a serious issue because it is preventing me from using goblin at the moment until this has been resolved.
Hi guys
Do you plan to add WTForms support?
It would probably take only small modifications as WTForms already has a populate_obj()
function.
I included a link to screenshots I made to explain how WTForms already works with the ODM MongoEngine, and how it could work with Goblin.
I think Goblin could be one of the first OGM to be interfaced directly to forms,
I don't think I'm enough skilled to modify Goblin codebase myself thought.
I included screenshots with the most complicated of scenarios (object that contains objects that contains objects)
In this example it is a City containing two Zoos containing Animals
The screenshots are here:
note:
the mongoengine code shown must use mongoengine==0.8.7 and pymongo==2.8 to work
Is there a way to create a vertex sans label?
I've tried overriding Vertex's get_label in order to return None or '' but those both threw exceptions. I'm using goblin with an existing database which does not have any vertex labels (and has a strict schema which does not permit label creation on the fly).
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.