Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/python-driver.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
- name: Set up python
uses: actions/setup-python@v4
with:
python-version: '3.10'
python-version: '3.12'

- name: Install pre-requisites
run: |
Expand All @@ -33,7 +33,7 @@ jobs:

- name: Build
run: |
python setup.py install
pip install .

- name: Test
run: |
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,7 @@ age--*.*.*.sql
!age--*--*sql
__pycache__
**/__pycache__
**/.venv
**/apache_age_python.egg-info

drivers/python/build
2 changes: 1 addition & 1 deletion drivers/python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ python -m unittest -v test_agtypes.py

### Build from source
```
python setup.py install
pip install .
```

### For more information about [Apache AGE](https://age.apache.org/)
Expand Down
3 changes: 2 additions & 1 deletion drivers/python/age/age.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
_EXCEPTION_NoConnection = NoConnection()
_EXCEPTION_GraphNotSet = GraphNotSet()

WHITESPACE = re.compile('\s')
WHITESPACE = re.compile(r'\s')


class AgeDumper(psycopg.adapt.Dumper):
Expand Down Expand Up @@ -233,3 +233,4 @@ def cypher(self, cursor:psycopg.cursor, cypherStmt:str, cols:list=None, params:t

# def queryCypher(self, cypherStmt:str, columns:list=None , params:tuple=None) -> psycopg.cursor :
# return queryCypher(self.connection, self.graphName, cypherStmt, columns, params)

48 changes: 48 additions & 0 deletions drivers/python/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "apache-age-python"
version = "0.0.7"
description = "Python driver support for Apache AGE"
readme = "README.md"
requires-python = ">=3.9"
license = "Apache-2.0"
keywords = ["Graph Database", "Apache AGE", "PostgreSQL"]
authors = [
{name = "Ikchan Kwon, Apache AGE", email = "dev-subscribe@age.apache.org"}
]
classifiers = [
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
]
dependencies = [
"psycopg",
"antlr4-python3-runtime==4.11.1",
]

[project.urls]
Homepage = "https://github.com/apache/age/tree/master/drivers/python"
Download = "https://github.com/apache/age/releases"

[tool.setuptools]
packages = ["age", "age.gen", "age.networkx"]
28 changes: 5 additions & 23 deletions drivers/python/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,10 @@
# specific language governing permissions and limitations
# under the License.

from setuptools import setup, find_packages
from age import VERSION
# This setup.py is maintained for backward compatibility.
# All package configuration is in pyproject.toml. For installation,
# use: pip install .

with open("README.md", "r", encoding='utf8') as fh:
long_description = fh.read()
from setuptools import setup

setup(
name = 'apache-age-python',
version = '0.0.7',
description = 'Python driver support for Apache AGE',
long_description=long_description,
long_description_content_type="text/markdown",
author = 'Ikchan Kwon, Apache AGE',
author_email = 'dev-subscribe@age.apache.org',
url = 'https://github.com/apache/age/tree/master/drivers/python',
download_url = 'https://github.com/apache/age/releases' ,
license = 'Apache2.0',
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',
classifiers = [
'Programming Language :: Python :: 3.9'
]
)
setup()
58 changes: 43 additions & 15 deletions regress/expected/age_load.out
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
\! cp -r regress/age_load/data regress/instance/data/age_load
\! rm -rf /tmp/age/age_load
\! mkdir -p /tmp/age
\! cp -r regress/age_load/data /tmp/age/age_load
LOAD 'age';
SET search_path TO ag_catalog;
-- Create a country using CREATE clause
Expand All @@ -43,13 +45,6 @@ SELECT load_labels_from_file('agload_test_graph', 'Country',

(1 row)

-- A temporary table should have been created with 54 ids; 1 from CREATE and 53 from file
SELECT COUNT(*)=54 FROM "_agload_test_graph_ag_vertex_ids";
?column?
----------
t
(1 row)

-- Sequence should be equal to max entry id i.e. 248
SELECT currval('agload_test_graph."Country_id_seq"')=248;
?column?
Expand All @@ -74,13 +69,6 @@ NOTICE: VLabel "City" has been created

(1 row)

-- Temporary table should have 54+72485 rows now
SELECT COUNT(*)=54+72485 FROM "_agload_test_graph_ag_vertex_ids";
?column?
----------
t
(1 row)

-- Sequence should be equal to max entry id i.e. 146941
SELECT currval('agload_test_graph."City_id_seq"')=146941;
?column?
Expand Down Expand Up @@ -415,6 +403,43 @@ SELECT * FROM cypher('agload_conversion', $$ MATCH ()-[e:Edges2]->() RETURN prop
{"bool": "false", "string": "nUll", "numeric": "3.14"}
(6 rows)

--
-- Check sandbox
--
-- check null file name
SELECT load_labels_from_file('agload_conversion', 'Person1', NULL, true, true);
ERROR: file path must not be NULL
SELECT load_edges_from_file('agload_conversion', 'Edges1', NULL, true);
ERROR: file path must not be NULL
-- check no file name
SELECT load_labels_from_file('agload_conversion', 'Person1', '', true, true);
ERROR: file name cannot be zero length
SELECT load_edges_from_file('agload_conversion', 'Edges1', '', true);
ERROR: file name cannot be zero length
-- check for file/path does not exist
SELECT load_labels_from_file('agload_conversion', 'Person1', 'age_load_xxx/conversion_vertices.csv', true, true);
ERROR: File or path does not exist [/tmp/age/age_load_xxx/conversion_vertices.csv]
SELECT load_edges_from_file('agload_conversion', 'Edges1', 'age_load_xxx/conversion_edges.csv', true);
ERROR: File or path does not exist [/tmp/age/age_load_xxx/conversion_edges.csv]
SELECT load_labels_from_file('agload_conversion', 'Person1', 'age_load/conversion_vertices.txt', true, true);
ERROR: File or path does not exist [/tmp/age/age_load/conversion_vertices.txt]
SELECT load_edges_from_file('agload_conversion', 'Edges1', 'age_load/conversion_edges.txt', true);
ERROR: File or path does not exist [/tmp/age/age_load/conversion_edges.txt]
-- check wrong extension
\! touch /tmp/age/age_load/conversion_vertices.txt
\! touch /tmp/age/age_load/conversion_edges.txt
SELECT load_labels_from_file('agload_conversion', 'Person1', 'age_load/conversion_vertices.txt', true, true);
ERROR: You can only load files with extension [.csv].
SELECT load_edges_from_file('agload_conversion', 'Edges1', 'age_load/conversion_edges.txt', true);
ERROR: You can only load files with extension [.csv].
-- check outside sandbox directory
SELECT load_labels_from_file('agload_conversion', 'Person1', '../../etc/passwd', true, true);
ERROR: You can only load files located in [/tmp/age/].
SELECT load_edges_from_file('agload_conversion', 'Edges1', '../../etc/passwd', true);
ERROR: You can only load files located in [/tmp/age/].
--
-- Cleanup
--
SELECT drop_graph('agload_conversion', true);
NOTICE: drop cascades to 6 other objects
DETAIL: drop cascades to table agload_conversion._ag_label_vertex
Expand All @@ -429,3 +454,6 @@ NOTICE: graph "agload_conversion" has been dropped

(1 row)

--
-- End
--
141 changes: 140 additions & 1 deletion regress/expected/catalog.out
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,146 @@ NOTICE: graph does not exist
(1 row)

DROP FUNCTION raise_notice(TEXT);
-- dropping the graph
--
-- Fix issue 2245 - Creating more than 41 vlabels causes drop_graph to fail with
-- label (relation) cache corrupted
--
-- this result will change if another graph was created prior to this point.
SELECT count(*) FROM ag_label;
count
-------
2
(1 row)

SELECT * FROM create_graph('issue_2245');
NOTICE: graph "issue_2245" has been created
create_graph
--------------

(1 row)

SELECT * FROM cypher('issue_2245', $$
CREATE (a1:Part1 {part_num: '123'}), (a2:Part2 {part_num: '345'}), (a3:Part3 {part_num: '456'}),
(a4:Part4 {part_num: '789'}), (a5:Part5 {part_num: '123'}), (a6:Part6 {part_num: '345'}),
(a7:Part7 {part_num: '456'}), (a8:Part8 {part_num: '789'}), (a9:Part9 {part_num: '123'}),
(a10:Part10 {part_num: '345'}), (a11:Part11 {part_num: '456'}), (a12:Part12 {part_num: '789'}),
(a13:Part13 {part_num: '123'}), (a14:Part14 {part_num: '345'}), (a15:Part15 {part_num: '456'}),
(a16:Part16 {part_num: '789'}), (a17:Part17 {part_num: '123'}), (a18:Part18 {part_num: '345'}),
(a19:Part19 {part_num: '456'}), (a20:Part20 {part_num: '789'}), (a21:Part21 {part_num: '123'}),
(a22:Part22 {part_num: '345'}), (a23:Part23 {part_num: '456'}), (a24:Part24 {part_num: '789'}),
(a25:Part25 {part_num: '123'}), (a26:Part26 {part_num: '345'}), (a27:Part27 {part_num: '456'}),
(a28:Part28 {part_num: '789'}), (a29:Part29 {part_num: '789'}), (a30:Part30 {part_num: '123'}),
(a31:Part31 {part_num: '345'}), (a32:Part32 {part_num: '456'}), (a33:Part33 {part_num: '789'}),
(a34:Part34 {part_num: '123'}), (a35:Part35 {part_num: '345'}), (a36:Part36 {part_num: '456'}),
(a37:Part37 {part_num: '789'}), (a38:Part38 {part_num: '123'}), (a39:Part39 {part_num: '345'}),
(a40:Part40 {part_num: '456'}), (a41:Part41 {part_num: '789'}), (a42:Part42 {part_num: '345'}),
(a43:Part43 {part_num: '456'}), (a44:Part44 {part_num: '789'}), (a45:Part45 {part_num: '456'}),
(a46:Part46 {part_num: '789'}), (a47:Part47 {part_num: '456'}), (a48:Part48 {part_num: '789'}),
(a49:Part49 {part_num: '789'}), (a50:Part50 {part_num: '456'}), (a51:Part51 {part_num: '789'})
$$) AS (result agtype);
result
--------
(0 rows)

SELECT count(*) FROM ag_label;
count
-------
55
(1 row)

SELECT drop_graph('issue_2245', true);
NOTICE: drop cascades to 53 other objects
DETAIL: drop cascades to table issue_2245._ag_label_vertex
drop cascades to table issue_2245._ag_label_edge
drop cascades to table issue_2245."Part1"
drop cascades to table issue_2245."Part2"
drop cascades to table issue_2245."Part3"
drop cascades to table issue_2245."Part4"
drop cascades to table issue_2245."Part5"
drop cascades to table issue_2245."Part6"
drop cascades to table issue_2245."Part7"
drop cascades to table issue_2245."Part8"
drop cascades to table issue_2245."Part9"
drop cascades to table issue_2245."Part10"
drop cascades to table issue_2245."Part11"
drop cascades to table issue_2245."Part12"
drop cascades to table issue_2245."Part13"
drop cascades to table issue_2245."Part14"
drop cascades to table issue_2245."Part15"
drop cascades to table issue_2245."Part16"
drop cascades to table issue_2245."Part17"
drop cascades to table issue_2245."Part18"
drop cascades to table issue_2245."Part19"
drop cascades to table issue_2245."Part20"
drop cascades to table issue_2245."Part21"
drop cascades to table issue_2245."Part22"
drop cascades to table issue_2245."Part23"
drop cascades to table issue_2245."Part24"
drop cascades to table issue_2245."Part25"
drop cascades to table issue_2245."Part26"
drop cascades to table issue_2245."Part27"
drop cascades to table issue_2245."Part28"
drop cascades to table issue_2245."Part29"
drop cascades to table issue_2245."Part30"
drop cascades to table issue_2245."Part31"
drop cascades to table issue_2245."Part32"
drop cascades to table issue_2245."Part33"
drop cascades to table issue_2245."Part34"
drop cascades to table issue_2245."Part35"
drop cascades to table issue_2245."Part36"
drop cascades to table issue_2245."Part37"
drop cascades to table issue_2245."Part38"
drop cascades to table issue_2245."Part39"
drop cascades to table issue_2245."Part40"
drop cascades to table issue_2245."Part41"
drop cascades to table issue_2245."Part42"
drop cascades to table issue_2245."Part43"
drop cascades to table issue_2245."Part44"
drop cascades to table issue_2245."Part45"
drop cascades to table issue_2245."Part46"
drop cascades to table issue_2245."Part47"
drop cascades to table issue_2245."Part48"
drop cascades to table issue_2245."Part49"
drop cascades to table issue_2245."Part50"
drop cascades to table issue_2245."Part51"
NOTICE: graph "issue_2245" has been dropped
drop_graph
------------

(1 row)

-- this result should be the same as the one before the create_graph
SELECT count(*) FROM ag_label;
count
-------
2
(1 row)

-- create the graph again
SELECT * FROM create_graph('issue_2245');
NOTICE: graph "issue_2245" has been created
create_graph
--------------

(1 row)

SELECT count(*) FROM ag_label;
count
-------
4
(1 row)

-- dropping the graphs
SELECT drop_graph('issue_2245', true);
NOTICE: drop cascades to 2 other objects
DETAIL: drop cascades to table issue_2245._ag_label_vertex
drop cascades to table issue_2245._ag_label_edge
NOTICE: graph "issue_2245" has been dropped
drop_graph
------------

(1 row)

SELECT drop_graph('graph', true);
NOTICE: drop cascades to 2 other objects
DETAIL: drop cascades to table graph._ag_label_vertex
Expand Down
16 changes: 16 additions & 0 deletions regress/expected/cypher.out
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,22 @@ CREATE TABLE my_edges AS
-- create a table of 4 columns, u, e, v, p. should be 5 rows
CREATE TABLE my_detailed_paths AS
(SELECT * FROM cypher('issue_1767', $$ MATCH p=(u)-[e]->(v) RETURN u,e,v,p $$) as (u agtype, e agtype, v agtype, p agtype));
--
-- Issue 2256: A segmentation fault occurs when calling the coalesce function
-- This also occurs with the greatest function too.
--
SELECT * FROM coalesce(1, 0);
coalesce
----------
1
(1 row)

SELECT * FROM greatest(1, 0);
greatest
----------
1
(1 row)

-- dump out the tables
SELECT * FROM my_vertices;
u
Expand Down
Loading