diff --git a/docs/changelog.md b/docs/changelog.md index fd1eff2f..cecb19a3 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,5 +1,19 @@ # Changelog +## v1.9.0 - June 23, 2026 + +### Features and improvements + + +* Fix release process (#387) +* feat: Build for Python 3.14 (#383) +* feat: Migrate to uv (#382) +* Add DOT import (#377) +* Add TensorflowGNN transformer (#353) +* Support Transport of ZonedDateTimes (#370) +* Added missing dependency for publish docs workflow (#368) + + ## v1.8.0 - June 12, 2025 ### Features and improvements diff --git a/docs/reference/gqlalchemy/models.md b/docs/reference/gqlalchemy/models.md index 3b9c7fb7..8657085f 100644 --- a/docs/reference/gqlalchemy/models.md +++ b/docs/reference/gqlalchemy/models.md @@ -146,6 +146,15 @@ Converts the GraphObject class into the appropriate subclass. This is used when deserialising a json representation of the class, or the object returned from the GraphDatabase. +#### model\_validate + +```python +@classmethod +def model_validate(cls, obj, *args, **kwargs) +``` + +Used to convert a dictionary object into the appropriate GraphObject. + #### parse\_obj ```python diff --git a/docs/reference/gqlalchemy/query_builders/memgraph_query_builder.md b/docs/reference/gqlalchemy/query_builders/memgraph_query_builder.md index 081b32ac..bc097a43 100644 --- a/docs/reference/gqlalchemy/query_builders/memgraph_query_builder.md +++ b/docs/reference/gqlalchemy/query_builders/memgraph_query_builder.md @@ -19,7 +19,8 @@ Load data from a CSV file by executing a Cypher query for each row. **Arguments**: -- `path` - A string representing the path to the CSV file. If beginning with `http://`, `https://`, or `ftp://`, the CSV file will be fetched over the network. +- `path` - A string representing the path to the CSV file. If beginning with + "http://", "https://" or "ftp://", the CSV file will be fetched over the network. - `header` - A bool indicating if the CSV file starts with a header row. - `row` - A string representing the name of the variable for iterating over each row. @@ -34,13 +35,27 @@ Load data from a CSV file by executing a Cypher query for each row. Load CSV with header: -- `Python` - `load_csv(path="path/to/my/file.csv", header=True, row="row").return_().execute()` -- `Cypher` - `LOAD CSV FROM "path/to/my/file.csv" WITH HEADER AS row RETURN *;` + - Python: + ```python + load_csv(path="path/to/my/file.csv", header=True, row="row").return_().execute() + ``` + + - Cypher: + ```cypher + LOAD CSV FROM "path/to/my/file.csv" WITH HEADER AS row RETURN *; + ``` Load CSV without header: -- `Python` - `load_csv(path="path/to/my/file.csv", header=False, row="row").return_().execute()` -- `Cypher` - `LOAD CSV FROM "path/to/my/file.csv" NO HEADER AS row RETURN *;` + - Python: + ```python + load_csv(path="path/to/my/file.csv", header=False, row="row").return_().execute() + ``` + + - Cypher: + ```cypher + LOAD CSV FROM "path/to/my/file.csv" NO HEADER AS row RETURN *; + ``` #### call @@ -55,7 +70,7 @@ def call(procedure: str, subgraph_path: str = None) -> "DeclarativeBase" ``` -Override of base class method to support Memgraph subgraph functionality. +Override of base class method to support Memgraph's subgraph functionality. Method can be called with node labels and relationship types, both being optional, which are used to construct a subgraph, or if neither is provided, a subgraph query is used, which can be passed as a string representing a @@ -64,7 +79,7 @@ Cypher query defining the MATCH clause which selects the nodes and relationships **Arguments**: - `procedure` - A string representing the name of the procedure in the - format `query_module.procedure`. + format "query_module.procedure". - `arguments` - A string representing the arguments of the procedure in text format. - `node_labels` - Either a string, which is then used as the label for all nodes, or @@ -77,18 +92,34 @@ Cypher query defining the MATCH clause which selects the nodes and relationships **Returns**: - A `DeclarativeBase` instance for constructing queries. + A DeclarativeBase instance for constructing queries. **Examples**: -- `Python` - `call('export_util.json', '/home/user', "LABEL", ["TYPE1", "TYPE2"]).execute()` -- `Cypher` - `MATCH p=(a)-[:TYPE1 | :TYPE2]->(b) WHERE (a:LABEL) AND (b:LABEL) WITH project(p) AS graph CALL export_util.json(graph, "/home/user")` + - Python: + ```python + call('export_util.json', '/home/user', "LABEL", ["TYPE1", "TYPE2"]).execute() + ``` + + - Cypher: + ```cypher + MATCH p=(a)-[:TYPE1 | :TYPE2]->(b) WHERE (a:LABEL) AND (b:LABEL) + WITH project(p) AS graph CALL export_util.json(graph, '/home/user') + ``` or -- `Python` - `call("export_util.json", "/home/user", subgraph_path="(:LABEL)-[:TYPE]->(:LABEL)").execute()` -- `Cypher` - `MATCH p=(:LABEL)-[:TYPE1]->(:LABEL) WITH project(p) AS graph CALL export_util.json(graph, "/home/user")` + - Python: + ```python + call('export_util.json', '/home/user', subgraph_path="(:LABEL)-[:TYPE]->(:LABEL)").execute() + ``` + + - Cypher: + ```cypher + MATCH p=(:LABEL)-[:TYPE1]->(:LABEL) WITH project(p) AS graph + CALL export_util.json(graph, '/home/user') + ``` ## ProjectPartialQuery Objects @@ -104,6 +135,6 @@ def construct_query() -> str Constructs a Project partial query. -Given path part of a query (e.g. (:LABEL)-[:TYPE]->(:LABEL2)), +Given path part of a query (e.g. (:LABEL)-[:TYPE]->(:LABEL2)), adds MATCH, a path identifier and appends the WITH clause. diff --git a/docs/reference/gqlalchemy/transformations/export/graph_transporter.md b/docs/reference/gqlalchemy/transformations/export/graph_transporter.md index 7955690d..85a7b125 100644 --- a/docs/reference/gqlalchemy/transformations/export/graph_transporter.md +++ b/docs/reference/gqlalchemy/transformations/export/graph_transporter.md @@ -33,7 +33,7 @@ graph = transporter.export() **Arguments**: -- `graph_type` - dgl, pyg or nx +- `graph_type` - dgl, pyg, nx or tfgnn #### export diff --git a/docs/reference/gqlalchemy/transformations/importing/graph_importer.md b/docs/reference/gqlalchemy/transformations/importing/graph_importer.md index 0ac6b6a3..921ea52f 100644 --- a/docs/reference/gqlalchemy/transformations/importing/graph_importer.md +++ b/docs/reference/gqlalchemy/transformations/importing/graph_importer.md @@ -29,29 +29,29 @@ Gets cypher queries using the underlying translator and then inserts all queries **Arguments**: -- `graph` - dgl, pytorch geometric or nx graph instance. +- `graph` - dgl, pytorch geometric, dot or nx graph instance. -#### translate_dot_file +#### translate\_dot\_file ```python def translate_dot_file(path: str) -> None ``` -Parses a DOT file into a NetworkX graph and imports it to Memgraph. This method is available when `graph_type="NX"`. +Parses a DOT file to a NetworkX graph and imports it to Memgraph. This method is available when ```graph_type="NX"``` **Arguments**: -- `path` - Path to a DOT file. + - ``path`` - Path to a DOT file. -#### translate_dot_data +#### translate\_dot\_data ```python def translate_dot_data(dot_data: str) -> None ``` -Parses DOT content from a string into a NetworkX graph and imports it to Memgraph. This method is available when `graph_type="NX"`. +Parses DOT content to a NetworkX graph and imports it to Memgraph. This method is available when ```graph_type="NX"```. **Arguments**: -- `dot_data` - Raw DOT graph content. + - ``dot_data`` - Raw DOT graph content. diff --git a/docs/reference/gqlalchemy/vendors/memgraph.md b/docs/reference/gqlalchemy/vendors/memgraph.md index 6af1468c..dd5d3568 100644 --- a/docs/reference/gqlalchemy/vendors/memgraph.md +++ b/docs/reference/gqlalchemy/vendors/memgraph.md @@ -340,7 +340,6 @@ Terminate transactions in the database. - `List[MemgraphTerminatedTransaction]` - A list of MemgraphTerminatedTransaction objects with info on their status. - #### get\_storage\_info ```python @@ -351,7 +350,15 @@ Get detailed storage information about the database instance. **Returns**: -- `List[dict]` - A list of dictionaries with 'storage info' and 'value' keys containing storage metrics like name, vertex_count, edge_count, memory_res, disk_usage, etc. +- `List[dict]` - A list of dictionaries with 'storage info' and 'value' keys containing: + - name: Current database name + - vertex_count: Total number of stored nodes + - edge_count: Total number of stored relationships + - average_degree: Average number of relationships per node + - memory_res: Non-swapped physical RAM memory used + - disk_usage: Data directory disk space consumption + - memory_tracked: RAM allocated and tracked by Memgraph + - and other storage-related metrics #### get\_build\_info @@ -363,7 +370,8 @@ Get build information about the Memgraph instance. **Returns**: -- `List[dict]` - A list of dictionaries with 'build info' and 'value' keys containing build_type (the optimization level). +- `List[dict]` - A list of dictionaries with 'build info' and 'value' keys containing: + - build_type: The optimization level the instance was built with #### analyze\_graph @@ -378,11 +386,19 @@ to select more optimal indexes and MERGE operations. **Arguments**: -- `labels` _Optional[List[str]]_ - Optional list of labels to analyze. If None, analyzes all labels. +- `labels` - Optional list of labels to analyze. If None, analyzes all labels. + **Returns**: -- `List[dict]` - A list of dictionaries containing analysis results with keys: label, property, num estimation nodes, num groups, avg group size, chi-squared value, avg degree. +- `List[dict]` - A list of dictionaries containing analysis results with keys: + - label: Index's label + - property: Index's property + - num estimation nodes: Nodes used for estimation + - num groups: Distinct property values + - avg group size: Average group size per value + - chi-squared value: Statistical distribution measure + - avg degree: Average degree of indexed nodes #### delete\_graph\_statistics @@ -392,12 +408,18 @@ def delete_graph_statistics(labels: Optional[List[str]] = None) -> List[dict] Delete graph statistics previously calculated by analyze_graph. +Use this to reset the analysis data if you want to recalculate statistics +after significant changes to the graph structure or data. + **Arguments**: -- `labels` _Optional[List[str]]_ - Optional list of labels to delete statistics for. If None, deletes statistics for all labels. + labels ``_Optional[List[str]]_``: Optional list of labels to delete statistics for. + If None, deletes statistics for all labels. + **Returns**: -- `List[dict]` - A list of dictionaries containing deleted index info with keys: label, property. - +- `List[dict]` - A list of dictionaries containing deleted index info with keys: + - label: The deleted index's label + - property: The deleted index's property diff --git a/gqlalchemy/models.py b/gqlalchemy/models.py index d3925907..008c3ee9 100644 --- a/gqlalchemy/models.py +++ b/gqlalchemy/models.py @@ -512,6 +512,9 @@ def model_validate(cls, obj, *args, **kwargs): def parse_obj(cls, obj): """Used to convert a dictionary object into the appropriate GraphObject. + + Compatibility note: `parse_obj` is retained for backward compatibility. + For Pydantic v2-style usage, prefer `model_validate`. """ return cls.model_validate(obj) diff --git a/gqlalchemy/query_builders/memgraph_query_builder.py b/gqlalchemy/query_builders/memgraph_query_builder.py index ae6f16a9..65178fa6 100644 --- a/gqlalchemy/query_builders/memgraph_query_builder.py +++ b/gqlalchemy/query_builders/memgraph_query_builder.py @@ -58,7 +58,8 @@ def load_csv(self, path: str, header: bool, row: str) -> "DeclarativeBase": """Load data from a CSV file by executing a Cypher query for each row. Args: - path: A string representing the path to the CSV file. If beginning with `http://`, `https://`, or `ftp://`, the CSV file will be fetched over the network. + path: A string representing the path to the CSV file. If beginning with + "http://", "https://" or "ftp://", the CSV file will be fetched over the network. header: A bool indicating if the CSV file starts with a header row. row: A string representing the name of the variable for iterating over each row. @@ -69,13 +70,28 @@ def load_csv(self, path: str, header: bool, row: str) -> "DeclarativeBase": Examples: Load CSV with header: - Python: `load_csv(path="path/to/my/file.csv", header=True, row="row").return_().execute()` - Cypher: `LOAD CSV FROM 'path/to/my/file.csv' WITH HEADER AS row RETURN *;` + - Python: + ```python + load_csv(path="path/to/my/file.csv", header=True, row="row").return_().execute() + ``` + + - Cypher: + ```cypher + LOAD CSV FROM "path/to/my/file.csv" WITH HEADER AS row RETURN *; + ``` Load CSV without header: - Python: `load_csv(path='path/to/my/file.csv', header=False, row='row').return_().execute()` - Cypher: `LOAD CSV FROM 'path/to/my/file.csv' NO HEADER AS row RETURN *;` + - Python: + ```python + load_csv(path="path/to/my/file.csv", header=False, row="row").return_().execute() + ``` + + - Cypher: + ```cypher + LOAD CSV FROM "path/to/my/file.csv" NO HEADER AS row RETURN *; + ``` + """ self._query.append(LoadCsvPartialQuery(path, header, row)) @@ -123,7 +139,7 @@ def call( Args: procedure: A string representing the name of the procedure in the - format `query_module.procedure`. + format "query_module.procedure". arguments: A string representing the arguments of the procedure in text format. node_labels: Either a string, which is then used as the label for all nodes, or @@ -134,18 +150,32 @@ def call( subgraph_path: Optional way to define the subgraph via a Cypher MATCH clause. Returns: - A `DeclarativeBase` instance for constructing queries. + A DeclarativeBase instance for constructing queries. Examples: - Python: `call('export_util.json', '/home/user', "LABEL", ["TYPE1", "TYPE2"]).execute() - Cypher: `MATCH p=(a)-[:TYPE1 | :TYPE2]->(b) WHERE (a:LABEL) AND (b:LABEL) - WITH project(p) AS graph CALL export_util.json(graph, '/home/user')` + - Python: + ```python + call('export_util.json', '/home/user', "LABEL", ["TYPE1", "TYPE2"]).execute() + ``` + + - Cypher: + ```cypher + MATCH p=(a)-[:TYPE1 | :TYPE2]->(b) WHERE (a:LABEL) AND (b:LABEL) + WITH project(p) AS graph CALL export_util.json(graph, '/home/user') + ``` or - Python: `call('export_util.json', '/home/user', subgraph_path="(:LABEL)-[:TYPE]->(:LABEL)").execute() - Cypher: `MATCH p=(:LABEL)-[:TYPE1]->(:LABEL) WITH project(p) AS graph - CALL export_util.json(graph, '/home/user')` + - Python: + ```python + call('export_util.json', '/home/user', subgraph_path="(:LABEL)-[:TYPE]->(:LABEL)").execute() + ``` + + - Cypher: + ```cypher + MATCH p=(:LABEL)-[:TYPE1]->(:LABEL) WITH project(p) AS graph + CALL export_util.json(graph, '/home/user') + ``` """ if not (node_labels is None and relationship_types is None): diff --git a/gqlalchemy/transformations/importing/graph_importer.py b/gqlalchemy/transformations/importing/graph_importer.py index a60f33b8..9262f3ea 100644 --- a/gqlalchemy/transformations/importing/graph_importer.py +++ b/gqlalchemy/transformations/importing/graph_importer.py @@ -86,7 +86,11 @@ def translate(self, graph) -> None: memgraph.execute(query) def translate_dot_file(self, path: str) -> None: - """Parses a DOT file to a NetworkX graph and imports it to Memgraph.""" + """Parses a DOT file to a NetworkX graph and imports it to Memgraph. This method is available when ```graph_type="NX"``` + + Args: + - ``path`` - Path to a DOT file. + """ self._raise_if_not_nx_importer() raise_if_not_imported(dependency=pydot, dependency_name="pydot") @@ -98,7 +102,11 @@ def translate_dot_file(self, path: str) -> None: self.translate(graph) def translate_dot_data(self, dot_data: str) -> None: - """Parses DOT content to a NetworkX graph and imports it to Memgraph.""" + """Parses DOT content to a NetworkX graph and imports it to Memgraph. This method is available when ```graph_type="NX"```. + + Args: + - ``dot_data`` - Raw DOT graph content. + """ self._raise_if_not_nx_importer() raise_if_not_imported(dependency=pydot, dependency_name="pydot") diff --git a/gqlalchemy/vendors/memgraph.py b/gqlalchemy/vendors/memgraph.py index 9a57f63a..00c138a9 100644 --- a/gqlalchemy/vendors/memgraph.py +++ b/gqlalchemy/vendors/memgraph.py @@ -631,7 +631,7 @@ def delete_graph_statistics(self, labels: Optional[List[str]] = None) -> List[di after significant changes to the graph structure or data. Args: - labels: Optional list of labels to delete statistics for. + labels ``_Optional[List[str]]_``: Optional list of labels to delete statistics for. If None, deletes statistics for all labels. Returns: diff --git a/pydoc-markdown.yml b/pydoc-markdown.yml index eb5eb215..e9780364 100644 --- a/pydoc-markdown.yml +++ b/pydoc-markdown.yml @@ -2,9 +2,9 @@ loaders: - type: python search_path: [.] modules: - - gqlalchemy.connection + - gqlalchemy.connection - gqlalchemy.disk_storage - - gqlalchemy.exceptions + - gqlalchemy.exceptions - gqlalchemy.instance_runner - gqlalchemy.models - gqlalchemy.utilities @@ -31,6 +31,12 @@ loaders: processors: - type: filter skip_empty_modules: true + expression: > + not ( + name == 'Field' + and obj.location.filename.replace('\\', '/').endswith('gqlalchemy/models.py') + ) + and default() - type: smart - type: crossref renderer: @@ -39,3 +45,5 @@ renderer: relative_output_path: reference relative_sidebar_path: sidebar.json sidebar_top_level_label: 'Reference' + markdown: + escape_html_in_docstring: true diff --git a/pyproject.toml b/pyproject.toml index 11eacc4d..15ef7184 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "GQLAlchemy" -version = "1.8.0" +version = "1.9.0" description = "GQLAlchemy is a library developed to assist with writing and running queries in Memgraph." readme = "README.md" license = "Apache-2.0"