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.
Files changed (286) hide show
  1. {cypher_graphdb-0.2.7/src/cypher_graphdb.egg-info → cypher_graphdb-0.2.8}/PKG-INFO +1 -1
  2. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/backendprovider.py +17 -8
  3. cypher_graphdb-0.2.8/src/cypher_graphdb/settings.py +240 -0
  4. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8/src/cypher_graphdb.egg-info}/PKG-INFO +1 -1
  5. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb.egg-info/SOURCES.txt +1 -0
  6. cypher_graphdb-0.2.8/tests/unit/test_settings.py +164 -0
  7. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/uv.lock +189 -176
  8. cypher_graphdb-0.2.7/src/cypher_graphdb/settings.py +0 -119
  9. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/.env.age.example +0 -0
  10. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/.env.example +0 -0
  11. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/.env.memgraph.example +0 -0
  12. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/.github/workflows/ci.yml +0 -0
  13. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/.github/workflows/publish.yml +0 -0
  14. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/.github/workflows/release.yml +0 -0
  15. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/.gitignore +0 -0
  16. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/.pre-commit-config.yaml +0 -0
  17. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/AGENTS.md +0 -0
  18. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/CHANGELOG.md +0 -0
  19. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/CONTRIBUTING.md +0 -0
  20. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/LICENSE.md +0 -0
  21. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/README.md +0 -0
  22. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/Taskfile.yml +0 -0
  23. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/cli +0 -0
  24. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/TODO.md +0 -0
  25. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/changelog.md +0 -0
  26. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/css/material.css +0 -0
  27. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/css/mkdocstrings.css +0 -0
  28. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/css/style.css +0 -0
  29. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/design/duckdb-migration.md +0 -0
  30. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/design/falkordb-integration.md +0 -0
  31. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/design/hierarchical-export-format.md +0 -0
  32. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/design/multiple-statement-execution.md +0 -0
  33. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/design/parameterized-queries-for-typed-models.md +0 -0
  34. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/design/query-result-immutable-design.md +0 -0
  35. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/design/read-only-mode.md +0 -0
  36. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/design/stateless-multi-graph-support.md +0 -0
  37. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/documentation-guide.md +0 -0
  38. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/examples/docstring_examples.py +0 -0
  39. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/index.md +0 -0
  40. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/reference/cypher_graphdb/backends/age/index.md +0 -0
  41. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/reference/cypher_graphdb/backends/index.md +0 -0
  42. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/reference/cypher_graphdb/cli/index.md +0 -0
  43. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/reference/cypher_graphdb/cypher/index.md +0 -0
  44. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/reference/cypher_graphdb/index.md +0 -0
  45. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/reference/cypher_graphdb/tools/index.md +0 -0
  46. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/docs/usage/index.md +0 -0
  47. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/mkdocs.yml +0 -0
  48. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/pyproject.toml +0 -0
  49. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/scripts/gen_ref_nav.py +0 -0
  50. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/setup.cfg +0 -0
  51. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/__init__.py +0 -0
  52. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/__main__.py +0 -0
  53. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/args.py +0 -0
  54. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/backend.py +0 -0
  55. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/backends/__init__.py +0 -0
  56. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/backends/age/__init__.py +0 -0
  57. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/backends/age/agebulkwriter.py +0 -0
  58. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/backends/age/agegraphdb.py +0 -0
  59. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/backends/age/agerowfactories.py +0 -0
  60. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/backends/age/agesearch.py +0 -0
  61. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/backends/age/ageserializer.py +0 -0
  62. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/backends/age/agesqlbuilder.py +0 -0
  63. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/backends/age/agtype.py +0 -0
  64. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/backends/age/agtype_parser.py +0 -0
  65. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/backends/memgraph/__init__.py +0 -0
  66. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/backends/memgraph/memgraphdb.py +0 -0
  67. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/backends/memgraph/memgraphrowfactories.py +0 -0
  68. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cardinality.py +0 -0
  69. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/__init__.py +0 -0
  70. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/app.py +0 -0
  71. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/banner.py +0 -0
  72. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/command_manager.py +0 -0
  73. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/command_map.py +0 -0
  74. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/command_registry.py +0 -0
  75. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/__init__.py +0 -0
  76. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/add_graph_command.py +0 -0
  77. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/apply_config_command.py +0 -0
  78. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/base_command.py +0 -0
  79. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/clear_graph_command.py +0 -0
  80. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/commit_command.py +0 -0
  81. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/connect_command.py +0 -0
  82. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/create_edge_command.py +0 -0
  83. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/create_graph_command.py +0 -0
  84. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/create_linked_node_command.py +0 -0
  85. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/create_node_command.py +0 -0
  86. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/delete_graphobj_command.py +0 -0
  87. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/disconnect_command.py +0 -0
  88. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/drop_graph_command.py +0 -0
  89. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/dump_backends_command.py +0 -0
  90. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/dump_graphs_command.py +0 -0
  91. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/dump_indexes_command.py +0 -0
  92. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/dump_labels_command.py +0 -0
  93. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/dump_models_command.py +0 -0
  94. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/dump_parsed_query_command.py +0 -0
  95. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/dump_schema_command.py +0 -0
  96. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/dump_statistics_command.py +0 -0
  97. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/execute_cypher_command.py +0 -0
  98. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/execute_file_command.py +0 -0
  99. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/exit_command.py +0 -0
  100. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/export_graph_command.py +0 -0
  101. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/fetch_all_command.py +0 -0
  102. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/fetch_edges_command.py +0 -0
  103. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/fetch_nodes_command.py +0 -0
  104. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/format_output_command.py +0 -0
  105. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/get_command.py +0 -0
  106. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/gid_command.py +0 -0
  107. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/graph_exists_command.py +0 -0
  108. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/graph_op_command.py +0 -0
  109. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/graph_to_tree_command.py +0 -0
  110. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/help_command.py +0 -0
  111. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/import_graph_command.py +0 -0
  112. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/last_result_op_command.py +0 -0
  113. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/load_models_command.py +0 -0
  114. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/resolve_edges_command.py +0 -0
  115. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/rollback_command.py +0 -0
  116. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/search_command.py +0 -0
  117. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/set_command.py +0 -0
  118. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/sql_command.py +0 -0
  119. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/update_graphobj_command.py +0 -0
  120. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/commands/use_graph_command.py +0 -0
  121. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/completer.py +0 -0
  122. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/config.py +0 -0
  123. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/exporter.py +0 -0
  124. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/file_executor.py +0 -0
  125. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/graphdata.py +0 -0
  126. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/graphdb.py +0 -0
  127. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/help/_overview.md +0 -0
  128. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/help/_template.md +0 -0
  129. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/help/add_graph.md +0 -0
  130. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/help/exit.md +0 -0
  131. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/help/export_graph.md +0 -0
  132. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/help/import_graph.md +0 -0
  133. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/help/last_result.md +0 -0
  134. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/help.py +0 -0
  135. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/importer.py +0 -0
  136. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/prompt.py +0 -0
  137. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/promptparser.py +0 -0
  138. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/provider.py +0 -0
  139. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/renderer.py +0 -0
  140. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/runtime.py +0 -0
  141. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/schema_cmd.py +0 -0
  142. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cli/settings.py +0 -0
  143. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/command_reader.py +0 -0
  144. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/config.py +0 -0
  145. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypher/.antlr/Cypher.interp +0 -0
  146. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypher/.antlr/Cypher.tokens +0 -0
  147. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypher/.antlr/CypherBaseListener.java +0 -0
  148. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypher/.antlr/CypherLexer.interp +0 -0
  149. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypher/.antlr/CypherLexer.java +0 -0
  150. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypher/.antlr/CypherLexer.tokens +0 -0
  151. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypher/.antlr/CypherListener.java +0 -0
  152. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypher/.antlr/CypherParser.java +0 -0
  153. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypher/Cypher.g4 +0 -0
  154. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypher/Cypher.interp +0 -0
  155. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypher/Cypher.tokens +0 -0
  156. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypher/CypherLexer.interp +0 -0
  157. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypher/CypherLexer.py +0 -0
  158. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypher/CypherLexer.tokens +0 -0
  159. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypher/CypherListener.py +0 -0
  160. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypher/CypherParser.py +0 -0
  161. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypher/__init__.py +0 -0
  162. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypherbuilder.py +0 -0
  163. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cyphergraphdb/__init__.py +0 -0
  164. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cyphergraphdb/batch.py +0 -0
  165. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cyphergraphdb/bulk_normalize.py +0 -0
  166. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cyphergraphdb/connection.py +0 -0
  167. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cyphergraphdb/criteria.py +0 -0
  168. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cyphergraphdb/cyphergraphdb.py +0 -0
  169. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cyphergraphdb/indexing.py +0 -0
  170. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cyphergraphdb/result.py +0 -0
  171. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cyphergraphdb/schema.py +0 -0
  172. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cyphergraphdb/search.py +0 -0
  173. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cyphergraphdb/sql.py +0 -0
  174. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cyphergraphdb/stream_mixin.py +0 -0
  175. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypherjson.py +0 -0
  176. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/cypherparser.py +0 -0
  177. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/dbpool.py +0 -0
  178. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/decorators.py +0 -0
  179. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/display.py +0 -0
  180. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/exceptions.py +0 -0
  181. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/graphops.py +0 -0
  182. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/main.py +0 -0
  183. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/modelinfo.py +0 -0
  184. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/modelprovider.py +0 -0
  185. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/models.py +0 -0
  186. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/options.py +0 -0
  187. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/schema/__init__.py +0 -0
  188. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/schema/converter.py +0 -0
  189. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/schema/core.py +0 -0
  190. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/schema/generator.py +0 -0
  191. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/statistics.py +0 -0
  192. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/__init__.py +0 -0
  193. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/base_exporter.py +0 -0
  194. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/base_importer.py +0 -0
  195. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/csv_exporter.py +0 -0
  196. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/csv_importer.py +0 -0
  197. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/csv_source.py +0 -0
  198. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/data_flattener.py +0 -0
  199. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/excel_exporter.py +0 -0
  200. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/excel_importer.py +0 -0
  201. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/excel_row_source.py +0 -0
  202. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/file_exporter.py +0 -0
  203. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/file_importer.py +0 -0
  204. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/hierarchical_exporter.py +0 -0
  205. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/hierarchical_importer.py +0 -0
  206. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/hierarchical_row_source.py +0 -0
  207. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/json_importer.py +0 -0
  208. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/json_yaml_data_source.py +0 -0
  209. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/row_collector.py +0 -0
  210. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/row_set.py +0 -0
  211. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/row_source.py +0 -0
  212. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/tabular_importer.py +0 -0
  213. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/tools/yaml_importer.py +0 -0
  214. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/utils/__init__.py +0 -0
  215. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/utils/collection_utils.py +0 -0
  216. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/utils/column_utils.py +0 -0
  217. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/utils/connection_utils.py +0 -0
  218. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/utils/conversion_utils.py +0 -0
  219. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/utils/core_utils.py +0 -0
  220. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/utils/schema_merge.py +0 -0
  221. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/utils/schema_to_llm.py +0 -0
  222. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/utils/schema_utils.py +0 -0
  223. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/utils/settings_repr.py +0 -0
  224. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb/utils/string_utils.py +0 -0
  225. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb.egg-info/dependency_links.txt +0 -0
  226. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb.egg-info/entry_points.txt +0 -0
  227. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb.egg-info/requires.txt +0 -0
  228. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/src/cypher_graphdb.egg-info/top_level.txt +0 -0
  229. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/README.md +0 -0
  230. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/conftest.py +0 -0
  231. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/integration/__init__.py +0 -0
  232. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/integration/conftest.py +0 -0
  233. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/integration/test_basic_operations.py +0 -0
  234. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/integration/test_create_or_merge.py +0 -0
  235. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/integration/test_example.py +0 -0
  236. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/integration/test_indexes_and_bulk.py +0 -0
  237. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/integration/test_parameters.py +0 -0
  238. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/integration/test_read_only_mode.py +0 -0
  239. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/integration/test_streaming.py +0 -0
  240. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/test_json_schema_loading.py +0 -0
  241. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/test_json_schema_vs_decorators.py +0 -0
  242. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/README.md +0 -0
  243. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/__init__.py +0 -0
  244. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/cli/__init__.py +0 -0
  245. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/cli/test_cmd_map.py +0 -0
  246. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/cli/test_command_registry.py +0 -0
  247. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/mock_backend.py +0 -0
  248. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_age_serializer.py +0 -0
  249. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_age_sqlbuilder.py +0 -0
  250. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_agtype_parser.py +0 -0
  251. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_backend_capabilities.py +0 -0
  252. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_bulk_normalize.py +0 -0
  253. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_column_utils.py +0 -0
  254. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_command_reader.py +0 -0
  255. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_cypherbuilder.py +0 -0
  256. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_cypherparser.py +0 -0
  257. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_dbpool.py +0 -0
  258. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_dict_access_mixin.py +0 -0
  259. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_extend_relation_decorator.py +0 -0
  260. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_extend_relations.py +0 -0
  261. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_graph_id_zero.py +0 -0
  262. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_graphops.py +0 -0
  263. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_indexing.py +0 -0
  264. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_model_inheritance.py +0 -0
  265. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_modelinfo.py +0 -0
  266. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_modelprovider_loading.py +0 -0
  267. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_modelprovider_schemas.py +0 -0
  268. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_models.py +0 -0
  269. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_prepared_statement_recovery.py +0 -0
  270. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_query_timeout.py +0 -0
  271. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/test_schema_converter.py +0 -0
  272. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/tools/__init__.py +0 -0
  273. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/tools/test_data_flattener.py +0 -0
  274. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/tools/test_exporters.py +0 -0
  275. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/tools/test_hierarchical_importer.py +0 -0
  276. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/tools/test_json_yaml_data_source.py +0 -0
  277. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/tools/test_resource_management.py +0 -0
  278. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/tools/test_tabular_import.py +0 -0
  279. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/utils/test_collection_utils.py +0 -0
  280. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/utils/test_connection_utils.py +0 -0
  281. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/utils/test_conversion_utils.py +0 -0
  282. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/utils/test_core_utils.py +0 -0
  283. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/utils/test_schema_merge.py +0 -0
  284. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/utils/test_schema_utils.py +0 -0
  285. {cypher_graphdb-0.2.7 → cypher_graphdb-0.2.8}/tests/unit/utils/test_settings_repr.py +0 -0
  286. {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.7
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 instantiate the backend for the given name.
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
- An instantiated CypherBackend, or None if resolution fails.
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
- # Instantiate only if result is a backend class (not an instance already)
104
- if result and isinstance(result, type) and issubclass(result, CypherBackend):
105
- result = result()
106
- # replace class with singleton instance
107
- self._backends[normalized_name] = result
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 result
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.7
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