cypher-graphdb 0.2.7__tar.gz → 0.2.8__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cypher_graphdb-0.2.7/src/cypher_graphdb.egg-info → cypher_graphdb-0.2.8}/PKG-INFO +1 -1
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/backendprovider.py +17 -8
- cypher_graphdb-0.2.8/src/cypher_graphdb/settings.py +240 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8/src/cypher_graphdb.egg-info}/PKG-INFO +1 -1
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb.egg-info/SOURCES.txt +1 -0
- cypher_graphdb-0.2.8/tests/unit/test_settings.py +164 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/uv.lock +189 -176
- cypher_graphdb-0.2.7/src/cypher_graphdb/settings.py +0 -119
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/.env.age.example +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/.env.example +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/.env.memgraph.example +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/.github/workflows/ci.yml +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/.github/workflows/publish.yml +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/.github/workflows/release.yml +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/.gitignore +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/.pre-commit-config.yaml +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/AGENTS.md +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/CHANGELOG.md +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/CONTRIBUTING.md +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/LICENSE.md +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/README.md +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/Taskfile.yml +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/cli +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/TODO.md +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/changelog.md +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/css/material.css +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/css/mkdocstrings.css +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/css/style.css +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/design/duckdb-migration.md +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/design/falkordb-integration.md +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/design/hierarchical-export-format.md +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/design/multiple-statement-execution.md +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/design/parameterized-queries-for-typed-models.md +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/design/query-result-immutable-design.md +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/design/read-only-mode.md +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/design/stateless-multi-graph-support.md +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/documentation-guide.md +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/examples/docstring_examples.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/index.md +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/reference/cypher_graphdb/backends/age/index.md +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/reference/cypher_graphdb/backends/index.md +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/reference/cypher_graphdb/cli/index.md +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/reference/cypher_graphdb/cypher/index.md +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/reference/cypher_graphdb/index.md +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/reference/cypher_graphdb/tools/index.md +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/usage/index.md +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/mkdocs.yml +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/pyproject.toml +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/scripts/gen_ref_nav.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/setup.cfg +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/__init__.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/__main__.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/args.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/backend.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/backends/__init__.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/backends/age/__init__.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/backends/age/agebulkwriter.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/backends/age/agegraphdb.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/backends/age/agerowfactories.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/backends/age/agesearch.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/backends/age/ageserializer.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/backends/age/agesqlbuilder.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/backends/age/agtype.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/backends/age/agtype_parser.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/backends/memgraph/__init__.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/backends/memgraph/memgraphdb.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/backends/memgraph/memgraphrowfactories.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cardinality.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/__init__.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/app.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/banner.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/command_manager.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/command_map.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/command_registry.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/__init__.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/add_graph_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/apply_config_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/base_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/clear_graph_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/commit_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/connect_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/create_edge_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/create_graph_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/create_linked_node_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/create_node_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/delete_graphobj_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/disconnect_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/drop_graph_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/dump_backends_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/dump_graphs_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/dump_indexes_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/dump_labels_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/dump_models_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/dump_parsed_query_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/dump_schema_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/dump_statistics_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/execute_cypher_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/execute_file_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/exit_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/export_graph_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/fetch_all_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/fetch_edges_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/fetch_nodes_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/format_output_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/get_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/gid_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/graph_exists_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/graph_op_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/graph_to_tree_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/help_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/import_graph_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/last_result_op_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/load_models_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/resolve_edges_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/rollback_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/search_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/set_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/sql_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/update_graphobj_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/use_graph_command.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/completer.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/config.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/exporter.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/file_executor.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/graphdata.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/graphdb.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/help/_overview.md +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/help/_template.md +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/help/add_graph.md +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/help/exit.md +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/help/export_graph.md +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/help/import_graph.md +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/help/last_result.md +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/help.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/importer.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/prompt.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/promptparser.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/provider.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/renderer.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/runtime.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/schema_cmd.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/settings.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/command_reader.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/config.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypher/.antlr/Cypher.interp +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypher/.antlr/Cypher.tokens +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypher/.antlr/CypherBaseListener.java +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypher/.antlr/CypherLexer.interp +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypher/.antlr/CypherLexer.java +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypher/.antlr/CypherLexer.tokens +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypher/.antlr/CypherListener.java +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypher/.antlr/CypherParser.java +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypher/Cypher.g4 +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypher/Cypher.interp +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypher/Cypher.tokens +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypher/CypherLexer.interp +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypher/CypherLexer.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypher/CypherLexer.tokens +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypher/CypherListener.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypher/CypherParser.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypher/__init__.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypherbuilder.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cyphergraphdb/__init__.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cyphergraphdb/batch.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cyphergraphdb/bulk_normalize.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cyphergraphdb/connection.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cyphergraphdb/criteria.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cyphergraphdb/cyphergraphdb.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cyphergraphdb/indexing.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cyphergraphdb/result.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cyphergraphdb/schema.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cyphergraphdb/search.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cyphergraphdb/sql.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cyphergraphdb/stream_mixin.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypherjson.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypherparser.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/dbpool.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/decorators.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/display.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/exceptions.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/graphops.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/main.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/modelinfo.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/modelprovider.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/models.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/options.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/schema/__init__.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/schema/converter.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/schema/core.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/schema/generator.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/statistics.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/__init__.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/base_exporter.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/base_importer.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/csv_exporter.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/csv_importer.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/csv_source.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/data_flattener.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/excel_exporter.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/excel_importer.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/excel_row_source.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/file_exporter.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/file_importer.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/hierarchical_exporter.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/hierarchical_importer.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/hierarchical_row_source.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/json_importer.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/json_yaml_data_source.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/row_collector.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/row_set.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/row_source.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/tabular_importer.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/yaml_importer.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/utils/__init__.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/utils/collection_utils.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/utils/column_utils.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/utils/connection_utils.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/utils/conversion_utils.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/utils/core_utils.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/utils/schema_merge.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/utils/schema_to_llm.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/utils/schema_utils.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/utils/settings_repr.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/utils/string_utils.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb.egg-info/dependency_links.txt +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb.egg-info/entry_points.txt +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb.egg-info/requires.txt +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb.egg-info/top_level.txt +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/README.md +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/conftest.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/integration/__init__.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/integration/conftest.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/integration/test_basic_operations.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/integration/test_create_or_merge.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/integration/test_example.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/integration/test_indexes_and_bulk.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/integration/test_parameters.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/integration/test_read_only_mode.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/integration/test_streaming.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/test_json_schema_loading.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/test_json_schema_vs_decorators.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/README.md +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/__init__.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/cli/__init__.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/cli/test_cmd_map.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/cli/test_command_registry.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/mock_backend.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_age_serializer.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_age_sqlbuilder.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_agtype_parser.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_backend_capabilities.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_bulk_normalize.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_column_utils.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_command_reader.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_cypherbuilder.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_cypherparser.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_dbpool.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_dict_access_mixin.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_extend_relation_decorator.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_extend_relations.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_graph_id_zero.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_graphops.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_indexing.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_model_inheritance.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_modelinfo.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_modelprovider_loading.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_modelprovider_schemas.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_models.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_prepared_statement_recovery.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_query_timeout.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_schema_converter.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/tools/__init__.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/tools/test_data_flattener.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/tools/test_exporters.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/tools/test_hierarchical_importer.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/tools/test_json_yaml_data_source.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/tools/test_resource_management.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/tools/test_tabular_import.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/utils/test_collection_utils.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/utils/test_connection_utils.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/utils/test_conversion_utils.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/utils/test_core_utils.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/utils/test_schema_merge.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/utils/test_schema_utils.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/utils/test_settings_repr.py +0 -0
- {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/utils/test_string_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cypher_graphdb
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.8
|
|
4
4
|
Summary: ORM like library and CLI for cypher query language supporting graph databases.
|
|
5
5
|
Author-email: Wolfgang Miller <wolfgang.miller@petrarca-labs.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -79,13 +79,18 @@ class BackendProvider(collections.abc.Collection):
|
|
|
79
79
|
return self._backends.get(name.casefold(), None)
|
|
80
80
|
|
|
81
81
|
def resolve(self, name: str) -> CypherBackend:
|
|
82
|
-
"""Load and
|
|
82
|
+
"""Load and return a fresh backend instance for the given name.
|
|
83
|
+
|
|
84
|
+
Each call returns a **new instance** so that multiple pools using the
|
|
85
|
+
same backend type (e.g. two AGE pools with different graph names) get
|
|
86
|
+
independent backend objects. The registry always stores the class, never
|
|
87
|
+
a cached instance.
|
|
83
88
|
|
|
84
89
|
Args:
|
|
85
90
|
name: Identifier of the backend to resolve (case-insensitive).
|
|
86
91
|
|
|
87
92
|
Returns:
|
|
88
|
-
|
|
93
|
+
A new CypherBackend instance, or None if resolution fails.
|
|
89
94
|
|
|
90
95
|
"""
|
|
91
96
|
with self._lock:
|
|
@@ -100,13 +105,17 @@ class BackendProvider(collections.abc.Collection):
|
|
|
100
105
|
if not phase and not self._try_to_load_backend(name):
|
|
101
106
|
break
|
|
102
107
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
+
if result is None:
|
|
109
|
+
return None
|
|
110
|
+
|
|
111
|
+
# Always instantiate from the class. If the registry already holds
|
|
112
|
+
# an instance (legacy / pre-existing code path), use its class.
|
|
113
|
+
if isinstance(result, type) and issubclass(result, CypherBackend):
|
|
114
|
+
return result()
|
|
115
|
+
if isinstance(result, CypherBackend):
|
|
116
|
+
return type(result)()
|
|
108
117
|
|
|
109
|
-
return
|
|
118
|
+
return None
|
|
110
119
|
|
|
111
120
|
def items(self) -> dict[str, CypherBackend | type[CypherBackend]]:
|
|
112
121
|
"""Return a snapshot of the registry mapping names to backends.
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
"""CypherGraphDB library configuration using Pydantic Settings.
|
|
2
|
+
|
|
3
|
+
This module centralizes runtime configuration for the CypherGraphDB library.
|
|
4
|
+
Values can be provided via environment variables (preferred) or fall back to
|
|
5
|
+
the defaults below. A ``Settings`` instance is intended to be retrieved via
|
|
6
|
+
``get_settings`` which caches the object for reuse across the process.
|
|
7
|
+
|
|
8
|
+
Environment variables (default prefix ``CGDB_``): ``CGDB_BACKEND``,
|
|
9
|
+
``CGDB_CINFO``, ``CGDB_GRAPH``, ``CGDB_READ_ONLY``,
|
|
10
|
+
``CGDB_CREATE_GRAPH_IF_NOT_EXISTS``, ``CGDB_QUERY_TIMEOUT_S``.
|
|
11
|
+
|
|
12
|
+
For applications that need multiple independent graph databases in the same
|
|
13
|
+
process, ``Settings.with_prefix("CGDB_TS_")`` produces a Settings object
|
|
14
|
+
bound to a different env-var prefix (``CGDB_TS_BACKEND``, etc.). The default
|
|
15
|
+
prefix is ``CGDB_`` for backward compatibility.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import os
|
|
19
|
+
from functools import lru_cache
|
|
20
|
+
from typing import Any
|
|
21
|
+
|
|
22
|
+
from pydantic import Field, computed_field, field_serializer
|
|
23
|
+
from pydantic.fields import FieldInfo
|
|
24
|
+
from pydantic_settings import BaseSettings, EnvSettingsSource, SettingsConfigDict
|
|
25
|
+
|
|
26
|
+
# Suffixes mapped to Settings fields. The full env var name is the
|
|
27
|
+
# extension's ``env_prefix`` concatenated with one of these suffixes.
|
|
28
|
+
# This is the single source of truth: field definitions below and
|
|
29
|
+
# _PrefixedEnvSource both derive from it.
|
|
30
|
+
_ENV_SUFFIXES: dict[str, str] = {
|
|
31
|
+
"backend": "BACKEND",
|
|
32
|
+
"cinfo": "CINFO",
|
|
33
|
+
"graph": "GRAPH",
|
|
34
|
+
"read_only": "READ_ONLY",
|
|
35
|
+
"create_graph": "CREATE_GRAPH_IF_NOT_EXISTS",
|
|
36
|
+
"query_timeout_s": "QUERY_TIMEOUT_S",
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
DEFAULT_ENV_PREFIX = "CGDB_"
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class _PrefixedEnvSource(EnvSettingsSource):
|
|
43
|
+
"""Env settings source that ignores ``validation_alias`` and reads a custom prefix.
|
|
44
|
+
|
|
45
|
+
Used by :meth:`Settings.with_prefix` to populate a Settings instance from
|
|
46
|
+
environment variables under a custom prefix without falling back to the
|
|
47
|
+
default ``CGDB_*`` aliases declared on each Field.
|
|
48
|
+
|
|
49
|
+
The source disables ``.env`` file loading -- multi-instance setups are
|
|
50
|
+
expected to provide explicit environment variables per backend.
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
def __init__(self, settings_cls: type[BaseSettings], runtime_prefix: str) -> None:
|
|
54
|
+
super().__init__(settings_cls)
|
|
55
|
+
self._runtime_prefix = runtime_prefix.upper()
|
|
56
|
+
|
|
57
|
+
def get_field_value(self, field: FieldInfo, field_name: str) -> tuple[Any, str, bool]:
|
|
58
|
+
"""Look up the env var as ``<prefix><SUFFIX>`` for the given field.
|
|
59
|
+
|
|
60
|
+
Ignores ``validation_alias`` entirely. Returns the raw string value
|
|
61
|
+
if present, or ``(None, field_name, False)`` if absent.
|
|
62
|
+
|
|
63
|
+
Fields not in ``_ENV_SUFFIXES`` (e.g. computed fields) are skipped.
|
|
64
|
+
"""
|
|
65
|
+
suffix = _ENV_SUFFIXES.get(field_name)
|
|
66
|
+
if suffix is None:
|
|
67
|
+
# Computed fields and any future non-env fields are skipped.
|
|
68
|
+
return None, field_name, False
|
|
69
|
+
env_name = f"{self._runtime_prefix}{suffix}"
|
|
70
|
+
# Read env at call time (not construction time) -- consistent with
|
|
71
|
+
# how EnvSettingsSource works and safe for test monkeypatching.
|
|
72
|
+
env_upper = {k.upper(): v for k, v in os.environ.items()}
|
|
73
|
+
value = env_upper.get(env_name)
|
|
74
|
+
if value is not None:
|
|
75
|
+
return value, field_name, False
|
|
76
|
+
return None, field_name, False
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class Settings(BaseSettings):
|
|
80
|
+
"""Runtime CypherGraphDB library settings.
|
|
81
|
+
|
|
82
|
+
Attributes map to environment variables. The default prefix is ``CGDB_``
|
|
83
|
+
so ``backend`` <- ``CGDB_BACKEND``. To use a different prefix (for
|
|
84
|
+
multi-instance setups), construct via ``Settings.with_prefix("CGDB_TS_")``.
|
|
85
|
+
|
|
86
|
+
These settings control the default behavior for CypherGraphDB connections
|
|
87
|
+
and can be overridden at runtime when creating CypherGraphDB instances.
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
backend: str | None = Field(
|
|
91
|
+
default=None,
|
|
92
|
+
description="Default backend type (memgraph, age, etc.)",
|
|
93
|
+
validation_alias=f"{DEFAULT_ENV_PREFIX}{_ENV_SUFFIXES['backend']}",
|
|
94
|
+
)
|
|
95
|
+
cinfo: str | None = Field(
|
|
96
|
+
default=None,
|
|
97
|
+
description="Default connection information/DSN",
|
|
98
|
+
validation_alias=f"{DEFAULT_ENV_PREFIX}{_ENV_SUFFIXES['cinfo']}",
|
|
99
|
+
)
|
|
100
|
+
graph: str | None = Field(
|
|
101
|
+
default=None,
|
|
102
|
+
description="Default graph name",
|
|
103
|
+
validation_alias=f"{DEFAULT_ENV_PREFIX}{_ENV_SUFFIXES['graph']}",
|
|
104
|
+
)
|
|
105
|
+
read_only: bool = Field(
|
|
106
|
+
default=False,
|
|
107
|
+
description="Enable read-only mode (prevents write operations)",
|
|
108
|
+
validation_alias=f"{DEFAULT_ENV_PREFIX}{_ENV_SUFFIXES['read_only']}",
|
|
109
|
+
)
|
|
110
|
+
create_graph: bool = Field(
|
|
111
|
+
default=False,
|
|
112
|
+
description="Auto-create graph if it does not exist (AGE only)",
|
|
113
|
+
validation_alias=f"{DEFAULT_ENV_PREFIX}{_ENV_SUFFIXES['create_graph']}",
|
|
114
|
+
)
|
|
115
|
+
query_timeout_s: int | None = Field(
|
|
116
|
+
default=30,
|
|
117
|
+
description=(
|
|
118
|
+
"Maximum seconds a single query may run before the backend cancels it. "
|
|
119
|
+
"Default is 30s -- enough for any legitimate graph query while preventing "
|
|
120
|
+
"runaway queries from exhausting the connection pool. "
|
|
121
|
+
"Set to 0 or None to disable. "
|
|
122
|
+
"AGE: sets PostgreSQL statement_timeout at connection time. "
|
|
123
|
+
"Memgraph: sets database setting query.timeout after connecting."
|
|
124
|
+
),
|
|
125
|
+
validation_alias=f"{DEFAULT_ENV_PREFIX}{_ENV_SUFFIXES['query_timeout_s']}",
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
@computed_field # type: ignore[misc]
|
|
129
|
+
@property
|
|
130
|
+
def cinfo_sanitized(self) -> str | None:
|
|
131
|
+
"""Get sanitized connection info safe for logging."""
|
|
132
|
+
return self._sanitize_cinfo(self.cinfo)
|
|
133
|
+
|
|
134
|
+
def _sanitize_cinfo(self, cinfo: str | None) -> str | None:
|
|
135
|
+
"""Sanitize connection info for safe logging."""
|
|
136
|
+
if not cinfo:
|
|
137
|
+
return None
|
|
138
|
+
|
|
139
|
+
from .utils.connection_utils import sanitize_connection_string_for_logging
|
|
140
|
+
|
|
141
|
+
return sanitize_connection_string_for_logging(cinfo)
|
|
142
|
+
|
|
143
|
+
@field_serializer("cinfo")
|
|
144
|
+
def serialize_cinfo(self, _value: str | None) -> str | None:
|
|
145
|
+
"""Serialize cinfo as sanitized version for safe output."""
|
|
146
|
+
return self.cinfo_sanitized
|
|
147
|
+
|
|
148
|
+
def __repr__(self) -> str:
|
|
149
|
+
"""String representation with sanitized cinfo."""
|
|
150
|
+
from .utils.settings_repr import safe_settings_repr
|
|
151
|
+
|
|
152
|
+
return safe_settings_repr(self, field_sanitizers={"cinfo": lambda _: self.cinfo_sanitized})
|
|
153
|
+
|
|
154
|
+
def __str__(self) -> str:
|
|
155
|
+
"""String representation with sanitized cinfo."""
|
|
156
|
+
from .utils.settings_repr import safe_settings_str
|
|
157
|
+
|
|
158
|
+
return safe_settings_str(self, field_sanitizers={"cinfo": lambda _: self.cinfo_sanitized})
|
|
159
|
+
|
|
160
|
+
model_config = SettingsConfigDict(
|
|
161
|
+
case_sensitive=False,
|
|
162
|
+
extra="ignore", # Ignore unexpected env vars
|
|
163
|
+
env_file=".env", # Optional .env loading (if present)
|
|
164
|
+
env_file_encoding="utf-8",
|
|
165
|
+
populate_by_name=True, # Allow construction by field name (used by with_prefix)
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
@classmethod
|
|
169
|
+
def with_prefix(cls, env_prefix: str) -> Settings:
|
|
170
|
+
"""Build a Settings instance from environment variables with a custom prefix.
|
|
171
|
+
|
|
172
|
+
This enables multi-instance setups where independent CypherGraphDB pools
|
|
173
|
+
each read their own set of env vars. For example, with
|
|
174
|
+
``env_prefix="CGDB_TS_"`` the instance reads ``CGDB_TS_BACKEND``,
|
|
175
|
+
``CGDB_TS_CINFO``, ``CGDB_TS_GRAPH``, etc.
|
|
176
|
+
|
|
177
|
+
Unlike the default ``Settings()`` constructor, this method does NOT
|
|
178
|
+
fall back to the default ``CGDB_*`` env vars or the ``.env`` file -- it
|
|
179
|
+
reads exclusively from env vars matching the given prefix. Pass
|
|
180
|
+
``Settings.with_prefix("CGDB_")`` to read the default prefix without
|
|
181
|
+
consulting ``.env``.
|
|
182
|
+
|
|
183
|
+
Args:
|
|
184
|
+
env_prefix: Prefix to apply to env var names. Must end with ``_``
|
|
185
|
+
by convention (not enforced). Pass ``""`` to read unprefixed
|
|
186
|
+
env vars (``BACKEND``, ``CINFO``, ...).
|
|
187
|
+
|
|
188
|
+
Returns:
|
|
189
|
+
A Settings instance populated from env vars with the given prefix.
|
|
190
|
+
Fields whose env var is not set use the field default.
|
|
191
|
+
|
|
192
|
+
Examples:
|
|
193
|
+
```python
|
|
194
|
+
# Default (reads CGDB_BACKEND, CGDB_GRAPH, ...; also .env)
|
|
195
|
+
settings = Settings()
|
|
196
|
+
|
|
197
|
+
# Scoped, env only -- no .env fallback, no default-prefix fallback
|
|
198
|
+
ts_settings = Settings.with_prefix("CGDB_TS_")
|
|
199
|
+
cg_settings = Settings.with_prefix("CGDB_CG_")
|
|
200
|
+
```
|
|
201
|
+
"""
|
|
202
|
+
from pydantic_core import PydanticUndefinedType
|
|
203
|
+
|
|
204
|
+
source = _PrefixedEnvSource(cls, env_prefix)
|
|
205
|
+
env_data = source()
|
|
206
|
+
# Build kwargs for only the regular (non-computed) fields that are in
|
|
207
|
+
# _ENV_SUFFIXES. For each field:
|
|
208
|
+
# - use the env value if the source found one
|
|
209
|
+
# - use the declared default if it is defined (not PydanticUndefined)
|
|
210
|
+
# - leave absent fields out so pydantic uses its own default mechanism
|
|
211
|
+
# Because we pass a value for every regular field as an init kwarg,
|
|
212
|
+
# pydantic-settings' init_settings source (highest priority) wins over
|
|
213
|
+
# the env/dotenv sources -- masking the default CGDB_* env vars and .env.
|
|
214
|
+
full_kwargs: dict[str, Any] = {}
|
|
215
|
+
for field_name in _ENV_SUFFIXES:
|
|
216
|
+
if field_name in env_data:
|
|
217
|
+
full_kwargs[field_name] = env_data[field_name]
|
|
218
|
+
else:
|
|
219
|
+
field_info = cls.model_fields.get(field_name)
|
|
220
|
+
if field_info is not None and not isinstance(field_info.default, PydanticUndefinedType):
|
|
221
|
+
full_kwargs[field_name] = field_info.default
|
|
222
|
+
else:
|
|
223
|
+
full_kwargs[field_name] = None
|
|
224
|
+
return cls(_env_file=None, **full_kwargs)
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
@lru_cache
|
|
228
|
+
def get_settings() -> Settings:
|
|
229
|
+
"""Return the cached ``Settings`` instance.
|
|
230
|
+
|
|
231
|
+
The first invocation reads environment variables / .env file; subsequent
|
|
232
|
+
calls reuse the same object to ensure consistent config.
|
|
233
|
+
|
|
234
|
+
Returns:
|
|
235
|
+
Settings: The cached settings instance.
|
|
236
|
+
"""
|
|
237
|
+
return Settings()
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
__all__ = ["DEFAULT_ENV_PREFIX", "Settings", "get_settings"]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cypher_graphdb
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.8
|
|
4
4
|
Summary: ORM like library and CLI for cypher query language supporting graph databases.
|
|
5
5
|
Author-email: Wolfgang Miller <wolfgang.miller@petrarca-labs.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -262,6 +262,7 @@ tests/unit/test_models.py
|
|
|
262
262
|
tests/unit/test_prepared_statement_recovery.py
|
|
263
263
|
tests/unit/test_query_timeout.py
|
|
264
264
|
tests/unit/test_schema_converter.py
|
|
265
|
+
tests/unit/test_settings.py
|
|
265
266
|
tests/unit/cli/__init__.py
|
|
266
267
|
tests/unit/cli/test_cmd_map.py
|
|
267
268
|
tests/unit/cli/test_command_registry.py
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"""Unit tests for cypher_graphdb.settings.Settings.
|
|
2
|
+
|
|
3
|
+
Covers:
|
|
4
|
+
- Default prefix behaviour (CGDB_*)
|
|
5
|
+
- Custom env_prefix via Settings.with_prefix()
|
|
6
|
+
- Multi-instance isolation (two settings reading two prefixes)
|
|
7
|
+
- Case-insensitive env var matching
|
|
8
|
+
- Type coercion (bool, int) from prefixed env vars
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import os
|
|
12
|
+
|
|
13
|
+
import pytest
|
|
14
|
+
|
|
15
|
+
from cypher_graphdb.settings import DEFAULT_ENV_PREFIX, Settings, get_settings
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@pytest.fixture(autouse=True)
|
|
19
|
+
def _isolated_env(monkeypatch, tmp_path):
|
|
20
|
+
"""Clear CGDB-related env vars and prevent .env from being read.
|
|
21
|
+
|
|
22
|
+
The local ``.env`` file in the repo root would otherwise pollute these
|
|
23
|
+
tests with real connection strings. We point pydantic-settings at a
|
|
24
|
+
nonexistent file to disable .env loading for the duration of each test.
|
|
25
|
+
"""
|
|
26
|
+
for key in list(os.environ.keys()):
|
|
27
|
+
if "CGDB" in key.upper() or key in {
|
|
28
|
+
"BACKEND",
|
|
29
|
+
"CINFO",
|
|
30
|
+
"GRAPH",
|
|
31
|
+
"READ_ONLY",
|
|
32
|
+
"CREATE_GRAPH_IF_NOT_EXISTS",
|
|
33
|
+
"QUERY_TIMEOUT_S",
|
|
34
|
+
}:
|
|
35
|
+
monkeypatch.delenv(key, raising=False)
|
|
36
|
+
# Patch Settings.model_config to not read any .env during tests.
|
|
37
|
+
monkeypatch.setitem(Settings.model_config, "env_file", str(tmp_path / "nonexistent.env"))
|
|
38
|
+
# Reset the lru_cache.
|
|
39
|
+
get_settings.cache_clear()
|
|
40
|
+
yield
|
|
41
|
+
get_settings.cache_clear()
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class TestDefaultPrefix:
|
|
45
|
+
"""Default CGDB_ prefix behaviour (unchanged)."""
|
|
46
|
+
|
|
47
|
+
def test_reads_default_cgdb_env_vars(self, monkeypatch):
|
|
48
|
+
monkeypatch.setenv("CGDB_BACKEND", "age")
|
|
49
|
+
monkeypatch.setenv("CGDB_CINFO", "postgresql://localhost/x")
|
|
50
|
+
monkeypatch.setenv("CGDB_GRAPH", "techgraph")
|
|
51
|
+
s = Settings()
|
|
52
|
+
assert s.backend == "age"
|
|
53
|
+
assert s.cinfo == "postgresql://localhost/x"
|
|
54
|
+
assert s.graph == "techgraph"
|
|
55
|
+
|
|
56
|
+
def test_defaults_when_no_env_vars(self):
|
|
57
|
+
s = Settings()
|
|
58
|
+
assert s.backend is None
|
|
59
|
+
assert s.cinfo is None
|
|
60
|
+
assert s.graph is None
|
|
61
|
+
assert s.read_only is False
|
|
62
|
+
assert s.create_graph is False
|
|
63
|
+
assert s.query_timeout_s == 30
|
|
64
|
+
|
|
65
|
+
def test_get_settings_returns_cached_instance(self, monkeypatch):
|
|
66
|
+
monkeypatch.setenv("CGDB_BACKEND", "memgraph")
|
|
67
|
+
s1 = get_settings()
|
|
68
|
+
s2 = get_settings()
|
|
69
|
+
assert s1 is s2
|
|
70
|
+
assert s1.backend == "memgraph"
|
|
71
|
+
|
|
72
|
+
def test_default_env_prefix_constant(self):
|
|
73
|
+
assert DEFAULT_ENV_PREFIX == "CGDB_"
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class TestWithPrefix:
|
|
77
|
+
"""Settings.with_prefix() for multi-instance setups."""
|
|
78
|
+
|
|
79
|
+
def test_reads_prefixed_env_vars(self, monkeypatch):
|
|
80
|
+
monkeypatch.setenv("CGDB_TS_BACKEND", "age")
|
|
81
|
+
monkeypatch.setenv("CGDB_TS_CINFO", "postgresql://localhost/techstack")
|
|
82
|
+
monkeypatch.setenv("CGDB_TS_GRAPH", "techgraph")
|
|
83
|
+
s = Settings.with_prefix("CGDB_TS_")
|
|
84
|
+
assert s.backend == "age"
|
|
85
|
+
assert s.cinfo == "postgresql://localhost/techstack"
|
|
86
|
+
assert s.graph == "techgraph"
|
|
87
|
+
|
|
88
|
+
def test_ignores_default_env_vars_when_prefixed(self, monkeypatch):
|
|
89
|
+
# Default vars set, but with_prefix should ignore them.
|
|
90
|
+
monkeypatch.setenv("CGDB_BACKEND", "default-backend")
|
|
91
|
+
monkeypatch.setenv("CGDB_GRAPH", "default-graph")
|
|
92
|
+
# Only the prefixed graph is set.
|
|
93
|
+
monkeypatch.setenv("CGDB_CG_GRAPH", "codegraph")
|
|
94
|
+
s = Settings.with_prefix("CGDB_CG_")
|
|
95
|
+
assert s.backend is None # CGDB_CG_BACKEND not set
|
|
96
|
+
assert s.graph == "codegraph"
|
|
97
|
+
|
|
98
|
+
def test_two_instances_isolated(self, monkeypatch):
|
|
99
|
+
monkeypatch.setenv("CGDB_TS_BACKEND", "age")
|
|
100
|
+
monkeypatch.setenv("CGDB_TS_GRAPH", "techgraph")
|
|
101
|
+
monkeypatch.setenv("CGDB_CG_BACKEND", "memgraph")
|
|
102
|
+
monkeypatch.setenv("CGDB_CG_GRAPH", "codegraph")
|
|
103
|
+
ts = Settings.with_prefix("CGDB_TS_")
|
|
104
|
+
cg = Settings.with_prefix("CGDB_CG_")
|
|
105
|
+
assert ts.backend == "age"
|
|
106
|
+
assert ts.graph == "techgraph"
|
|
107
|
+
assert cg.backend == "memgraph"
|
|
108
|
+
assert cg.graph == "codegraph"
|
|
109
|
+
|
|
110
|
+
def test_with_default_prefix_matches_settings(self, monkeypatch):
|
|
111
|
+
monkeypatch.setenv("CGDB_BACKEND", "age")
|
|
112
|
+
monkeypatch.setenv("CGDB_GRAPH", "g")
|
|
113
|
+
plain = Settings()
|
|
114
|
+
prefixed = Settings.with_prefix(DEFAULT_ENV_PREFIX)
|
|
115
|
+
assert plain.backend == prefixed.backend
|
|
116
|
+
assert plain.graph == prefixed.graph
|
|
117
|
+
|
|
118
|
+
def test_case_insensitive_env_lookup(self, monkeypatch):
|
|
119
|
+
# Lowercase env var should still match (case_sensitive=False).
|
|
120
|
+
monkeypatch.setenv("cgdb_ts_backend", "age")
|
|
121
|
+
s = Settings.with_prefix("CGDB_TS_")
|
|
122
|
+
assert s.backend == "age"
|
|
123
|
+
|
|
124
|
+
def test_bool_coercion(self, monkeypatch):
|
|
125
|
+
monkeypatch.setenv("CGDB_TS_READ_ONLY", "true")
|
|
126
|
+
monkeypatch.setenv("CGDB_TS_CREATE_GRAPH_IF_NOT_EXISTS", "1")
|
|
127
|
+
s = Settings.with_prefix("CGDB_TS_")
|
|
128
|
+
assert s.read_only is True
|
|
129
|
+
assert s.create_graph is True
|
|
130
|
+
|
|
131
|
+
def test_int_coercion(self, monkeypatch):
|
|
132
|
+
monkeypatch.setenv("CGDB_TS_QUERY_TIMEOUT_S", "120")
|
|
133
|
+
s = Settings.with_prefix("CGDB_TS_")
|
|
134
|
+
assert s.query_timeout_s == 120
|
|
135
|
+
|
|
136
|
+
def test_defaults_when_prefixed_env_not_set(self):
|
|
137
|
+
s = Settings.with_prefix("CGDB_UNSET_")
|
|
138
|
+
assert s.backend is None
|
|
139
|
+
assert s.cinfo is None
|
|
140
|
+
assert s.graph is None
|
|
141
|
+
assert s.read_only is False
|
|
142
|
+
assert s.create_graph is False
|
|
143
|
+
assert s.query_timeout_s == 30
|
|
144
|
+
|
|
145
|
+
def test_empty_prefix_reads_all_unprefixed(self, monkeypatch):
|
|
146
|
+
# Empty prefix means read BACKEND/CINFO/GRAPH directly.
|
|
147
|
+
monkeypatch.setenv("BACKEND", "age")
|
|
148
|
+
monkeypatch.setenv("GRAPH", "g")
|
|
149
|
+
s = Settings.with_prefix("")
|
|
150
|
+
assert s.backend == "age"
|
|
151
|
+
assert s.graph == "g"
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
class TestPrefixSanitization:
|
|
155
|
+
"""cinfo sanitization works regardless of prefix source."""
|
|
156
|
+
|
|
157
|
+
def test_sanitized_cinfo_with_prefix(self, monkeypatch):
|
|
158
|
+
monkeypatch.setenv("CGDB_TS_CINFO", "postgresql://user:secret@host/db")
|
|
159
|
+
s = Settings.with_prefix("CGDB_TS_")
|
|
160
|
+
# Sanitized variant must redact the secret.
|
|
161
|
+
assert s.cinfo == "postgresql://user:secret@host/db"
|
|
162
|
+
sanitized = s.cinfo_sanitized
|
|
163
|
+
assert sanitized is not None
|
|
164
|
+
assert "secret" not in sanitized
|