python driver psycopg3 (#1793)
* update for psycopg3
* set a default argparse namespace in case tests are run in such a way that argparse is bypassed.
diff --git a/.gitignore b/.gitignore
index e03dd04..a8e809d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,3 +9,7 @@
*.dylib
age--*.*.*.sql
!age--*--*sql
+__pycache__
+**/__pycache__
+
+drivers/python/build
diff --git a/drivers/python/age/__init__.py b/drivers/python/age/__init__.py
index 5d0e31e..6382690 100644
--- a/drivers/python/age/__init__.py
+++ b/drivers/python/age/__init__.py
@@ -13,6 +13,7 @@
# specific language governing permissions and limitations
# under the License.
+import psycopg.conninfo as conninfo
from . import age
from .age import *
from .models import *
@@ -23,10 +24,13 @@
return VERSION.VERSION
-def connect(dsn=None, graph=None, connection_factory=None, cursor_factory=None, **kwargs):
- ag = Age()
- ag.connect(dsn=dsn, graph=graph, connection_factory=connection_factory, cursor_factory=cursor_factory, **kwargs)
- return ag
+def connect(dsn=None, graph=None, connection_factory=None, cursor_factory=ClientCursor, **kwargs):
+
+ dsn = conninfo.make_conninfo('' if dsn is None else dsn, **kwargs)
+
+ ag = Age()
+ ag.connect(dsn=dsn, graph=graph, connection_factory=connection_factory, cursor_factory=cursor_factory, **kwargs)
+ return ag
# Dummy ResultHandler
rawPrinter = DummyResultHandler()
diff --git a/drivers/python/age/age.py b/drivers/python/age/age.py
index 40ad0c2..2d98e3f 100644
--- a/drivers/python/age/age.py
+++ b/drivers/python/age/age.py
@@ -13,13 +13,14 @@
# specific language governing permissions and limitations
# under the License.
-import re
-import psycopg2
-from psycopg2 import errors
-from psycopg2 import extensions as ext
-from psycopg2 import sql
+import re
+import psycopg
+from psycopg.types import TypeInfo
+from psycopg.adapt import Loader
+from psycopg import sql
+from psycopg.client_cursor import ClientCursor
from .exceptions import *
-from .builder import ResultHandler , parseAgeValue, newResultHandler
+from .builder import parseAgeValue
_EXCEPTION_NoConnection = NoConnection()
@@ -27,26 +28,36 @@
WHITESPACE = re.compile('\s')
-def setUpAge(conn:ext.connection, graphName:str):
+
+class AgeDumper(psycopg.adapt.Dumper):
+ def dump(self, obj: Any) -> bytes | bytearray | memoryview:
+ pass
+
+
+class AgeLoader(psycopg.adapt.Loader):
+ def load(self, data: bytes | bytearray | memoryview) -> Any | None:
+ return parseAgeValue(data.decode('utf-8'))
+
+
+def setUpAge(conn:psycopg.connection, graphName:str):
with conn.cursor() as cursor:
cursor.execute("LOAD 'age';")
cursor.execute("SET search_path = ag_catalog, '$user', public;")
- cursor.execute("SELECT typelem FROM pg_type WHERE typname='_agtype'")
- oid = cursor.fetchone()[0]
- if oid == None :
- raise AgeNotSet()
+ ag_info = TypeInfo.fetch(conn, 'agtype')
- AGETYPE = ext.new_type((oid,), 'AGETYPE', parseAgeValue)
- ext.register_type(AGETYPE)
- # ext.register_adapter(Path, marshalAgtValue)
+ if not ag_info:
+ raise AgeNotSet()
+
+ conn.adapters.register_loader(ag_info.oid, AgeLoader)
+ conn.adapters.register_loader(ag_info.array_oid, AgeLoader)
# Check graph exists
if graphName != None:
checkGraphCreated(conn, graphName)
# Create the graph, if it does not exist
-def checkGraphCreated(conn:ext.connection, graphName:str):
+def checkGraphCreated(conn:psycopg.connection, graphName:str):
with conn.cursor() as cursor:
cursor.execute(sql.SQL("SELECT count(*) FROM ag_graph WHERE name={graphName}").format(graphName=sql.Literal(graphName)))
if cursor.fetchone()[0] == 0:
@@ -54,7 +65,7 @@
conn.commit()
-def deleteGraph(conn:ext.connection, graphName:str):
+def deleteGraph(conn:psycopg.connection, graphName:str):
with conn.cursor() as cursor:
cursor.execute(sql.SQL("SELECT drop_graph({graphName}, true);").format(graphName=sql.Literal(graphName)))
conn.commit()
@@ -82,7 +93,7 @@
stmtArr.append(");")
return "".join(stmtArr)
-def execSql(conn:ext.connection, stmt:str, commit:bool=False, params:tuple=None) -> ext.cursor :
+def execSql(conn:psycopg.connection, stmt:str, commit:bool=False, params:tuple=None) -> psycopg.cursor :
if conn == None or conn.closed:
raise _EXCEPTION_NoConnection
@@ -101,14 +112,14 @@
raise SqlExecutionError("Execution ERR[" + str(cause) +"](" + stmt +")", cause)
-def querySql(conn:ext.connection, stmt:str, params:tuple=None) -> ext.cursor :
+def querySql(conn:psycopg.connection, stmt:str, params:tuple=None) -> psycopg.cursor :
return execSql(conn, stmt, False, params)
# Execute cypher statement and return cursor.
# If cypher statement changes data (create, set, remove),
# You must commit session(ag.commit())
# (Otherwise the execution cannot make any effect.)
-def execCypher(conn:ext.connection, graphName:str, cypherStmt:str, cols:list=None, params:tuple=None) -> ext.cursor :
+def execCypher(conn:psycopg.connection, graphName:str, cypherStmt:str, cols:list=None, params:tuple=None) -> psycopg.cursor :
if conn == None or conn.closed:
raise _EXCEPTION_NoConnection
@@ -117,7 +128,7 @@
cypherStmt = cypherStmt.replace("\n", "")
cypherStmt = cypherStmt.replace("\t", "")
cypher = str(cursor.mogrify(cypherStmt, params))
- cypher = cypher[2:len(cypher)-1]
+ cypher = cypher.strip()
preparedStmt = "SELECT * FROM age_prepare_cypher({graphName},{cypherStmt})"
@@ -145,12 +156,12 @@
raise SqlExecutionError("Execution ERR[" + str(cause) +"](" + stmt +")", cause)
-def cypher(cursor:ext.cursor, graphName:str, cypherStmt:str, cols:list=None, params:tuple=None) -> ext.cursor :
+def cypher(cursor:psycopg.cursor, graphName:str, cypherStmt:str, cols:list=None, params:tuple=None) -> psycopg.cursor :
#clean up the string for mogrification
cypherStmt = cypherStmt.replace("\n", "")
cypherStmt = cypherStmt.replace("\t", "")
cypher = str(cursor.mogrify(cypherStmt, params))
- cypher = cypher[2:len(cypher)-1]
+ cypher = cypher.strip()
preparedStmt = "SELECT * FROM age_prepare_cypher({graphName},{cypherStmt})"
cursor.execute(sql.SQL(preparedStmt).format(graphName=sql.Literal(graphName),cypherStmt=sql.Literal(cypher)))
@@ -159,22 +170,22 @@
cursor.execute(stmt)
-# def execCypherWithReturn(conn:ext.connection, graphName:str, cypherStmt:str, columns:list=None , params:tuple=None) -> ext.cursor :
+# def execCypherWithReturn(conn:psycopg.connection, graphName:str, cypherStmt:str, columns:list=None , params:tuple=None) -> psycopg.cursor :
# stmt = buildCypher(graphName, cypherStmt, columns)
# return execSql(conn, stmt, False, params)
-# def queryCypher(conn:ext.connection, graphName:str, cypherStmt:str, columns:list=None , params:tuple=None) -> ext.cursor :
+# def queryCypher(conn:psycopg.connection, graphName:str, cypherStmt:str, columns:list=None , params:tuple=None) -> psycopg.cursor :
# return execCypherWithReturn(conn, graphName, cypherStmt, columns, params)
class Age:
def __init__(self):
- self.connection = None # psycopg2 connection]
+ self.connection = None # psycopg connection]
self.graphName = None
# Connect to PostgreSQL Server and establish session and type extension environment.
- def connect(self, graph:str=None, dsn:str=None, connection_factory=None, cursor_factory=None, **kwargs):
- conn = psycopg2.connect(dsn, connection_factory, cursor_factory, **kwargs)
+ def connect(self, graph:str=None, dsn:str=None, connection_factory=None, cursor_factory=ClientCursor, **kwargs):
+ conn = psycopg.connect(dsn, cursor_factory=cursor_factory, **kwargs)
setUpAge(conn, graph)
self.connection = conn
self.graphName = graph
@@ -194,21 +205,21 @@
def rollback(self):
self.connection.rollback()
- def execCypher(self, cypherStmt:str, cols:list=None, params:tuple=None) -> ext.cursor :
+ def execCypher(self, cypherStmt:str, cols:list=None, params:tuple=None) -> psycopg.cursor :
return execCypher(self.connection, self.graphName, cypherStmt, cols=cols, params=params)
- def cypher(self, cursor:ext.cursor, cypherStmt:str, cols:list=None, params:tuple=None) -> ext.cursor :
+ def cypher(self, cursor:psycopg.cursor, cypherStmt:str, cols:list=None, params:tuple=None) -> psycopg.cursor :
return cypher(cursor, self.graphName, cypherStmt, cols=cols, params=params)
- # def execSql(self, stmt:str, commit:bool=False, params:tuple=None) -> ext.cursor :
+ # def execSql(self, stmt:str, commit:bool=False, params:tuple=None) -> psycopg.cursor :
# return execSql(self.connection, stmt, commit, params)
- # def execCypher(self, cypherStmt:str, commit:bool=False, params:tuple=None) -> ext.cursor :
+ # def execCypher(self, cypherStmt:str, commit:bool=False, params:tuple=None) -> psycopg.cursor :
# return execCypher(self.connection, self.graphName, cypherStmt, commit, params)
- # def execCypherWithReturn(self, cypherStmt:str, columns:list=None , params:tuple=None) -> ext.cursor :
+ # def execCypherWithReturn(self, cypherStmt:str, columns:list=None , params:tuple=None) -> psycopg.cursor :
# return execCypherWithReturn(self.connection, self.graphName, cypherStmt, columns, params)
- # def queryCypher(self, cypherStmt:str, columns:list=None , params:tuple=None) -> ext.cursor :
- # return queryCypher(self.connection, self.graphName, cypherStmt, columns, params)
+ # def queryCypher(self, cypherStmt:str, columns:list=None , params:tuple=None) -> psycopg.cursor :
+ # return queryCypher(self.connection, self.graphName, cypherStmt, columns, params)
diff --git a/drivers/python/age/builder.py b/drivers/python/age/builder.py
index 0f4d711..a3815b8 100644
--- a/drivers/python/age/builder.py
+++ b/drivers/python/age/builder.py
@@ -18,8 +18,8 @@
from .gen.AgtypeVisitor import AgtypeVisitor
from .models import *
from .exceptions import *
-from antlr4 import *
-from antlr4.tree.Tree import *
+from antlr4 import InputStream, CommonTokenStream, ParserRuleContext
+from antlr4.tree.Tree import TerminalNode
from decimal import Decimal
resultHandler = None
@@ -42,7 +42,7 @@
try:
return resultHandler.parse(value)
except Exception as ex:
- raise AGTypeError(value)
+ raise AGTypeError(value, ex)
class Antlr4ResultHandler(ResultHandler):
diff --git a/drivers/python/age/exceptions.py b/drivers/python/age/exceptions.py
index 8c46e8e..3aa94f4 100644
--- a/drivers/python/age/exceptions.py
+++ b/drivers/python/age/exceptions.py
@@ -13,7 +13,7 @@
# specific language governing permissions and limitations
# under the License.
-from psycopg2.errors import *
+from psycopg.errors import *
class AgeNotSet(Exception):
def __init__(self, name):
diff --git a/drivers/python/age/networkx/age_to_networkx.py b/drivers/python/age/networkx/age_to_networkx.py
index 3a16aa3..4e27a54 100644
--- a/drivers/python/age/networkx/age_to_networkx.py
+++ b/drivers/python/age/networkx/age_to_networkx.py
@@ -14,13 +14,13 @@
# under the License.
from age import *
-import psycopg2
+import psycopg
import networkx as nx
from age.models import Vertex, Edge, Path
from .lib import *
-def age_to_networkx(connection: psycopg2.connect,
+def age_to_networkx(connection: psycopg.connect,
graphName: str,
G: None | nx.DiGraph = None,
query: str | None = None
@@ -28,7 +28,7 @@
"""
@params
---------------------
- connection - (psycopg2.connect) Connection object
+ connection - (psycopg.connect) Connection object
graphName - (str) Name of the graph
G - (networkx.DiGraph) Networkx directed Graph [optional]
query - (str) Cypher query [optional]
diff --git a/drivers/python/age/networkx/lib.py b/drivers/python/age/networkx/lib.py
index a4df088..3086586 100644
--- a/drivers/python/age/networkx/lib.py
+++ b/drivers/python/age/networkx/lib.py
@@ -14,15 +14,15 @@
# under the License.
from age import *
-import psycopg2
+import json
+import psycopg
import networkx as nx
-from psycopg2 import sql
-from psycopg2.extras import execute_values
+from psycopg import sql
from typing import Dict, Any, List, Set
from age.models import Vertex, Edge, Path
-def checkIfGraphNameExistInAGE(connection: psycopg2.connect,
+def checkIfGraphNameExistInAGE(connection: psycopg.connect,
graphName: str):
"""Check if the age graph exists"""
with connection.cursor() as cursor:
@@ -35,7 +35,7 @@
raise GraphNotFound(graphName)
-def getOidOfGraph(connection: psycopg2.connect,
+def getOidOfGraph(connection: psycopg.connect,
graphName: str) -> int:
"""Returns oid of a graph"""
try:
@@ -49,7 +49,7 @@
print(e)
-def get_vlabel(connection: psycopg2.connect,
+def get_vlabel(connection: psycopg.connect,
graphName: str):
node_label_list = []
oid = getOidOfGraph(connection, graphName)
@@ -65,7 +65,7 @@
return node_label_list
-def create_vlabel(connection: psycopg2.connect,
+def create_vlabel(connection: psycopg.connect,
graphName: str,
node_label_list: List):
"""create_vlabels from list if not exist"""
@@ -85,7 +85,7 @@
raise Exception(e)
-def get_elabel(connection: psycopg2.connect,
+def get_elabel(connection: psycopg.connect,
graphName: str):
edge_label_list = []
oid = getOidOfGraph(connection, graphName)
@@ -100,7 +100,7 @@
return edge_label_list
-def create_elabel(connection: psycopg2.connect,
+def create_elabel(connection: psycopg.connect,
graphName: str,
edge_label_list: List):
"""create_vlabels from list if not exist"""
@@ -169,7 +169,7 @@
return edge_label_list
-def addAllNodesIntoAGE(connection: psycopg2.connect, graphName: str, G: nx.DiGraph, node_label_list: Set):
+def addAllNodesIntoAGE(connection: psycopg.connect, graphName: str, G: nx.DiGraph, node_label_list: Set):
"""Add all node to AGE"""
try:
queue_data = {label: [] for label in node_label_list}
@@ -181,23 +181,29 @@
for label, rows in queue_data.items():
table_name = """%s."%s" """ % (graphName, label)
- insert_query = f"INSERT INTO {table_name} (properties) VALUES %s RETURNING id"
+ insert_query = f"INSERT INTO {table_name} (properties) VALUES (%s) RETURNING id"
cursor = connection.cursor()
- id_data[label] = execute_values(
- cursor, insert_query, rows, fetch=True)
+ cursor.executemany(insert_query, rows, returning=True)
+ ids = []
+ while True:
+ ids.append(cursor.fetchone()[0])
+ if not cursor.nextset():
+ break
+
+ id_data[label] = ids
connection.commit()
cursor.close()
id_data[label].reverse()
for node, data in G.nodes(data=True):
- data['properties']['__gid__'] = id_data[data['label']][-1][0]
+ data['properties']['__gid__'] = id_data[data['label']][-1]
id_data[data['label']].pop()
except Exception as e:
raise Exception(e)
-def addAllEdgesIntoAGE(connection: psycopg2.connect, graphName: str, G: nx.DiGraph, edge_label_list: Set):
+def addAllEdgesIntoAGE(connection: psycopg.connect, graphName: str, G: nx.DiGraph, edge_label_list: Set):
"""Add all edge to AGE"""
try:
queue_data = {label: [] for label in edge_label_list}
@@ -208,16 +214,16 @@
for label, rows in queue_data.items():
table_name = """%s."%s" """ % (graphName, label)
- insert_query = f"INSERT INTO {table_name} (start_id,end_id,properties) VALUES %s"
+ insert_query = f"INSERT INTO {table_name} (start_id,end_id,properties) VALUES (%s, %s, %s)"
cursor = connection.cursor()
- execute_values(cursor, insert_query, rows)
+ cursor.executemany(insert_query, rows)
connection.commit()
cursor.close()
except Exception as e:
raise Exception(e)
-def addAllNodesIntoNetworkx(connection: psycopg2.connect, graphName: str, G: nx.DiGraph):
+def addAllNodesIntoNetworkx(connection: psycopg.connect, graphName: str, G: nx.DiGraph):
"""Add all nodes to Networkx"""
node_label_list = get_vlabel(connection, graphName)
try:
@@ -235,7 +241,7 @@
print(e)
-def addAllEdgesIntoNetworkx(connection: psycopg2.connect, graphName: str, G: nx.DiGraph):
+def addAllEdgesIntoNetworkx(connection: psycopg.connect, graphName: str, G: nx.DiGraph):
"""Add All edges to Networkx"""
try:
edge_label_list = get_elabel(connection, graphName)
diff --git a/drivers/python/age/networkx/networkx_to_age.py b/drivers/python/age/networkx/networkx_to_age.py
index 90cee97..053193c 100644
--- a/drivers/python/age/networkx/networkx_to_age.py
+++ b/drivers/python/age/networkx/networkx_to_age.py
@@ -14,18 +14,18 @@
# under the License.
from age import *
-import psycopg2
+import psycopg
import networkx as nx
from .lib import *
-def networkx_to_age(connection: psycopg2.connect,
+def networkx_to_age(connection: psycopg.connect,
G: nx.DiGraph,
graphName: str):
"""
@params
-----------
- connection - (psycopg2.connect) Connection object
+ connection - (psycopg.connect) Connection object
G - (networkx.DiGraph) Networkx directed Graph
diff --git a/drivers/python/requirements.txt b/drivers/python/requirements.txt
index 81d1ef7..b0593b7 100644
--- a/drivers/python/requirements.txt
+++ b/drivers/python/requirements.txt
Binary files differ
diff --git a/drivers/python/samples/apache-age-agtypes.ipynb b/drivers/python/samples/apache-age-agtypes.ipynb
index 141ff3f..7055db9 100644
--- a/drivers/python/samples/apache-age-agtypes.ipynb
+++ b/drivers/python/samples/apache-age-agtypes.ipynb
@@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 12,
"id": "6301516b-a3fa-48e2-a95f-0f79903a6cdd",
"metadata": {},
"outputs": [],
@@ -22,10 +22,32 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 13,
"id": "adf14fe9-692c-4701-86d4-8c84fd53d966",
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "<class 'dict'> | {\"name\": \"Smith\", \"num\":123, \"yn\":true, \"bigInt\":123456789123456789123456789123456789::numeric} --> {'name': 'Smith', 'num': 123, 'yn': True, 'bigInt': Decimal('123456789123456789123456789123456789')}\n",
+ "<class 'list'> | [\"name\", \"Smith\", \"num\", 123, \"yn\", true, 123456789123456789123456789123456789.8888::numeric] --> ['name', 'Smith', 'num', 123, 'yn', True, Decimal('123456789123456789123456789123456789.8888')]\n",
+ "<class 'str'> | \"abcd\" --> abcd\n",
+ "<class 'int'> | 1234 --> 1234\n",
+ "<class 'float'> | 1234.56789 --> 1234.56789\n",
+ "<class 'decimal.Decimal'> | 12345678901234567890123456789123456789.789::numeric --> 12345678901234567890123456789123456789.789\n",
+ "<class 'decimal.Decimal'> | 12345678901234567890123456789123456789::numeric --> 12345678901234567890123456789123456789\n",
+ "<class 'bool'> | true --> True\n",
+ "<class 'float'> | -6.45161290322581e+46 --> -6.45161290322581e+46\n",
+ "<class 'decimal.Decimal'> | -123456789.99::numeric --> -123456789.99\n",
+ "<class 'decimal.Decimal'> | -6.45161290322581e+46::numeric --> -6.45161290322581E+46\n",
+ "<class 'int'> | 1234 --> 1234\n",
+ "<class 'float'> | NaN --> nan\n",
+ "<class 'float'> | -Infinity --> -inf\n",
+ "<class 'float'> | Infinity --> inf\n"
+ ]
+ }
+ ],
"source": [
"\n",
"mapStr = '{\"name\": \"Smith\", \"num\":123, \"yn\":true, \"bigInt\":123456789123456789123456789123456789::numeric}' \n",
@@ -57,10 +79,26 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 14,
"id": "8881804e-d71d-4704-b74c-376ed55be808",
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "<class 'int'> 2251799813685425\n",
+ "<class 'str'> Person\n",
+ "<class 'str'> Smith\n",
+ "<class 'int'> 123\n",
+ "<class 'float'> 384.23424\n",
+ "<class 'decimal.Decimal'> 123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789\n",
+ "<class 'decimal.Decimal'> 123456789123456789123456789123456789.12345\n",
+ "<class 'bool'> True\n",
+ "<class 'NoneType'> None\n"
+ ]
+ }
+ ],
"source": [
"vertexExp = '''{\"id\": 2251799813685425, \"label\": \"Person\", \n",
" \"properties\": {\"name\": \"Smith\", \"numInt\":123, \"numFloat\": 384.23424, \n",
@@ -82,10 +120,27 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 15,
"id": "0a70e467-9587-4eb7-b97d-895223009bcc",
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "<class 'int'> 2251799813685425\n",
+ "<class 'str'> Person\n",
+ "<class 'str'> Smith\n",
+ "<class 'int'> 2533274790396576\n",
+ "<class 'str'> workWith\n",
+ "<class 'int'> 3\n",
+ "<class 'decimal.Decimal'> 123456789123456789123456789.12345\n",
+ "<class 'int'> 2251799813685424\n",
+ "<class 'str'> Person\n",
+ "<class 'str'> Joe\n"
+ ]
+ }
+ ],
"source": [
"\n",
"pathExp = '''[{\"id\": 2251799813685425, \"label\": \"Person\", \"properties\": {\"name\": \"Smith\"}}::vertex, \n",
@@ -138,7 +193,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.9.2"
+ "version": "3.11.1"
}
},
"nbformat": 4,
diff --git a/drivers/python/samples/apache-age-basic.ipynb b/drivers/python/samples/apache-age-basic.ipynb
index f174963..59de8e4 100644
--- a/drivers/python/samples/apache-age-basic.ipynb
+++ b/drivers/python/samples/apache-age-basic.ipynb
@@ -5,9 +5,9 @@
"id": "2e236ac7-6f78-4a59-bed7-45f593d060c2",
"metadata": {},
"source": [
- "# Basic Samples : Agtype mapper for Psycopg2 driver\n",
+ "# Basic Samples : Agtype mapper for psycopg driver\n",
"\n",
- "You can make transactions and queries for PostgreSQL with Psycopg2.\n",
+ "You can make transactions and queries for PostgreSQL with Psycopg.\n",
"\n",
"This module enable to mapping agtype to python class(Path, Vertex, Edge)\n",
"\n",
@@ -16,26 +16,46 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 21,
"id": "98a5863c-1e79-438e-81d4-d1f5354a1bdb",
"metadata": {},
"outputs": [],
"source": [
- "import psycopg2 \n",
+ "import psycopg \n",
"import age\n",
"\n",
"GRAPH_NAME = \"test_graph\"\n",
- "conn = psycopg2.connect(host=\"172.17.0.2\", port=\"5432\", dbname=\"postgres\", user=\"postgres\", password=\"agens\")\n",
- "\n",
- "age.setUpAge(conn, GRAPH_NAME)\n"
+ "ag = age.connect(host=\"172.17.0.2\", port=\"5432\", dbname=\"postgre\", user=\"postgres\", password=\"agens\", graph=GRAPH_NAME)\n",
+ "conn = ag.connection\n"
]
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 22,
"id": "ebcf65a5-de7c-4224-aacc-2695c9e5f8d5",
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "CREATED:: {label:Person, id:844424930131971, properties:{name: Tom, title: Manager}}::VERTEX\n",
+ "------- [Select Vertices] --------\n",
+ "844424930131969 Person Joe Developer\n",
+ "--> {label:Person, id:844424930131969, properties:{name: Joe, title: Developer}}::VERTEX\n",
+ "844424930131970 Person Smith Developer\n",
+ "--> {label:Person, id:844424930131970, properties:{name: Smith, title: Developer}}::VERTEX\n",
+ "844424930131971 Person Tom Manager\n",
+ "--> {label:Person, id:844424930131971, properties:{name: Tom, title: Manager}}::VERTEX\n",
+ "<class 'psycopg.ClientCursor'>\n",
+ "------- [Select Paths] --------\n",
+ "1 Joe 2 workWith 5 1 Smith\n",
+ "--> [{label:Person, id:844424930131969, properties:{name: Joe, title: Developer}}::VERTEX,{label:workWith, id:1125899906842625, properties:{weight: 5}, start_id:844424930131969, end_id:844424930131970}::EDGE,{label:Person, id:844424930131970, properties:{name: Smith, title: Developer}}::VERTEX]::PATH\n",
+ "1 Smith 2 workWith 3 1 Tom\n",
+ "--> [{label:Person, id:844424930131970, properties:{name: Smith, title: Developer}}::VERTEX,{label:workWith, id:1125899906842626, properties:{weight: 3}, start_id:844424930131970, end_id:844424930131971}::EDGE,{label:Person, id:844424930131971, properties:{name: Tom, title: Manager}}::VERTEX]::PATH\n"
+ ]
+ }
+ ],
"source": [
"with conn.cursor() as cursor:\n",
" try :\n",
@@ -91,10 +111,21 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 23,
"id": "f45f7c7d-2256-4aea-92f6-e0ad71017feb",
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Joe workWith Smith\n",
+ "--> ('Joe', 'workWith', 'Smith')\n",
+ "Smith workWith Tom\n",
+ "--> ('Smith', 'workWith', 'Tom')\n"
+ ]
+ }
+ ],
"source": [
"with conn.cursor() as cursor:\n",
" try:\n",
@@ -111,10 +142,20 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 24,
"id": "c40b9076-d45e-43e6-85ae-296ba68a3031",
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Joe {'weight': 5} Smith\n",
+ "Smith {'weight': 3} Tom\n",
+ "Jack {'weight': 2} John\n"
+ ]
+ }
+ ],
"source": [
"with conn.cursor() as cursor:\n",
" try :\n",
@@ -152,10 +193,20 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 25,
"id": "29ffe1b7-86df-446a-9df0-635be25a9eea",
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Joe 1125899906842625 {'weight': 5} Smith\n",
+ "Smith 1125899906842626 {'weight': 3} Tom\n",
+ "Jack 1125899906842627 {'weight': 2} John\n"
+ ]
+ }
+ ],
"source": [
"with conn.cursor() as cursor:\n",
" try:\n",
@@ -172,7 +223,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 26,
"id": "428e6ddf-3958-49ff-af73-809b9a1ce42b",
"metadata": {},
"outputs": [],
@@ -180,25 +231,6 @@
"age.deleteGraph(conn, GRAPH_NAME)\n",
"conn.close()"
]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "a4819e39-9f37-4dd5-bdbd-337b6d289158",
- "metadata": {},
- "outputs": [],
- "source": [
- "\n",
- " "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "02041ef2-9761-4eb3-b270-ded23e1caa6d",
- "metadata": {},
- "outputs": [],
- "source": []
}
],
"metadata": {
@@ -217,7 +249,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.9.2"
+ "version": "3.11.1"
}
},
"nbformat": 4,
diff --git a/drivers/python/samples/apache-age-note.ipynb b/drivers/python/samples/apache-age-note.ipynb
index 59c25bc..d6bcf69 100644
--- a/drivers/python/samples/apache-age-note.ipynb
+++ b/drivers/python/samples/apache-age-note.ipynb
@@ -131,12 +131,10 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "CREATED: {label:Person, id:844424930131975, properties:{name: Jack, }}::VERTEX\n",
- "CREATED: 844424930131976\n",
+ "CREATED: {label:Person, id:844424930131971, properties:{name: Jack}}::VERTEX\n",
+ "CREATED: 844424930131972\n",
"SET: \"Manager\"\n",
- "SET: \"Manager\"\n",
- "REMOVE Prop: 844424930131970\n",
- "REMOVE Prop: 844424930131974\n"
+ "REMOVE Prop: 844424930131970\n"
]
}
],
@@ -221,29 +219,17 @@
"text": [
"-- Query Vertices --------------------\n",
"844424930131969 Person Joe\n",
- "--> {label:Person, id:844424930131969, properties:{name: Joe, }}::VERTEX\n",
+ "--> {label:Person, id:844424930131969, properties:{name: Joe}}::VERTEX\n",
"844424930131971 Person Jack\n",
- "--> {label:Person, id:844424930131971, properties:{name: Jack, }}::VERTEX\n",
+ "--> {label:Person, id:844424930131971, properties:{name: Jack}}::VERTEX\n",
"844424930131972 Person Andy\n",
- "--> {label:Person, id:844424930131972, properties:{name: Andy, title: Developer, }}::VERTEX\n",
- "844424930131973 Person Joe\n",
- "--> {label:Person, id:844424930131973, properties:{name: Joe, }}::VERTEX\n",
- "844424930131975 Person Jack\n",
- "--> {label:Person, id:844424930131975, properties:{name: Jack, }}::VERTEX\n",
- "844424930131976 Person Andy\n",
- "--> {label:Person, id:844424930131976, properties:{name: Andy, title: Developer, }}::VERTEX\n",
+ "--> {label:Person, id:844424930131972, properties:{name: Andy, title: Developer}}::VERTEX\n",
"844424930131970 Person Smith\n",
- "--> {label:Person, id:844424930131970, properties:{name: Smith, }}::VERTEX\n",
- "844424930131974 Person Smith\n",
- "--> {label:Person, id:844424930131974, properties:{name: Smith, }}::VERTEX\n",
+ "--> {label:Person, id:844424930131970, properties:{name: Smith}}::VERTEX\n",
"-- Query Vertices with with multi columns. --------------------\n",
"\"Person\" Joe\n",
"\"Person\" Jack\n",
"\"Person\" Andy\n",
- "\"Person\" Joe\n",
- "\"Person\" Jack\n",
- "\"Person\" Andy\n",
- "\"Person\" Smith\n",
"\"Person\" Smith\n"
]
}
@@ -305,14 +291,8 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "[{label:Person, id:844424930131972, properties:{name: Andy, title: Developer, }}::VERTEX,{label:workWith, id:1125899906842637, properties:{}, start_id:844424930131972, end_id:844424930131970}::EDGE,{label:Person, id:844424930131970, properties:{name: Smith, }}::VERTEX]::PATH\n",
- "[{label:Person, id:844424930131972, properties:{name: Andy, title: Developer, }}::VERTEX,{label:workWith, id:1125899906842638, properties:{}, start_id:844424930131972, end_id:844424930131974}::EDGE,{label:Person, id:844424930131974, properties:{name: Smith, }}::VERTEX]::PATH\n",
- "[{label:Person, id:844424930131976, properties:{name: Andy, title: Developer, }}::VERTEX,{label:workWith, id:1125899906842639, properties:{}, start_id:844424930131976, end_id:844424930131970}::EDGE,{label:Person, id:844424930131970, properties:{name: Smith, }}::VERTEX]::PATH\n",
- "[{label:Person, id:844424930131976, properties:{name: Andy, title: Developer, }}::VERTEX,{label:workWith, id:1125899906842640, properties:{}, start_id:844424930131976, end_id:844424930131974}::EDGE,{label:Person, id:844424930131974, properties:{name: Smith, }}::VERTEX]::PATH\n",
- "(a) {label:Person, id:844424930131969, properties:{name: Joe, }}::VERTEX : (r) {label:workWith, id:1125899906842641, properties:{weight: 5, }, start_id:844424930131969, end_id:844424930131971}::EDGE : (b) {label:Person, id:844424930131971, properties:{name: Jack, }}::VERTEX\n",
- "(a) {label:Person, id:844424930131969, properties:{name: Joe, }}::VERTEX : (r) {label:workWith, id:1125899906842642, properties:{weight: 5, }, start_id:844424930131969, end_id:844424930131975}::EDGE : (b) {label:Person, id:844424930131975, properties:{name: Jack, }}::VERTEX\n",
- "(a) {label:Person, id:844424930131973, properties:{name: Joe, }}::VERTEX : (r) {label:workWith, id:1125899906842643, properties:{weight: 5, }, start_id:844424930131973, end_id:844424930131971}::EDGE : (b) {label:Person, id:844424930131971, properties:{name: Jack, }}::VERTEX\n",
- "(a) {label:Person, id:844424930131973, properties:{name: Joe, }}::VERTEX : (r) {label:workWith, id:1125899906842644, properties:{weight: 5, }, start_id:844424930131973, end_id:844424930131975}::EDGE : (b) {label:Person, id:844424930131975, properties:{name: Jack, }}::VERTEX\n"
+ "[{label:Person, id:844424930131972, properties:{name: Andy, title: Developer}}::VERTEX,{label:workWith, id:1125899906842627, properties:{}, start_id:844424930131972, end_id:844424930131970}::EDGE,{label:Person, id:844424930131970, properties:{name: Smith}}::VERTEX]::PATH\n",
+ "(a) {label:Person, id:844424930131969, properties:{name: Joe}}::VERTEX : (r) {label:workWith, id:1125899906842628, properties:{weight: 5}, start_id:844424930131969, end_id:844424930131971}::EDGE : (b) {label:Person, id:844424930131971, properties:{name: Jack}}::VERTEX\n"
]
}
],
@@ -393,7 +373,7 @@
},
{
"cell_type": "code",
- "execution_count": 5,
+ "execution_count": 7,
"id": "7673e270-4ea3-4878-961c-8fc97106e1bd",
"metadata": {},
"outputs": [
@@ -401,156 +381,36 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "START: {label:Person, id:844424930131971, properties:{name: Jack, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842628, properties:{weight: 5, }, start_id:844424930131969, end_id:844424930131971}::EDGE\n",
- "END: {label:Person, id:844424930131969, properties:{name: Joe, }}::VERTEX\n",
- "START: {label:Person, id:844424930131971, properties:{name: Jack, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842641, properties:{weight: 5, }, start_id:844424930131969, end_id:844424930131971}::EDGE\n",
- "END: {label:Person, id:844424930131969, properties:{name: Joe, }}::VERTEX\n",
- "START: {label:Person, id:844424930131975, properties:{name: Jack, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842642, properties:{weight: 5, }, start_id:844424930131969, end_id:844424930131975}::EDGE\n",
- "END: {label:Person, id:844424930131969, properties:{name: Joe, }}::VERTEX\n",
- "START: {label:Person, id:844424930131970, properties:{name: Smith, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842625, properties:{weight: 3, }, start_id:844424930131969, end_id:844424930131970}::EDGE\n",
- "END: {label:Person, id:844424930131969, properties:{name: Joe, }}::VERTEX\n",
- "START: {label:Person, id:844424930131970, properties:{name: Smith, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842629, properties:{weight: 3, }, start_id:844424930131969, end_id:844424930131970}::EDGE\n",
- "END: {label:Person, id:844424930131969, properties:{name: Joe, }}::VERTEX\n",
- "START: {label:Person, id:844424930131974, properties:{name: Smith, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842630, properties:{weight: 3, }, start_id:844424930131969, end_id:844424930131974}::EDGE\n",
- "END: {label:Person, id:844424930131969, properties:{name: Joe, }}::VERTEX\n",
- "START: {label:Person, id:844424930131969, properties:{name: Joe, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842628, properties:{weight: 5, }, start_id:844424930131969, end_id:844424930131971}::EDGE\n",
- "END: {label:Person, id:844424930131971, properties:{name: Jack, }}::VERTEX\n",
- "START: {label:Person, id:844424930131969, properties:{name: Joe, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842641, properties:{weight: 5, }, start_id:844424930131969, end_id:844424930131971}::EDGE\n",
- "END: {label:Person, id:844424930131971, properties:{name: Jack, }}::VERTEX\n",
- "START: {label:Person, id:844424930131972, properties:{name: Andy, title: Developer, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842626, properties:{weight: 5, }, start_id:844424930131971, end_id:844424930131972}::EDGE\n",
- "END: {label:Person, id:844424930131971, properties:{name: Jack, }}::VERTEX\n",
- "START: {label:Person, id:844424930131972, properties:{name: Andy, title: Developer, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842633, properties:{weight: 5, }, start_id:844424930131971, end_id:844424930131972}::EDGE\n",
- "END: {label:Person, id:844424930131971, properties:{name: Jack, }}::VERTEX\n",
- "START: {label:Person, id:844424930131973, properties:{name: Joe, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842643, properties:{weight: 5, }, start_id:844424930131973, end_id:844424930131971}::EDGE\n",
- "END: {label:Person, id:844424930131971, properties:{name: Jack, }}::VERTEX\n",
- "START: {label:Person, id:844424930131976, properties:{name: Andy, title: Developer, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842634, properties:{weight: 5, }, start_id:844424930131971, end_id:844424930131976}::EDGE\n",
- "END: {label:Person, id:844424930131971, properties:{name: Jack, }}::VERTEX\n",
- "START: {label:Person, id:844424930131971, properties:{name: Jack, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842626, properties:{weight: 5, }, start_id:844424930131971, end_id:844424930131972}::EDGE\n",
- "END: {label:Person, id:844424930131972, properties:{name: Andy, title: Developer, }}::VERTEX\n",
- "START: {label:Person, id:844424930131971, properties:{name: Jack, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842633, properties:{weight: 5, }, start_id:844424930131971, end_id:844424930131972}::EDGE\n",
- "END: {label:Person, id:844424930131972, properties:{name: Andy, title: Developer, }}::VERTEX\n",
- "START: {label:Person, id:844424930131975, properties:{name: Jack, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842635, properties:{weight: 5, }, start_id:844424930131975, end_id:844424930131972}::EDGE\n",
- "END: {label:Person, id:844424930131972, properties:{name: Andy, title: Developer, }}::VERTEX\n",
- "START: {label:Person, id:844424930131970, properties:{name: Smith, }}::VERTEX\n",
+ "START: {label:Person, id:844424930131971, properties:{name: Jack}}::VERTEX\n",
+ "EDGE: {label:workWith, id:1125899906842628, properties:{weight: 5}, start_id:844424930131969, end_id:844424930131971}::EDGE\n",
+ "END: {label:Person, id:844424930131969, properties:{name: Joe}}::VERTEX\n",
+ "START: {label:Person, id:844424930131970, properties:{name: Smith}}::VERTEX\n",
+ "EDGE: {label:workWith, id:1125899906842625, properties:{weight: 3}, start_id:844424930131969, end_id:844424930131970}::EDGE\n",
+ "END: {label:Person, id:844424930131969, properties:{name: Joe}}::VERTEX\n",
+ "START: {label:Person, id:844424930131969, properties:{name: Joe}}::VERTEX\n",
+ "EDGE: {label:workWith, id:1125899906842628, properties:{weight: 5}, start_id:844424930131969, end_id:844424930131971}::EDGE\n",
+ "END: {label:Person, id:844424930131971, properties:{name: Jack}}::VERTEX\n",
+ "START: {label:Person, id:844424930131972, properties:{name: Andy, title: Developer}}::VERTEX\n",
+ "EDGE: {label:workWith, id:1125899906842626, properties:{weight: 5}, start_id:844424930131971, end_id:844424930131972}::EDGE\n",
+ "END: {label:Person, id:844424930131971, properties:{name: Jack}}::VERTEX\n",
+ "START: {label:Person, id:844424930131971, properties:{name: Jack}}::VERTEX\n",
+ "EDGE: {label:workWith, id:1125899906842626, properties:{weight: 5}, start_id:844424930131971, end_id:844424930131972}::EDGE\n",
+ "END: {label:Person, id:844424930131972, properties:{name: Andy, title: Developer}}::VERTEX\n",
+ "START: {label:Person, id:844424930131970, properties:{name: Smith}}::VERTEX\n",
"EDGE: {label:workWith, id:1125899906842627, properties:{}, start_id:844424930131972, end_id:844424930131970}::EDGE\n",
- "END: {label:Person, id:844424930131972, properties:{name: Andy, title: Developer, }}::VERTEX\n",
- "START: {label:Person, id:844424930131970, properties:{name: Smith, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842637, properties:{}, start_id:844424930131972, end_id:844424930131970}::EDGE\n",
- "END: {label:Person, id:844424930131972, properties:{name: Andy, title: Developer, }}::VERTEX\n",
- "START: {label:Person, id:844424930131974, properties:{name: Smith, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842638, properties:{}, start_id:844424930131972, end_id:844424930131974}::EDGE\n",
- "END: {label:Person, id:844424930131972, properties:{name: Andy, title: Developer, }}::VERTEX\n",
- "START: {label:Person, id:844424930131971, properties:{name: Jack, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842643, properties:{weight: 5, }, start_id:844424930131973, end_id:844424930131971}::EDGE\n",
- "END: {label:Person, id:844424930131973, properties:{name: Joe, }}::VERTEX\n",
- "START: {label:Person, id:844424930131975, properties:{name: Jack, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842644, properties:{weight: 5, }, start_id:844424930131973, end_id:844424930131975}::EDGE\n",
- "END: {label:Person, id:844424930131973, properties:{name: Joe, }}::VERTEX\n",
- "START: {label:Person, id:844424930131970, properties:{name: Smith, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842631, properties:{weight: 3, }, start_id:844424930131973, end_id:844424930131970}::EDGE\n",
- "END: {label:Person, id:844424930131973, properties:{name: Joe, }}::VERTEX\n",
- "START: {label:Person, id:844424930131974, properties:{name: Smith, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842632, properties:{weight: 3, }, start_id:844424930131973, end_id:844424930131974}::EDGE\n",
- "END: {label:Person, id:844424930131973, properties:{name: Joe, }}::VERTEX\n",
- "START: {label:Person, id:844424930131969, properties:{name: Joe, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842642, properties:{weight: 5, }, start_id:844424930131969, end_id:844424930131975}::EDGE\n",
- "END: {label:Person, id:844424930131975, properties:{name: Jack, }}::VERTEX\n",
- "START: {label:Person, id:844424930131972, properties:{name: Andy, title: Developer, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842635, properties:{weight: 5, }, start_id:844424930131975, end_id:844424930131972}::EDGE\n",
- "END: {label:Person, id:844424930131975, properties:{name: Jack, }}::VERTEX\n",
- "START: {label:Person, id:844424930131973, properties:{name: Joe, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842644, properties:{weight: 5, }, start_id:844424930131973, end_id:844424930131975}::EDGE\n",
- "END: {label:Person, id:844424930131975, properties:{name: Jack, }}::VERTEX\n",
- "START: {label:Person, id:844424930131976, properties:{name: Andy, title: Developer, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842636, properties:{weight: 5, }, start_id:844424930131975, end_id:844424930131976}::EDGE\n",
- "END: {label:Person, id:844424930131975, properties:{name: Jack, }}::VERTEX\n",
- "START: {label:Person, id:844424930131971, properties:{name: Jack, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842634, properties:{weight: 5, }, start_id:844424930131971, end_id:844424930131976}::EDGE\n",
- "END: {label:Person, id:844424930131976, properties:{name: Andy, title: Developer, }}::VERTEX\n",
- "START: {label:Person, id:844424930131975, properties:{name: Jack, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842636, properties:{weight: 5, }, start_id:844424930131975, end_id:844424930131976}::EDGE\n",
- "END: {label:Person, id:844424930131976, properties:{name: Andy, title: Developer, }}::VERTEX\n",
- "START: {label:Person, id:844424930131970, properties:{name: Smith, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842639, properties:{}, start_id:844424930131976, end_id:844424930131970}::EDGE\n",
- "END: {label:Person, id:844424930131976, properties:{name: Andy, title: Developer, }}::VERTEX\n",
- "START: {label:Person, id:844424930131974, properties:{name: Smith, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842640, properties:{}, start_id:844424930131976, end_id:844424930131974}::EDGE\n",
- "END: {label:Person, id:844424930131976, properties:{name: Andy, title: Developer, }}::VERTEX\n",
- "START: {label:Person, id:844424930131969, properties:{name: Joe, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842625, properties:{weight: 3, }, start_id:844424930131969, end_id:844424930131970}::EDGE\n",
- "END: {label:Person, id:844424930131970, properties:{name: Smith, }}::VERTEX\n",
- "START: {label:Person, id:844424930131969, properties:{name: Joe, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842629, properties:{weight: 3, }, start_id:844424930131969, end_id:844424930131970}::EDGE\n",
- "END: {label:Person, id:844424930131970, properties:{name: Smith, }}::VERTEX\n",
- "START: {label:Person, id:844424930131972, properties:{name: Andy, title: Developer, }}::VERTEX\n",
+ "END: {label:Person, id:844424930131972, properties:{name: Andy, title: Developer}}::VERTEX\n",
+ "START: {label:Person, id:844424930131969, properties:{name: Joe}}::VERTEX\n",
+ "EDGE: {label:workWith, id:1125899906842625, properties:{weight: 3}, start_id:844424930131969, end_id:844424930131970}::EDGE\n",
+ "END: {label:Person, id:844424930131970, properties:{name: Smith}}::VERTEX\n",
+ "START: {label:Person, id:844424930131972, properties:{name: Andy, title: Developer}}::VERTEX\n",
"EDGE: {label:workWith, id:1125899906842627, properties:{}, start_id:844424930131972, end_id:844424930131970}::EDGE\n",
- "END: {label:Person, id:844424930131970, properties:{name: Smith, }}::VERTEX\n",
- "START: {label:Person, id:844424930131972, properties:{name: Andy, title: Developer, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842637, properties:{}, start_id:844424930131972, end_id:844424930131970}::EDGE\n",
- "END: {label:Person, id:844424930131970, properties:{name: Smith, }}::VERTEX\n",
- "START: {label:Person, id:844424930131973, properties:{name: Joe, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842631, properties:{weight: 3, }, start_id:844424930131973, end_id:844424930131970}::EDGE\n",
- "END: {label:Person, id:844424930131970, properties:{name: Smith, }}::VERTEX\n",
- "START: {label:Person, id:844424930131976, properties:{name: Andy, title: Developer, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842639, properties:{}, start_id:844424930131976, end_id:844424930131970}::EDGE\n",
- "END: {label:Person, id:844424930131970, properties:{name: Smith, }}::VERTEX\n",
- "START: {label:Person, id:844424930131969, properties:{name: Joe, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842630, properties:{weight: 3, }, start_id:844424930131969, end_id:844424930131974}::EDGE\n",
- "END: {label:Person, id:844424930131974, properties:{name: Smith, }}::VERTEX\n",
- "START: {label:Person, id:844424930131972, properties:{name: Andy, title: Developer, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842638, properties:{}, start_id:844424930131972, end_id:844424930131974}::EDGE\n",
- "END: {label:Person, id:844424930131974, properties:{name: Smith, }}::VERTEX\n",
- "START: {label:Person, id:844424930131973, properties:{name: Joe, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842632, properties:{weight: 3, }, start_id:844424930131973, end_id:844424930131974}::EDGE\n",
- "END: {label:Person, id:844424930131974, properties:{name: Smith, }}::VERTEX\n",
- "START: {label:Person, id:844424930131976, properties:{name: Andy, title: Developer, }}::VERTEX\n",
- "EDGE: {label:workWith, id:1125899906842640, properties:{}, start_id:844424930131976, end_id:844424930131974}::EDGE\n",
- "END: {label:Person, id:844424930131974, properties:{name: Smith, }}::VERTEX\n",
+ "END: {label:Person, id:844424930131970, properties:{name: Smith}}::VERTEX\n",
"-- [Query path with multi columns --------\n",
"Jack workWith 5 Joe\n",
- "Jack workWith 5 Joe\n",
- "Jack workWith 5 Joe\n",
- "Smith workWith 3 Joe\n",
- "Smith workWith 3 Joe\n",
- "Smith workWith 3 Joe\n",
- "Joe workWith 5 Jack\n",
- "Joe workWith 5 Jack\n",
- "Andy workWith 5 Jack\n",
- "Andy workWith 5 Jack\n",
- "Joe workWith 5 Jack\n",
- "Andy workWith 5 Jack\n",
- "Jack workWith 5 Andy\n",
- "Jack workWith 5 Andy\n",
- "Jack workWith 5 Andy\n",
- "Jack workWith 5 Joe\n",
- "Jack workWith 5 Joe\n",
- "Smith workWith 3 Joe\n",
"Smith workWith 3 Joe\n",
"Joe workWith 5 Jack\n",
"Andy workWith 5 Jack\n",
- "Joe workWith 5 Jack\n",
- "Andy workWith 5 Jack\n",
"Jack workWith 5 Andy\n",
- "Jack workWith 5 Andy\n",
- "Joe workWith 3 Smith\n",
- "Joe workWith 3 Smith\n",
- "Joe workWith 3 Smith\n",
- "Joe workWith 3 Smith\n",
"Joe workWith 3 Smith\n"
]
}
@@ -564,7 +424,7 @@
" print(\"END:\", path[2]) \n",
"\n",
"print(\"-- [Query path with multi columns --------\")\n",
- "cursor = ag.execCypher(\"MATCH p=(a)-[b]-(c) WHERE b.weight>2 RETURN a,label(b), b.weight, c\", cols=[\"a\",\"bl\",\"bw\", \"c\"], params=(2,))\n",
+ "cursor = ag.execCypher(\"MATCH p=(a)-[b]-(c) WHERE b.weight>%s RETURN a,label(b), b.weight, c\", cols=[\"a\",\"bl\",\"bw\", \"c\"], params=(2,))\n",
"for row in cursor:\n",
" start = row[0]\n",
" edgel = row[1]\n",
@@ -588,7 +448,7 @@
},
{
"cell_type": "code",
- "execution_count": 6,
+ "execution_count": 8,
"id": "5771219a",
"metadata": {},
"outputs": [
@@ -596,22 +456,14 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "Joe workWith ['Smith', 'Smith', 'Jack', 'Jack', 'Smith', 'Jack']\n",
- "Smith workWith ['Joe', 'Joe', 'Andy', 'Andy', 'Joe', 'Andy']\n",
- "Jack workWith ['Joe', 'Joe', 'Andy', 'Andy', 'Joe', 'Andy']\n",
- "Andy workWith ['Smith', 'Smith', 'Jack', 'Jack', 'Smith', 'Jack']\n",
- "Joe workWith ['Jack', 'Smith', 'Jack', 'Smith']\n",
- "Smith workWith ['Andy', 'Joe', 'Andy', 'Joe']\n",
- "Jack workWith ['Joe', 'Joe', 'Andy', 'Andy']\n",
- "Andy workWith ['Jack', 'Smith', 'Jack', 'Smith']\n",
- "Joe workWith ['Smith', 'Smith', 'Jack', 'Jack', 'Smith', 'Jack']\n",
- "Smith workWith ['Joe', 'Joe', 'Andy', 'Andy', 'Joe', 'Andy']\n",
- "Jack workWith ['Joe', 'Joe', 'Andy', 'Andy', 'Joe', 'Andy']\n",
- "Andy workWith ['Smith', 'Smith', 'Jack', 'Jack', 'Smith', 'Jack']\n",
- "Joe workWith ['Jack', 'Smith', 'Jack', 'Smith']\n",
- "Smith workWith ['Andy', 'Joe', 'Andy', 'Joe']\n",
- "Jack workWith ['Joe', 'Joe', 'Andy', 'Andy']\n",
- "Andy workWith ['Jack', 'Smith', 'Jack', 'Smith']\n"
+ "Joe workWith ['Jack', 'Smith']\n",
+ "Smith workWith ['Joe', 'Andy']\n",
+ "Jack workWith ['Joe', 'Andy']\n",
+ "Andy workWith ['Jack', 'Smith']\n",
+ "Joe workWith ['Jack', 'Smith']\n",
+ "Smith workWith ['Joe', 'Andy']\n",
+ "Jack workWith ['Joe', 'Andy']\n",
+ "Andy workWith ['Jack', 'Smith']\n"
]
}
],
@@ -642,7 +494,7 @@
},
{
"cell_type": "code",
- "execution_count": 7,
+ "execution_count": 9,
"id": "c8b36687-c842-4663-a7aa-084ae618301e",
"metadata": {},
"outputs": [
@@ -714,7 +566,7 @@
},
{
"cell_type": "code",
- "execution_count": 8,
+ "execution_count": 10,
"id": "7f93e698-888a-4dde-b327-e591659e051f",
"metadata": {},
"outputs": [
@@ -726,22 +578,13 @@
"844424930131969\n",
"844424930131971\n",
"844424930131972\n",
- "844424930131973\n",
- "844424930131975\n",
- "844424930131976\n",
"844424930131970\n",
- "844424930131974\n",
"-- Query properties --------------------\n",
"{'name': 'Joe'}\n",
"{'name': 'Jack'}\n",
"{'name': 'Andy', 'title': 'Developer'}\n",
- "{'name': 'Joe'}\n",
- "{'name': 'Jack'}\n",
- "{'name': 'Andy', 'title': 'Developer'}\n",
- "{'name': 'Smith'}\n",
"{'name': 'Smith'}\n",
"-- Query property value --------------------\n",
- "Developer\n",
"Developer\n"
]
}
@@ -777,7 +620,7 @@
},
{
"cell_type": "code",
- "execution_count": 9,
+ "execution_count": 11,
"id": "e15b0654-66d2-4da4-af66-6f776e6729ac",
"metadata": {},
"outputs": [],
diff --git a/drivers/python/samples/networkx.ipynb b/drivers/python/samples/networkx.ipynb
index 20fc566..759dee2 100644
--- a/drivers/python/samples/networkx.ipynb
+++ b/drivers/python/samples/networkx.ipynb
@@ -6,12 +6,12 @@
"metadata": {},
"outputs": [],
"source": [
- "import psycopg2\n",
+ "import psycopg\n",
"from age.networkx import *\n",
"from age import *\n",
"import networkx as nx\n",
"\n",
- "conn = psycopg2.connect(\n",
+ "conn = psycopg.connect(\n",
" host=\"localhost\",\n",
" port=\"5432\",\n",
" dbname=\"postgres\",\n",
diff --git a/drivers/python/setup.py b/drivers/python/setup.py
index 15be9e7..1da49d9 100644
--- a/drivers/python/setup.py
+++ b/drivers/python/setup.py
@@ -30,7 +30,7 @@
url = 'https://github.com/apache/age/tree/master/drivers/python',
download_url = 'https://github.com/apache/age/releases' ,
license = 'Apache2.0',
- install_requires = [ 'psycopg2', 'antlr4-python3-runtime==4.11.1'],
+ install_requires = [ 'psycopg', 'antlr4-python3-runtime==4.11.1'],
packages = ['age', 'age.gen','age.networkx'],
keywords = ['Graph Database', 'Apache AGE', 'PostgreSQL'],
python_requires = '>=3.9',
diff --git a/drivers/python/test_age_py.py b/drivers/python/test_age_py.py
index 8048844..f904fb9 100644
--- a/drivers/python/test_age_py.py
+++ b/drivers/python/test_age_py.py
@@ -20,7 +20,6 @@
import age
import argparse
-DSN = "host=localhost port=5432 dbname=postgres user=postgres password=agens"
TEST_HOST = "localhost"
TEST_PORT = 5432
TEST_DB = "postgres"
@@ -28,12 +27,32 @@
TEST_PASSWORD = "agens"
TEST_GRAPH_NAME = "test_graph"
+
class TestAgeBasic(unittest.TestCase):
ag = None
+ args: argparse.Namespace = argparse.Namespace(
+ host=TEST_HOST,
+ port=TEST_PORT,
+ database=TEST_DB,
+ user=TEST_USER,
+ password=TEST_PASSWORD,
+ graphName=TEST_GRAPH_NAME
+ )
+
def setUp(self):
print("Connecting to Test Graph.....")
- self.ag = age.connect(graph=TEST_GRAPH_NAME, host=TEST_HOST, port=TEST_PORT, dbname=TEST_DB, user=TEST_USER, password=TEST_PASSWORD)
+ args = dict(
+ host=self.args.host,
+ port=self.args.port,
+ dbname=self.args.database,
+ user=self.args.user,
+ password=self.args.password,
+ )
+ dsn = "host={host} port={port} dbname={dbname} user={user} password={password}".format(
+ **args
+ )
+ self.ag = age.connect(dsn, graph=self.args.graphName, **args)
def tearDown(self):
# Clear test data
@@ -42,43 +61,52 @@
self.ag.close()
def testExec(self):
-
print("\n---------------------------------------------------")
print("Test 1: Checking single and multi column Returns.....")
print("---------------------------------------------------\n")
ag = self.ag
# Create and Return single column
- cursor = ag.execCypher("CREATE (n:Person {name: %s, title: 'Developer'}) RETURN n", params=('Andy',))
+ cursor = ag.execCypher(
+ "CREATE (n:Person {name: %s, title: 'Developer'}) RETURN n",
+ params=("Andy",),
+ )
for row in cursor:
print("Vertex: %s , Type: %s " % (Vertex, type(row[0])))
-
# Create and Return multi columns
- cursor = ag.execCypher("CREATE (n:Person {name: %s, title: %s}) RETURN id(n), n.name", cols=['id','name'], params=('Jack','Manager'))
+ cursor = ag.execCypher(
+ "CREATE (n:Person {name: %s, title: %s}) RETURN id(n), n.name",
+ cols=["id", "name"],
+ params=("Jack", "Manager"),
+ )
row = cursor.fetchone()
print("Id: %s , Name: %s" % (row[0], row[1]))
self.assertEqual(int, type(row[0]))
ag.commit()
print("\nTest 1 Successful....")
-
-
-
def testQuery(self):
-
print("\n--------------------------------------------------")
- print("Test 2: Testing CREATE and query relationships....." )
+ print("Test 2: Testing CREATE and query relationships.....")
print("--------------------------------------------------\n")
ag = self.ag
- ag.execCypher("CREATE (n:Person {name: %s}) ", params=('Jack',))
- ag.execCypher("CREATE (n:Person {name: %s}) ", params=('Andy',))
- ag.execCypher("CREATE (n:Person {name: %s}) ", params=('Smith',))
- ag.execCypher("MATCH (a:Person), (b:Person) WHERE a.name = 'Andy' AND b.name = 'Jack' CREATE (a)-[r:worksWith {weight: 3}]->(b)")
- ag.execCypher("""MATCH (a:Person), (b:Person)
+ ag.execCypher("CREATE (n:Person {name: %s}) ", params=("Jack",))
+ ag.execCypher("CREATE (n:Person {name: %s}) ", params=("Andy",))
+ ag.execCypher("CREATE (n:Person {name: %s}) ", params=("Smith",))
+ ag.execCypher(
+ "MATCH (a:Person), (b:Person) WHERE a.name = 'Andy' AND b.name = 'Jack' CREATE (a)-[r:worksWith {weight: 3}]->(b)"
+ )
+ ag.execCypher(
+ """MATCH (a:Person), (b:Person)
WHERE a.name = %s AND b.name = %s
- CREATE p=((a)-[r:worksWith]->(b)) """, params=('Jack', 'Smith',))
+ CREATE p=((a)-[r:worksWith]->(b)) """,
+ params=(
+ "Jack",
+ "Smith",
+ ),
+ )
ag.commit()
@@ -89,20 +117,25 @@
print("EDGE:", path[1])
print("END:", path[2])
- cursor = ag.execCypher("MATCH p=(a)-[b]-(c) WHERE b.weight>2 RETURN a,label(b), b.weight, c", cols=["a","bl","bw", "c"], params=(2,))
+ cursor = ag.execCypher(
+ "MATCH p=(a)-[b]-(c) WHERE b.weight>%s RETURN a,label(b), b.weight, c",
+ cols=["a", "bl", "bw", "c"],
+ params=(2,),
+ )
for row in cursor:
start = row[0]
edgel = row[1]
edgew = row[2]
end = row[3]
- print("Relationship: %s %s %s. Edge weight: %s" % (start["name"] , edgel,end["name"], edgew))
- #Assert that the weight of the edge is greater than 2
+ print(
+ "Relationship: %s %s %s. Edge weight: %s"
+ % (start["name"], edgel, end["name"], edgew)
+ )
+ # Assert that the weight of the edge is greater than 2
self.assertEqual(edgew > 2, True)
print("\nTest 2 Successful...")
-
def testChangeData(self):
-
print("\n-------------------------------------------------------")
print("Test 3: Testing changes in data using SET and REMOVE.....")
print("-------------------------------------------------------\n")
@@ -112,14 +145,23 @@
# Commit automatically
ag.execCypher("CREATE (n:Person {name: 'Joe'})")
- cursor = ag.execCypher("CREATE (n:Person {name: %s, title: 'Developer'}) RETURN n", params=('Smith',))
+ cursor = ag.execCypher(
+ "CREATE (n:Person {name: %s, title: 'Developer'}) RETURN n",
+ params=("Smith",),
+ )
row = cursor.fetchone()
print("CREATED: ", row[0])
# You must commit explicitly
ag.commit()
- cursor = ag.execCypher("MATCH (n:Person {name: %s}) SET n.title=%s RETURN n", params=('Smith','Manager',))
+ cursor = ag.execCypher(
+ "MATCH (n:Person {name: %s}) SET n.title=%s RETURN n",
+ params=(
+ "Smith",
+ "Manager",
+ ),
+ )
row = cursor.fetchone()
vertex = row[0]
title1 = vertex["title"]
@@ -133,38 +175,39 @@
self.assertEqual(title1, title2)
- cursor = ag.execCypher("MATCH (n:Person {name: %s}) SET n.bigNum=-6.45161e+46::numeric RETURN n", params=('Smith',))
+ cursor = ag.execCypher(
+ "MATCH (n:Person {name: %s}) SET n.bigNum=-6.45161e+46::numeric RETURN n",
+ params=("Smith",),
+ )
row = cursor.fetchone()
vertex = row[0]
for row in cursor:
- print("SET bigNum: ", vertex['bigNum'])
+ print("SET bigNum: ", vertex["bigNum"])
bigNum1 = vertex["bigNum"]
self.assertEqual(decimal.Decimal("-6.45161e+46"), bigNum1)
ag.commit()
-
cursor = ag.execCypher("MATCH (p:Person {name: 'Smith'}) RETURN p.bigNum")
row = cursor.fetchone()
bigNum2 = row[0]
self.assertEqual(bigNum1, bigNum2)
-
- cursor = ag.execCypher("MATCH (n:Person {name: %s}) REMOVE n.title RETURN n", params=('Smith',))
+ cursor = ag.execCypher(
+ "MATCH (n:Person {name: %s}) REMOVE n.title RETURN n", params=("Smith",)
+ )
for row in cursor:
print("REMOVE Prop title: ", row[0])
- #Assert that the title property is removed
- self.assertIsNone(row[0].properties.get('title'))
+ # Assert that the title property is removed
+ self.assertIsNone(row[0].properties.get("title"))
print("\nTest 3 Successful....")
# You must commit explicitly
ag.commit()
-
def testCypher(self):
-
print("\n--------------------------")
print("Test 4: Testing Cypher.....")
print("--------------------------\n")
@@ -172,12 +215,12 @@
ag = self.ag
with ag.connection.cursor() as cursor:
- try :
- ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=('Joe',))
- ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=('Jack',))
- ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=('Andy',))
- ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=('Smith',))
- ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=('Tom',))
+ try:
+ ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=("Joe",))
+ ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=("Jack",))
+ ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=("Andy",))
+ ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=("Smith",))
+ ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=("Tom",))
# You must commit explicitly
ag.commit()
@@ -186,10 +229,19 @@
ag.rollback()
with ag.connection.cursor() as cursor:
- try :# Create Edges
- ag.cypher(cursor,"MATCH (a:Person), (b:Person) WHERE a.name = 'Joe' AND b.name = 'Smith' CREATE (a)-[r:worksWith {weight: 3}]->(b)")
- ag.cypher(cursor,"MATCH (a:Person), (b:Person) WHERE a.name = 'Andy' AND b.name = 'Tom' CREATE (a)-[r:worksWith {weight: 1}]->(b)")
- ag.cypher(cursor,"MATCH (a:Person {name: 'Jack'}), (b:Person {name: 'Andy'}) CREATE (a)-[r:worksWith {weight: 5}]->(b)")
+ try: # Create Edges
+ ag.cypher(
+ cursor,
+ "MATCH (a:Person), (b:Person) WHERE a.name = 'Joe' AND b.name = 'Smith' CREATE (a)-[r:worksWith {weight: 3}]->(b)",
+ )
+ ag.cypher(
+ cursor,
+ "MATCH (a:Person), (b:Person) WHERE a.name = 'Andy' AND b.name = 'Tom' CREATE (a)-[r:worksWith {weight: 1}]->(b)",
+ )
+ ag.cypher(
+ cursor,
+ "MATCH (a:Person {name: 'Jack'}), (b:Person {name: 'Andy'}) CREATE (a)-[r:worksWith {weight: 5}]->(b)",
+ )
# You must commit explicitly
ag.commit()
@@ -197,12 +249,16 @@
print(ex)
ag.rollback()
-
# With Params
- cursor = ag.execCypher("""MATCH (a:Person), (b:Person)
+ cursor = ag.execCypher(
+ """MATCH (a:Person), (b:Person)
WHERE a.name = %s AND b.name = %s
CREATE p=((a)-[r:worksWith]->(b)) RETURN p""",
- params=('Andy', 'Smith',))
+ params=(
+ "Andy",
+ "Smith",
+ ),
+ )
for row in cursor:
print("CREATED EDGE: %s" % row[0])
@@ -213,25 +269,22 @@
for row in cursor:
print("CREATED EDGE WITH PROPERTIES: %s" % row[0])
- self.assertEqual(row[0][1].properties['weight'], 5)
+ self.assertEqual(row[0][1].properties["weight"], 5)
print("\nTest 4 Successful...")
-
-
def testMultipleEdges(self):
-
print("\n------------------------------------")
print("Test 5: Testing Multiple Edges.....")
print("------------------------------------\n")
ag = self.ag
with ag.connection.cursor() as cursor:
- try :
- ag.cypher(cursor, "CREATE (n:Country {name: %s}) ", params=('USA',))
- ag.cypher(cursor, "CREATE (n:Country {name: %s}) ", params=('France',))
- ag.cypher(cursor, "CREATE (n:Country {name: %s}) ", params=('Korea',))
- ag.cypher(cursor, "CREATE (n:Country {name: %s}) ", params=('Russia',))
+ try:
+ ag.cypher(cursor, "CREATE (n:Country {name: %s}) ", params=("USA",))
+ ag.cypher(cursor, "CREATE (n:Country {name: %s}) ", params=("France",))
+ ag.cypher(cursor, "CREATE (n:Country {name: %s}) ", params=("Korea",))
+ ag.cypher(cursor, "CREATE (n:Country {name: %s}) ", params=("Russia",))
# You must commit explicitly after all executions.
ag.connection.commit()
@@ -240,10 +293,19 @@
raise ex
with ag.connection.cursor() as cursor:
- try :# Create Edges
- ag.cypher(cursor,"MATCH (a:Country), (b:Country) WHERE a.name = 'USA' AND b.name = 'France' CREATE (a)-[r:distance {unit:'miles', value: 4760}]->(b)")
- ag.cypher(cursor,"MATCH (a:Country), (b:Country) WHERE a.name = 'France' AND b.name = 'Korea' CREATE (a)-[r:distance {unit: 'km', value: 9228}]->(b)")
- ag.cypher(cursor,"MATCH (a:Country {name: 'Korea'}), (b:Country {name: 'Russia'}) CREATE (a)-[r:distance {unit:'km', value: 3078}]->(b)")
+ try: # Create Edges
+ ag.cypher(
+ cursor,
+ "MATCH (a:Country), (b:Country) WHERE a.name = 'USA' AND b.name = 'France' CREATE (a)-[r:distance {unit:'miles', value: 4760}]->(b)",
+ )
+ ag.cypher(
+ cursor,
+ "MATCH (a:Country), (b:Country) WHERE a.name = 'France' AND b.name = 'Korea' CREATE (a)-[r:distance {unit: 'km', value: 9228}]->(b)",
+ )
+ ag.cypher(
+ cursor,
+ "MATCH (a:Country {name: 'Korea'}), (b:Country {name: 'Russia'}) CREATE (a)-[r:distance {unit:'km', value: 3078}]->(b)",
+ )
# You must commit explicitly
ag.connection.commit()
@@ -251,7 +313,6 @@
ag.rollback()
raise ex
-
cursor = ag.execCypher("""MATCH p=(:Country {name:"USA"})-[:distance]-(:Country)-[:distance]-(:Country)
RETURN p""")
@@ -263,7 +324,9 @@
if e.gtype == age.TP_VERTEX:
output.append(e.label + " " + e["name"])
elif e.gtype == age.TP_EDGE:
- output.append("---- (distance " + str(e["value"]) + " " + e["unit"] + ") --->")
+ output.append(
+ "---- (distance " + str(e["value"]) + " " + e["unit"] + ") --->"
+ )
else:
output.append("Unknown element. " + str(e))
@@ -271,14 +334,11 @@
formatted_output = " ".join(output)
print("PATH WITH MULTIPLE EDGES: %s" % formatted_output)
- self.assertEqual(5,count)
+ self.assertEqual(5, count)
print("\nTest 5 Successful...")
-
-
def testCollect(self):
-
print("\n--------------------------")
print("Test 6: Testing COLLECT.....")
print("--------------------------\n")
@@ -286,12 +346,12 @@
ag = self.ag
with ag.connection.cursor() as cursor:
- try :
- ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=('Joe',))
- ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=('Jack',))
- ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=('Andy',))
- ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=('Smith',))
- ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=('Tom',))
+ try:
+ ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=("Joe",))
+ ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=("Jack",))
+ ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=("Andy",))
+ ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=("Smith",))
+ ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=("Tom",))
# You must commit explicitly
ag.commit()
@@ -300,10 +360,19 @@
ag.rollback()
with ag.connection.cursor() as cursor:
- try :# Create Edges
- ag.cypher(cursor,"MATCH (a:Person), (b:Person) WHERE a.name = 'Joe' AND b.name = 'Smith' CREATE (a)-[r:worksWith {weight: 3}]->(b)")
- ag.cypher(cursor,"MATCH (a:Person), (b:Person) WHERE a.name = 'Joe' AND b.name = 'Tom' CREATE (a)-[r:worksWith {weight: 1}]->(b)")
- ag.cypher(cursor,"MATCH (a:Person {name: 'Joe'}), (b:Person {name: 'Andy'}) CREATE (a)-[r:worksWith {weight: 5}]->(b)")
+ try: # Create Edges
+ ag.cypher(
+ cursor,
+ "MATCH (a:Person), (b:Person) WHERE a.name = 'Joe' AND b.name = 'Smith' CREATE (a)-[r:worksWith {weight: 3}]->(b)",
+ )
+ ag.cypher(
+ cursor,
+ "MATCH (a:Person), (b:Person) WHERE a.name = 'Joe' AND b.name = 'Tom' CREATE (a)-[r:worksWith {weight: 1}]->(b)",
+ )
+ ag.cypher(
+ cursor,
+ "MATCH (a:Person {name: 'Joe'}), (b:Person {name: 'Andy'}) CREATE (a)-[r:worksWith {weight: 5}]->(b)",
+ )
# You must commit explicitly
ag.commit()
@@ -313,24 +382,29 @@
print(" -------- TESTING COLLECT #1 --------")
with ag.connection.cursor() as cursor:
- ag.cypher(cursor, "MATCH (a)-[:worksWith]->(c) WITH a as V, COLLECT(c) as CV RETURN V.name, CV", cols=["V","CV"])
+ ag.cypher(
+ cursor,
+ "MATCH (a)-[:worksWith]->(c) WITH a as V, COLLECT(c) as CV RETURN V.name, CV",
+ cols=["V", "CV"],
+ )
for row in cursor:
nm = row[0]
collected = row[1]
print(nm, "worksWith", [i["name"] for i in collected])
- self.assertEqual(3,len(collected))
-
+ self.assertEqual(3, len(collected))
print(" -------- TESTING COLLECT #2 --------")
- for row in ag.execCypher("MATCH (a)-[:worksWith]->(c) WITH a as V, COLLECT(c) as CV RETURN V.name, CV", cols=["V1","CV"]):
+ for row in ag.execCypher(
+ "MATCH (a)-[:worksWith]->(c) WITH a as V, COLLECT(c) as CV RETURN V.name, CV",
+ cols=["V1", "CV"],
+ ):
nm = row[0]
collected = row[1]
print(nm, "worksWith", [i["name"] for i in collected])
- self.assertEqual(3,len(collected))
+ self.assertEqual(3, len(collected))
print("\nTest 6 Successful...")
def testSerialization(self):
-
print("\n---------------------------------------")
print("Test 6: Testing Vertex Serialization.....")
print("-----------------------------------------\n")
@@ -339,11 +413,11 @@
with ag.connection.cursor() as cursor:
try:
- ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=('Joe',))
- ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=('Jack',))
- ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=('Andy',))
- ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=('Smith',))
- ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=('Tom',))
+ ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=("Joe",))
+ ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=("Jack",))
+ ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=("Andy",))
+ ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=("Smith",))
+ ag.cypher(cursor, "CREATE (n:Person {name: %s}) ", params=("Tom",))
# You must commit explicitly
ag.commit()
@@ -375,42 +449,48 @@
print("Vertex.toString() 'properties' field is formatted properly.")
-if __name__ == '__main__':
+if __name__ == "__main__":
parser = argparse.ArgumentParser()
- parser.add_argument('-host',
- '--host',
- help='Optional Host Name. Default Host is "127.0.0.1" ',
- default="127.0.0.1")
- parser.add_argument('-port',
- '--port',
- help='Optional Port Number. Default port no is 5432',
- default=5432)
- parser.add_argument('-db',
- '--database',
- help='Required Database Name',
- required=True)
- parser.add_argument('-u',
- '--user',
- help='Required Username Name',
- required=True)
- parser.add_argument('-pass',
- '--password',
- help='Required Password for authentication',
- required=True)
- parser.add_argument('-gn',
- '--graphName',
- help='Optional Graph Name to be created. Default graphName is "test_graph"',
- default="test_graph")
+ parser.add_argument(
+ "-host",
+ "--host",
+ help='Optional Host Name. Default Host is "127.0.0.1" ',
+ default=TEST_HOST,
+ )
+ parser.add_argument(
+ "-port",
+ "--port",
+ help="Optional Port Number. Default port no is 5432",
+ default=TEST_PORT,
+ )
+ parser.add_argument(
+ "-db", "--database", help="Required Database Name", default=TEST_DB
+ )
+ parser.add_argument(
+ "-u", "--user", help="Required Username Name", default=TEST_USER
+ )
+ parser.add_argument(
+ "-pass",
+ "--password",
+ help="Required Password for authentication",
+ default=TEST_PASSWORD,
+ )
+ parser.add_argument(
+ "-gn",
+ "--graphName",
+ help='Optional Graph Name to be created. Default graphName is "test_graph"',
+ default=TEST_GRAPH_NAME,
+ )
args = parser.parse_args()
suite = unittest.TestSuite()
- suite.addTest(TestAgeBasic('testExec'))
- suite.addTest(TestAgeBasic('testQuery'))
- suite.addTest(TestAgeBasic('testChangeData'))
- suite.addTest(TestAgeBasic('testCypher'))
- suite.addTest(TestAgeBasic('testMultipleEdges'))
- suite.addTest(TestAgeBasic('testCollect'))
- suite.addTest(TestAgeBasic('testSerialization'))
+ suite.addTest(TestAgeBasic("testExec"))
+ suite.addTest(TestAgeBasic("testQuery"))
+ suite.addTest(TestAgeBasic("testChangeData"))
+ suite.addTest(TestAgeBasic("testCypher"))
+ suite.addTest(TestAgeBasic("testMultipleEdges"))
+ suite.addTest(TestAgeBasic("testCollect"))
+ suite.addTest(TestAgeBasic("testSerialization"))
TestAgeBasic.args = args
unittest.TextTestRunner().run(suite)
diff --git a/drivers/python/test_networkx.py b/drivers/python/test_networkx.py
index 290d4c4..310d2cf 100644
--- a/drivers/python/test_networkx.py
+++ b/drivers/python/test_networkx.py
@@ -26,22 +26,38 @@
ORIGINAL_GRAPH = "original_graph"
EXPECTED_GRAPH = "expected_graph"
+TEST_HOST = "localhost"
+TEST_PORT = 5432
+TEST_DB = "postgres"
+TEST_USER = "postgres"
+TEST_PASSWORD = "agens"
+
class TestAgeToNetworkx(unittest.TestCase):
ag = None
+ args: argparse.Namespace = argparse.Namespace(
+ host=TEST_HOST,
+ port=TEST_PORT,
+ database=TEST_DB,
+ user=TEST_USER,
+ password=TEST_PASSWORD,
+ graphName=TEST_GRAPH_NAME
+ )
def setUp(self):
+ args = dict(
+ host=self.args.host,
+ port=self.args.port,
+ dbname=self.args.database,
+ user=self.args.user,
+ password=self.args.password
+ )
- TEST_DB = self.args.database
- TEST_USER = self.args.user
- TEST_PASSWORD = self.args.password
- TEST_PORT = self.args.port
- TEST_HOST = self.args.host
- self.ag = age.connect(graph=TEST_GRAPH_NAME, host=TEST_HOST, port=TEST_PORT,
- dbname=TEST_DB, user=TEST_USER, password=TEST_PASSWORD)
+ dsn = "host={host} port={port} dbname={dbname} user={user} password={password}".format(**args)
+ self.ag = age.connect(dsn, graph=TEST_GRAPH_NAME, **args)
def tearDown(self):
- age.deleteGraph(self.ag.connection, self.ag.graphName)
+ age.deleteGraph(self.ag.connection, TEST_GRAPH_NAME)
self.ag.close()
def compare_networkX(self, G, H):
@@ -215,19 +231,28 @@
ag = None
ag1 = None
ag2 = None
+ args: argparse.Namespace = argparse.Namespace(
+ host=TEST_HOST,
+ port=TEST_PORT,
+ database=TEST_DB,
+ user=TEST_USER,
+ password=TEST_PASSWORD,
+ graphName=TEST_GRAPH_NAME
+ )
def setUp(self):
- TEST_DB = self.args.database
- TEST_USER = self.args.user
- TEST_PASSWORD = self.args.password
- TEST_PORT = self.args.port
- TEST_HOST = self.args.host
- self.ag = age.connect(graph=TEST_GRAPH_NAME, host=TEST_HOST, port=TEST_PORT,
- dbname=TEST_DB, user=TEST_USER, password=TEST_PASSWORD)
- self.ag1 = age.connect(graph=ORIGINAL_GRAPH, host=TEST_HOST, port=TEST_PORT,
- dbname=TEST_DB, user=TEST_USER, password=TEST_PASSWORD)
- self.ag2 = age.connect(graph=EXPECTED_GRAPH, host=TEST_HOST, port=TEST_PORT,
- dbname=TEST_DB, user=TEST_USER, password=TEST_PASSWORD)
+ args = dict(
+ host=self.args.host,
+ port=self.args.port,
+ dbname=self.args.database,
+ user=self.args.user,
+ password=self.args.password
+ )
+
+ dsn = "host={host} port={port} dbname={dbname} user={user} password={password}".format(**args)
+ self.ag = age.connect(dsn, graph=TEST_GRAPH_NAME, **args)
+ self.ag1 = age.connect(dsn, graph=ORIGINAL_GRAPH, **args)
+ self.ag2 = age.connect(dsn, graph=EXPECTED_GRAPH, **args)
self.graph = nx.DiGraph()
def tearDown(self):
@@ -441,23 +466,23 @@
parser.add_argument('-host',
'--host',
help='Optional Host Name. Default Host is "127.0.0.1" ',
- default="127.0.0.1")
+ default=TEST_HOST)
parser.add_argument('-port',
'--port',
help='Optional Port Number. Default port no is 5432',
- default=5432)
+ default=TEST_PORT)
parser.add_argument('-db',
'--database',
help='Required Database Name',
- required=True)
+ default=TEST_DB)
parser.add_argument('-u',
'--user',
help='Required Username Name',
- required=True)
+ default=TEST_USER)
parser.add_argument('-pass',
'--password',
help='Required Password for authentication',
- required=True)
+ default=TEST_PASSWORD)
args = parser.parse_args()
suite = unittest.TestSuite()