Package: simple-graph-sqlite
AboutThis is thePyPIpackage of thesimple-graphimplementation inPython, which is a simplegraph databaseinSQLite, inspired by "SQLite as a document database".Build and TestHow togenerate the distribution archiveand confirm it ontest.pypi.org, also based on thepypa/sampleproject:rm-rfbuilddistsrc/simple_graph_sqlite.egg-info
python-mbuild
python-mtwineupload--repositorytestpypidist/*Create a virtual environment for the test package, activate it, pull fromtest.pypi.org(the--extra-index-urlis necessary since thegraphvizand/orJinja2dependencies may not be in the test archive), and confirm the package is available:$pipinstall-ihttps://test.pypi.org/simple/--extra-index-urlhttps://pypi.org/simplesimple-graph-sqlitegraphviz==0.16Jinja2==3.1.2
$python
Python3.6.13|Anaconda,Inc.|(default,Jun42021,14:25:59)[GCC7.5.0]onlinux
Type"help","copyright","credits"or"license"formoreinformation.
>>>fromsimple_graph_sqliteimportdatabaseasdbWith the test package installed, updatePYTHONPATHto include./testsand runpytestfrom the root of this repository. If the tests pass, rebuild and push topypi.org:rm-rfbuilddistsrc/simple_graph_sqlite.egg-info
python-mbuild
python-mtwineupload--repositorypypidist/*StructureTheschemaconsists of just two structures:Nodes - these are anyjsonobjects, with the only constraint being that they each contain a uniqueidvalueEdges - these are pairs of nodeidvalues, specifying the direction, with an optional json object as connection propertiesThere are also traversal functions as native SQLiteCommon Table Expressions:Both directionsInboundOutboundApplicationsSocial networksInterest maps/recommendation findersTo-do / task listsBug trackersCustomer relationship management (CRM)Gantt chartUsageInstallation RequirementsSQLite, version 3.31.0 or higher; get the latest source or precompiled binaries from theSQLite Download PageGraphvizfor visualization (download page,installation procedure for Windows)Jinja2for the search and traversal templatesBasic FunctionsThedatabase scriptprovides convenience functions foratomic transactionsto add, delete, connect, and search for nodes.Any single node or path of nodes can also be depicted graphically by using thevisualizefunction within the database script to generatedotfiles, which in turn can be converted to images with Graphviz.ExampleDropping into a python shell, we can create,upsert, and connect people from the early days ofApple Computer. The resulting database will be saved to a SQLite file namedapple.sqlite:>>> apple = "apple.sqlite"
>>> from simple_graph_sqlite import database as db
>>> db.initialize(apple)
>>> db.atomic(apple, db.add_node({'name': 'Apple Computer Company', 'type':['company', 'start-up'], 'founded': 'April 1, 1976'}, 1))
>>> db.atomic(apple, db.add_node({'name': 'Steve Wozniak', 'type':['person','engineer','founder']}, 2))
>>> db.atomic(apple, db.add_node({'name': 'Steve Jobs', 'type':['person','designer','founder']}, 3))
>>> db.atomic(apple, db.add_node({'name': 'Ronald Wayne', 'type':['person','administrator','founder']}, 4))
>>> db.atomic(apple, db.add_node({'name': 'Mike Markkula', 'type':['person','investor']}, 5))
>>> db.atomic(apple, db.connect_nodes(2, 1, {'action': 'founded'}))
>>> db.atomic(apple, db.connect_nodes(3, 1, {'action': 'founded'}))
>>> db.atomic(apple, db.connect_nodes(4, 1, {'action': 'founded'}))
>>> db.atomic(apple, db.connect_nodes(5, 1, {'action': 'invested', 'equity': 80000, 'debt': 170000}))
>>> db.atomic(apple, db.connect_nodes(1, 4, {'action': 'divested', 'amount': 800, 'date': 'April 12, 1976'}))
>>> db.atomic(apple, db.connect_nodes(2, 3))
>>> db.atomic(apple, db.upsert_node(2, {'nickname': 'Woz'}))There are also bulk operations, to insert and connect lists of nodes in one transaction.The nodes can be searched by their ids:>>> db.atomic(apple, db.find_node(1))
{'name': 'Apple Computer Company', 'type': ['company', 'start-up'], 'founded': 'April 1, 1976', 'id': 1}Searches can also use combinations of other attributes, both as strict equality, or usingLIKEin combination with a trailing%for "starts with" or%at both ends for "contains":>>> db.atomic(apple, db.find_nodes([db._generate_clause('name', predicate='LIKE')], ('Steve%',)))
[{'name': 'Steve Wozniak', 'type': ['person', 'engineer', 'founder'], 'id': 2, 'nickname': 'Woz'}, {'name': 'Steve Jobs', 'type': ['person', 'designer', 'founder'], 'id': 3}]
>>> db.atomic(apple, db.find_nodes([db._generate_clause('name', predicate='LIKE'), db._generate_clause('name', predicate='LIKE', joiner='OR')], ('%Woz%', '%Markkula',)))
[{'name': 'Steve Wozniak', 'type': ['person', 'engineer', 'founder'], 'id': 2, 'nickname': 'Woz'}, {'name': 'Mike Markkula', 'type': ['person', 'investor'], 'id': 5}]More complex queries to introspect the json body, using thesqlite json_tree() function, are also possible, such as this query for every node whosetypearray contains the valuefounder:>>> db.atomic(apple, db.find_nodes([db._generate_clause('type', tree=True)], ('founder',), tree_query=True, key='type'))
[{'name': 'Steve Wozniak', 'type': ['person', 'engineer', 'founder'], 'id': 2, 'nickname': 'Woz'}, {'name': 'Steve Jobs', 'type': ['person', 'designer', 'founder'], 'id': 3}, {'name': 'Ronald Wayne', 'type': ['person', 'administrator', 'founder'], 'id': 4}]See the_generate_clause()and_generate_query()functions indatabase.pyfor usage hints.Paths through the graph can be discovered with a starting node id, and an optional ending id; the default neighbor expansion is nodes connected nodes in either direction, but that can changed by specifying eitherfind_outbound_neighborsorfind_inbound_neighborsinstead:>>> db.traverse(apple, 2, 3)
['2', '1', '3']
>>> db.traverse(apple, 4, 5)
['4', '1', '2', '3', '5']
>>> db.traverse(apple, 5, neighbors_fn=db.find_inbound_neighbors)
['5']
>>> db.traverse(apple, 5, neighbors_fn=db.find_outbound_neighbors)
['5', '1', '4']
>>> db.traverse(apple, 5, neighbors_fn=db.find_neighbors)
['5', '1', '2', '3', '4']Any path or list of nodes can rendered graphically by using thevisualizefunction. This command producesdotfiles, which are also rendered as images with Graphviz:>>> from visualizers import graphviz_visualize
>>> graphviz_visualize(apple, 'apple.dot', [4, 1, 5])Theresulting text filealso comes with an associated image (the default ispng, but that can be changed by supplying a different value to theformatparameter)The default options include every key/value pair (excluding the id) in the node and edge objects, and there are display options to help refine what is produced:>>> graphviz_visualize(apple, 'apple.dot', [4, 1, 5], exclude_node_keys=['type'], hide_edge_key=True)Theresulting dot filecan be edited further as needed; thedot guidehas more options and examples.