graphforge 0.3.9__tar.gz → 0.4.0__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.
- {graphforge-0.3.9 → graphforge-0.4.0}/.github/SECURITY.md +10 -32
- {graphforge-0.3.9 → graphforge-0.4.0}/.github/workflows/docs.yml +12 -10
- {graphforge-0.3.9 → graphforge-0.4.0}/.github/workflows/test.yml +1 -1
- {graphforge-0.3.9 → graphforge-0.4.0}/.gitignore +4 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/CHANGELOG.md +28 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/CLAUDE.md +110 -1
- {graphforge-0.3.9 → graphforge-0.4.0}/Makefile +13 -1
- {graphforge-0.3.9 → graphforge-0.4.0}/PKG-INFO +60 -14
- {graphforge-0.3.9 → graphforge-0.4.0}/README.md +49 -8
- graphforge-0.4.0/benchmarks/algorithms/bench_gds.py +91 -0
- graphforge-0.4.0/benchmarks/baseline.md +34 -0
- graphforge-0.4.0/docs/architecture/overview.md +517 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/architecture/storage.md +1 -1
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/development/contributing.md +2 -2
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/development/perf-baseline-findings-v0.3.9.md +1 -1
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/development/requirements.md +45 -25
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/development/v0.4-revised-plan.md +3 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/getting-started/installation.md +23 -2
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/getting-started/tutorial.md +1 -1
- graphforge-0.4.0/docs/guide/analytics-integration.md +234 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/reference/INCOMPLETE_FEATURES_ISSUES.md +1 -1
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/reference/api.md +21 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/reference/column-naming-behavior.md +1 -1
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/reference/opencypher-compatibility.md +13 -64
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/reference/scale-limits.md +1 -4
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/releases/phase-1-complete.md +1 -2
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/releases/phase-2-complete.md +1 -1
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/releases/roadmap.md +22 -33
- graphforge-0.4.0/docs/research/agent-grounding-v040.md +224 -0
- graphforge-0.4.0/docs/research/agent-grounding.md +719 -0
- graphforge-0.4.0/docs/research/gds-network-analysis.md +189 -0
- graphforge-0.4.0/docs/research/genealogy.md +227 -0
- graphforge-0.4.0/docs/research/kg-construction.md +731 -0
- graphforge-0.4.0/docs/research/llm-context-building.md +179 -0
- graphforge-0.4.0/docs/research/llm-workflows.md +794 -0
- graphforge-0.4.0/docs/research/network-analysis.md +796 -0
- graphforge-0.4.0/docs/research/search-entity-resolution.md +186 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/use-cases/agent-grounding.md +141 -48
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/use-cases/agent-tool-recall.md +112 -64
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/use-cases/knowledge-graph-construction.md +120 -7
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/use-cases/llm-workflows.md +179 -61
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/use-cases/network-analysis.md +144 -62
- {graphforge-0.3.9 → graphforge-0.4.0}/examples/05_migration_from_networkx.py +40 -24
- {graphforge-0.3.9 → graphforge-0.4.0}/mkdocs.yml +32 -5
- {graphforge-0.3.9 → graphforge-0.4.0}/pyproject.toml +27 -10
- graphforge-0.4.0/scripts/benchmark_neighbourhood.py +421 -0
- graphforge-0.4.0/scripts/benchmark_tool_registry.py +329 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/scripts/tck_perf_report.py +2 -2
- graphforge-0.4.0/scripts/validate_agent_snippets.py +1188 -0
- graphforge-0.4.0/scripts/validate_llm_snippets.py +916 -0
- graphforge-0.4.0/src/graphforge/__init__.py +12 -0
- graphforge-0.4.0/src/graphforge/_compat.py +14 -0
- graphforge-0.4.0/src/graphforge/algorithms/__init__.py +5 -0
- graphforge-0.4.0/src/graphforge/algorithms/_dispatch.py +74 -0
- graphforge-0.4.0/src/graphforge/algorithms/centrality.py +128 -0
- graphforge-0.4.0/src/graphforge/algorithms/community.py +73 -0
- graphforge-0.4.0/src/graphforge/algorithms/gds.py +287 -0
- graphforge-0.4.0/src/graphforge/algorithms/structural.py +56 -0
- graphforge-0.4.0/src/graphforge/api.py +1935 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/ast/expression.py +17 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/datasets/exporters/json_graph.py +7 -2
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/executor/executor.py +76 -1
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/optimizer/optimizer.py +13 -2
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/parser/cypher.lark +10 -1
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/parser/parser.py +27 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/planner/planner.py +27 -3
- graphforge-0.4.0/src/graphforge/recipes/__init__.py +49 -0
- graphforge-0.4.0/src/graphforge/search/__init__.py +6 -0
- graphforge-0.4.0/src/graphforge/search/search.py +647 -0
- graphforge-0.4.0/src/graphforge/search/types.py +31 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/types/values.py +89 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/conftest.py +19 -15
- graphforge-0.4.0/tests/integration/conftest.py +34 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_distinct_clause.py +45 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_exists_is_empty.py +76 -0
- graphforge-0.4.0/tests/integration/test_shortest_path.py +45 -0
- graphforge-0.4.0/tests/integration/test_three_surfaces.py +135 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_with_clause.py +69 -0
- graphforge-0.4.0/tests/unit/algorithms/__init__.py +0 -0
- graphforge-0.4.0/tests/unit/algorithms/test_gds.py +315 -0
- graphforge-0.4.0/tests/unit/api/test_add_graph_documents.py +261 -0
- graphforge-0.4.0/tests/unit/api/test_analytics.py +489 -0
- graphforge-0.4.0/tests/unit/api/test_cache.py +220 -0
- graphforge-0.4.0/tests/unit/api/test_json_io.py +261 -0
- graphforge-0.4.0/tests/unit/api/test_merge_node.py +156 -0
- graphforge-0.4.0/tests/unit/api/test_schema_introspection.py +163 -0
- graphforge-0.4.0/tests/unit/api/test_set_node_properties.py +166 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/datasets/test_registry.py +21 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_unwind_limit_short_circuit.py +35 -1
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/optimizer/test_redundant_elimination.py +53 -1
- graphforge-0.4.0/tests/unit/parser/test_shortest_path_parser.py +63 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/planner/test_syntax_error_validation.py +10 -0
- graphforge-0.4.0/tests/unit/procedures/__init__.py +0 -0
- graphforge-0.4.0/tests/unit/recipes/__init__.py +0 -0
- graphforge-0.4.0/tests/unit/recipes/test_neighbourhood.py +113 -0
- graphforge-0.4.0/tests/unit/search/__init__.py +0 -0
- graphforge-0.4.0/tests/unit/search/test_search.py +610 -0
- graphforge-0.4.0/tests/unit/types/test_unwrap.py +179 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/uv.lock +439 -16
- graphforge-0.3.9/coverage.json +0 -1
- graphforge-0.3.9/docs/architecture/overview.md +0 -797
- graphforge-0.3.9/src/graphforge/__init__.py +0 -9
- graphforge-0.3.9/src/graphforge/api.py +0 -995
- graphforge-0.3.9/tests/integration/conftest.py +0 -13
- {graphforge-0.3.9 → graphforge-0.4.0}/.codecov.yml +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/.coderabbit.yaml +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/.editorconfig +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/.github/CODEOWNERS +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/.github/ISSUE_TEMPLATE/question.yml +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/.github/ISSUE_WORKFLOW.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/.github/dependabot.yml +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/.github/pull_request_template.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/.github/workflows/README.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/.github/workflows/changelog-check.yml +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/.github/workflows/pr-labeler.yml +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/.github/workflows/publish.yaml +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/.github/workflows/release-tracking.yml +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/.pre-commit-config.yaml +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/CHANGELOG_v0.3.0.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/CODE_OF_CONDUCT.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/CONTRIBUTING.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/IMPLEMENTATION_PLAN.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/LICENSE +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/RELEASING.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/benchmarks/.gitkeep +0 -0
- {graphforge-0.3.9/tests/perf → graphforge-0.4.0/benchmarks/algorithms}/__init__.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/architecture/ast-and-planning.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/architecture/execution-model.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/architecture/storage-analysis.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/community/code-of-conduct.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/community/security.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/cypher-guide.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/datasets/cypher-script-loading.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/datasets/ldbc.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/datasets/neo4j-examples.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/datasets/networkrepository.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/datasets/overview.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/datasets/snap.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/development/QUICKSTART_V0.2.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/development/codecov-integration.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/development/documentation-update-summary.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/development/parser-performance-analysis.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/development/perf-v038-to-v039-delta.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/development/phase-1a-completion-report.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/development/release-process.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/development/release-strategy.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/development/sessions/session-2026-01-31-cicd-infrastructure.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/development/sessions/session-2026-01-31-documentation.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/development/sessions/session-2026-01-31-regression-fix.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/development/sessions/session-2026-01-31-with-clause.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/development/sessions/session-2026-02-01-codecov-setup.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/development/sessions/session-2026-02-01-column-naming-investigation.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/development/sessions/session-summary.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/development/sessions/tck-session-2026-01-31-final.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/development/sessions/tck-session-2026-01-31.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/development/tck_baseline_analysis_v0.3.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/development/testing-setup-complete.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/development/testing.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/development/v0.2-plan-summary.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/development/workflow.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/getting-started/quickstart.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/guide/cypher-guide.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/guide/graph-construction.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/guide/overview.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/index.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/reference/README.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/reference/RELEASE_TRACKING.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/reference/VALIDATION_REPORT.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/reference/changelog.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/reference/feature-aggregation-functions.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/reference/feature-graph-queries.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/reference/feature-graph-schema.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/reference/feature-mapping/clause-to-tck.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/reference/feature-mapping/function-to-tck.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/reference/feature-order-by.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/reference/feature-return-aliasing.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/reference/implementation-status/clauses.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/reference/implementation-status/functions.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/reference/implementation-status/operators.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/reference/implementation-status/patterns.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/reference/opencypher-compatibility-matrix.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/reference/opencypher-features/01-clauses.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/reference/opencypher-features/02-functions.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/reference/opencypher-features/03-operators.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/reference/opencypher-features/04-patterns.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/reference/opencypher-features/05-data-types.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/reference/tck-compliance.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/reference/tck-inventory.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/releases/implementation-summary.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/releases/next-steps.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/releases/phase-3-complete.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/docs/stylesheets/extra.css +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/examples/01_social_network.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/examples/02_knowledge_graph.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/examples/03_data_lineage.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/examples/04_citation_network.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/examples/agent_grounding/ecommerce_agent.ipynb +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/examples/basic_graph.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/examples/basic_usage.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/scripts/build_feature_graph.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/scripts/bump_version.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/scripts/check_release_needed.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/scripts/inventory_tck.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/scripts/perf_report.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/scripts/pre-push-check.sh +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/scripts/tck_metrics.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/scripts/validate_datasets.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/ast/__init__.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/ast/clause.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/ast/pattern.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/ast/query.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/datasets/__init__.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/datasets/base.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/datasets/data/__init__.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/datasets/data/networkrepository.json +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/datasets/data/snap.json +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/datasets/exporters/__init__.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/datasets/formats/__init__.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/datasets/formats/json_graph.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/datasets/loaders/__init__.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/datasets/loaders/compression.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/datasets/loaders/csv.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/datasets/loaders/cypher.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/datasets/loaders/graphml.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/datasets/loaders/json_graph.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/datasets/loaders/ldbc.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/datasets/loaders/ldbc_schema.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/datasets/registry.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/datasets/sources/__init__.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/datasets/sources/graphml.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/datasets/sources/json_graph.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/datasets/sources/ldbc.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/datasets/sources/networkrepository.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/datasets/sources/snap.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/executor/__init__.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/executor/evaluator.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/optimizer/__init__.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/optimizer/cost_model.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/optimizer/join_reorder.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/optimizer/predicate_utils.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/optimizer/statistics.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/parser/__init__.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/planner/__init__.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/planner/operators.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/planner/types.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/procedures/__init__.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/procedures/registry.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/storage/__init__.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/storage/memory.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/storage/pydantic_serialization.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/storage/serialization.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/storage/sqlite_backend.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/types/__init__.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/src/graphforge/types/graph.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/README.md +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/__init__.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/__init__.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/datasets/test_compression.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/datasets/test_cypher_loader_docs.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/datasets/test_end_to_end_workflows.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/datasets/test_graphml_loader.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/datasets/test_json_graph_exporter.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/datasets/test_json_graph_loader.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/datasets/test_json_graph_roundtrip.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/datasets/test_ldbc_loader.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/datasets/test_networkrepository_loader.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/executor/test_graph_functions.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_aggregation_edge_cases.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_aggregation_functions_advanced.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_anonymous_relationships.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_arithmetic.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_builder_api.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_call_procedures.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_call_subqueries.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_case_expressions.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_collect.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_column_naming.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_compact_iso8601.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_complex_merge_patterns.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_complex_where_predicates.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_create_clause.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_create_edge_cases.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_delete_null.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_detach_delete.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_e2e_queries.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_executor_edge_cases.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_graph_element_comparison.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_hex_octal_literals.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_iana_timezones.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_id_function.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_issues_271_274.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_label_disjunction.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_label_predicate.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_list_comprehension.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_list_concatenation.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_list_functions.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_list_operations.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_list_path_overloading.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_list_subscript.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_logical_operators.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_map_subscript.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_match_create.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_math_functions.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_math_functions_extended.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_math_functions_new.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_merge_edge_cases.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_merge_on_create_real.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_merge_on_match_real.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_mixed_type_sort.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_nan_handling.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_null_handling.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_operator_precedence.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_optimizer_aggregate_pushdown.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_optimizer_integration.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_optimizer_redundant_elimination.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_optional_match.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_optional_match_delete.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_path_binding.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_path_binding_variable_length.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_path_functions.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_pattern_comprehension.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_pattern_predicates.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_persistence.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_power_operator.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_predicate_functions.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_properties_keys_functions.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_relationship_directions.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_relationship_uniqueness.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_remove_clause.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_set_delete_merge.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_size_function.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_skip_limit_expressions.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_snap_dataset_loading.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_sort_after_aggregation.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_spatial_api.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_sqlite_persistence.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_startnode_endnode_functions.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_string_functions.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_string_functions_new.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_string_matching.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_subquery_expressions.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_temporal_map_constructors.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_temporal_queries.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_temporal_select_into.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_transactions.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_type_conversion_fixes.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_type_functions.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_union.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_unwind.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_variable_length_paths.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_varlen_predicate_and_uniqueness.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_wildcard_execution.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_with_aggregation_real.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_with_clause_modifiers.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_with_clause_positions.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_with_distinct_skip_limit.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/integration/test_xor_operator.py +0 -0
- {graphforge-0.3.9/tests/unit/procedures → graphforge-0.4.0/tests/perf}/__init__.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/perf/conftest.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/perf/test_real_datasets.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/property/__init__.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/property/strategies.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/__init__.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/conftest.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/coverage_matrix.json +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/download_tck.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/Aggregation1_BasicAggregation.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/Match1_SimpleMatches.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/call/Call1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/call/Call2.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/call/Call3.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/call/Call4.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/call/Call5.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/call/Call6.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/create/Create1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/create/Create2.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/create/Create3.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/create/Create4.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/create/Create5.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/create/Create6.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/delete/Delete1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/delete/Delete2.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/delete/Delete3.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/delete/Delete4.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/delete/Delete5.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/delete/Delete6.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/match/Match1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/match/Match2.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/match/Match3.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/match/Match4.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/match/Match5.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/match/Match6.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/match/Match7.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/match/Match8.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/match/Match9.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/match-where/MatchWhere1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/match-where/MatchWhere2.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/match-where/MatchWhere3.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/match-where/MatchWhere4.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/match-where/MatchWhere5.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/match-where/MatchWhere6.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/merge/Merge1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/merge/Merge2.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/merge/Merge3.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/merge/Merge4.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/merge/Merge5.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/merge/Merge6.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/merge/Merge7.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/merge/Merge8.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/merge/Merge9.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/remove/Remove1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/remove/Remove2.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/remove/Remove3.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/return/Return1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/return/Return2.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/return/Return3.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/return/Return4.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/return/Return5.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/return/Return6.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/return/Return7.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/return/Return8.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/return-orderby/ReturnOrderBy1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/return-orderby/ReturnOrderBy2.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/return-orderby/ReturnOrderBy3.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/return-orderby/ReturnOrderBy4.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/return-orderby/ReturnOrderBy5.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/return-orderby/ReturnOrderBy6.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/return-skip-limit/ReturnSkipLimit1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/return-skip-limit/ReturnSkipLimit2.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/return-skip-limit/ReturnSkipLimit3.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/set/Set1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/set/Set2.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/set/Set3.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/set/Set4.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/set/Set5.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/set/Set6.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/union/Union1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/union/Union2.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/union/Union3.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/unwind/Unwind1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/with/With1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/with/With2.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/with/With3.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/with/With4.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/with/With5.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/with/With6.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/with/With7.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/with-orderBy/WithOrderBy1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/with-orderBy/WithOrderBy2.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/with-orderBy/WithOrderBy3.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/with-orderBy/WithOrderBy4.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/with-skip-limit/WithSkipLimit1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/with-skip-limit/WithSkipLimit2.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/with-skip-limit/WithSkipLimit3.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/with-where/WithWhere1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/with-where/WithWhere2.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/with-where/WithWhere3.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/with-where/WithWhere4.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/with-where/WithWhere5.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/with-where/WithWhere6.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/clauses/with-where/WithWhere7.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/aggregation/Aggregation1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/aggregation/Aggregation2.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/aggregation/Aggregation3.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/aggregation/Aggregation4.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/aggregation/Aggregation5.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/aggregation/Aggregation6.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/aggregation/Aggregation7.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/aggregation/Aggregation8.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/boolean/Boolean1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/boolean/Boolean2.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/boolean/Boolean3.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/boolean/Boolean4.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/boolean/Boolean5.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/comparison/Comparison1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/comparison/Comparison2.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/comparison/Comparison3.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/comparison/Comparison4.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/conditional/Conditional1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/conditional/Conditional2.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/existentialSubqueries/ExistentialSubquery1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/existentialSubqueries/ExistentialSubquery2.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/existentialSubqueries/ExistentialSubquery3.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/graph/Graph1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/graph/Graph2.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/graph/Graph3.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/graph/Graph4.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/graph/Graph5.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/graph/Graph6.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/graph/Graph7.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/graph/Graph8.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/graph/Graph9.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/list/List1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/list/List10.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/list/List11.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/list/List12.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/list/List2.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/list/List3.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/list/List4.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/list/List5.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/list/List6.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/list/List7.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/list/List8.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/list/List9.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/literals/Literals1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/literals/Literals2.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/literals/Literals3.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/literals/Literals4.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/literals/Literals5.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/literals/Literals6.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/literals/Literals7.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/literals/Literals8.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/map/Map1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/map/Map2.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/map/Map3.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/mathematical/Mathematical1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/mathematical/Mathematical10.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/mathematical/Mathematical11.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/mathematical/Mathematical12.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/mathematical/Mathematical13.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/mathematical/Mathematical14.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/mathematical/Mathematical15.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/mathematical/Mathematical16.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/mathematical/Mathematical17.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/mathematical/Mathematical2.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/mathematical/Mathematical3.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/mathematical/Mathematical4.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/mathematical/Mathematical5.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/mathematical/Mathematical6.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/mathematical/Mathematical7.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/mathematical/Mathematical8.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/mathematical/Mathematical9.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/null/Null1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/null/Null2.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/null/Null3.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/path/Path1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/path/Path2.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/path/Path3.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/pattern/Pattern1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/pattern/Pattern2.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/precedence/Precedence1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/precedence/Precedence2.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/precedence/Precedence3.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/precedence/Precedence4.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/quantifier/Quantifier1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/quantifier/Quantifier10.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/quantifier/Quantifier11.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/quantifier/Quantifier12.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/quantifier/Quantifier2.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/quantifier/Quantifier3.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/quantifier/Quantifier4.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/quantifier/Quantifier5.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/quantifier/Quantifier6.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/quantifier/Quantifier7.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/quantifier/Quantifier8.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/quantifier/Quantifier9.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/string/String1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/string/String10.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/string/String11.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/string/String12.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/string/String13.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/string/String14.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/string/String2.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/string/String3.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/string/String4.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/string/String5.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/string/String6.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/string/String7.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/string/String8.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/string/String9.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/temporal/Temporal1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/temporal/Temporal10.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/temporal/Temporal2.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/temporal/Temporal3.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/temporal/Temporal4.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/temporal/Temporal5.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/temporal/Temporal6.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/temporal/Temporal7.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/temporal/Temporal8.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/temporal/Temporal9.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/typeConversion/TypeConversion1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/typeConversion/TypeConversion2.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/typeConversion/TypeConversion3.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/typeConversion/TypeConversion4.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/typeConversion/TypeConversion5.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/expressions/typeConversion/TypeConversion6.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/useCases/countingSubgraphMatches/CountingSubgraphMatches1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/features/official/useCases/triadicSelection/TriadicSelection1.feature +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/graphs/binary-tree-1/binary-tree-1.cypher +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/graphs/binary-tree-1/binary-tree-1.json +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/graphs/binary-tree-2/binary-tree-2.cypher +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/graphs/binary-tree-2/binary-tree-2.json +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/graphs/named-graphs.adoc +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/tck_config.yaml +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/tck_markers.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/test_features.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/tck/test_tck_compliance.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/__init__.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/api/__init__.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/api/test_api_coverage.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/api/test_bulk_ingest.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/api/test_clear.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/api/test_clone.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/api/test_cypher_value_conversion.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/ast/__init__.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/ast/test_ast_nodes.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/ast/test_expression_coverage.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/datasets/__init__.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/datasets/test_compression_coverage.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/datasets/test_csv_loader.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/datasets/test_cypher_loader.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/datasets/test_graphml_loader.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/datasets/test_json_graph_exporter.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/datasets/test_json_graph_format.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/datasets/test_json_graph_loader.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/datasets/test_ldbc_schema.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/datasets/test_networkrepository.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/datasets/test_snap_datasets.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/datasets/test_sources_registration.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/__init__.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_aggregation_errors.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_aggregation_functions_advanced.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_arithmetic_evaluator.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_element_id.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_evaluator.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_evaluator_additional_coverage.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_evaluator_coverage_boost.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_evaluator_error_paths.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_executor_coverage_boost.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_executor_error_paths.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_expression_matching.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_expressions_match.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_graph_functions.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_id_function.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_in_operator.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_infer_rel_var.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_limit_short_circuit.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_list_functions.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_list_functions_errors.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_map_property_access.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_merge_on_create.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_merge_on_match.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_multihop_create.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_optional_expand_bound_dst.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_optional_scan_coverage.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_parenthesized_expr_coverage.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_path_functions.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_procedure_call_executor.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_properties_keys_errors.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_property_index_executor.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_set_extensions.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_sort_edge_cases.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_spatial_functions.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_startnode_endnode_errors.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_string_functions_new.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_string_matching_evaluator.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_subquery_planner_check.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_temporal_functions.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_temporal_truncate_arithmetic.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_three_valued_logic.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_type_conversion_complex.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_undirected_relationship_bugs.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/executor/test_with_aggregation.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/optimizer/__init__.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/optimizer/test_aggregate_pushdown.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/optimizer/test_cost_model.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/optimizer/test_filter_pushdown.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/optimizer/test_join_reorder.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/optimizer/test_join_reorder_coverage.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/optimizer/test_optimizer_coverage.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/optimizer/test_optimizer_reuse.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/optimizer/test_predicate_reorder.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/optimizer/test_predicate_utils.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/optimizer/test_predicate_utils_coverage.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/optimizer/test_statistics.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/parser/__init__.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/parser/test_arithmetic_parser.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/parser/test_call_procedure_parser.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/parser/test_case_parser.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/parser/test_collect_parser.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/parser/test_delete_parser.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/parser/test_float_literals.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/parser/test_grammar.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/parser/test_hex_octal_literals.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/parser/test_label_predicate_parser.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/parser/test_merge_on_create.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/parser/test_merge_on_match.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/parser/test_optional_match_delete.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/parser/test_order_by_direction.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/parser/test_parser.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/parser/test_parser_caching.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/parser/test_parser_coverage_boost.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/parser/test_path_binding.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/parser/test_pattern_comprehension_binding.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/parser/test_pattern_predicates.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/parser/test_remove_parser.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/parser/test_string_matching_parser.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/parser/test_wildcard_parsing.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/parser/test_with_at_query_start.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/parser/test_with_clause_positions.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/planner/__init__.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/planner/test_call_procedure_planner.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/planner/test_expand_multi_hop_operator.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/planner/test_operator_validation.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/planner/test_operators.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/planner/test_planner_branch_coverage.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/planner/test_planner_comprehensive.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/planner/test_planner_edge_cases.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/planner/test_remove_planner.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/planner/test_type_tracking.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/planner/test_with_validation.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/procedures/test_registry.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/storage/__init__.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/storage/test_graph_edge_cases.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/storage/test_memory_store.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/storage/test_property_index.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/storage/test_pydantic_serialization.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/storage/test_serialization_edge_cases.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/storage/test_spatial_serialization.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/storage/test_sqlite_backend_adjacency.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/storage/test_sqlite_backend_delete_bulk.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/storage/test_storage_coverage.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/storage/test_temporal_serialization.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/test_graph_elements.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/test_iana_timezone_construction.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/test_procedure_registry_coverage.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/test_values.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/types/test_cypher_values_deep_equality.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/types/test_cypher_values_edge_cases.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/types/test_extreme_temporal_values.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/types/test_graph_element_edge_cases.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/types/test_path_values.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/types/test_spatial_values.py +0 -0
- {graphforge-0.3.9 → graphforge-0.4.0}/tests/unit/types/test_temporal_values.py +0 -0
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
## Supported Versions
|
|
4
4
|
|
|
5
|
-
GraphForge is
|
|
5
|
+
GraphForge is pre-v1.0. The API is still maturing, and only the **latest release** receives security updates. If you discover a vulnerability, please update to the latest version first.
|
|
6
6
|
|
|
7
|
-
| Version | Supported
|
|
8
|
-
| ------- |
|
|
9
|
-
| 0.
|
|
10
|
-
|
|
|
7
|
+
| Version | Supported |
|
|
8
|
+
| ------- | --------- |
|
|
9
|
+
| Latest (0.3.x) | :white_check_mark: |
|
|
10
|
+
| Older releases | :x: |
|
|
11
|
+
|
|
12
|
+
We will begin supporting multiple versions once a stable v1.0 API is reached.
|
|
11
13
|
|
|
12
14
|
## Reporting a Vulnerability
|
|
13
15
|
|
|
@@ -19,11 +21,7 @@ Please do not report security vulnerabilities through public GitHub issues.
|
|
|
19
21
|
|
|
20
22
|
### 2. Report Privately
|
|
21
23
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
**Email:** [Add your security contact email]
|
|
25
|
-
|
|
26
|
-
Or use GitHub's private vulnerability reporting:
|
|
24
|
+
Use GitHub's private vulnerability reporting:
|
|
27
25
|
|
|
28
26
|
1. Go to the [Security tab](https://github.com/DecisionNerd/graphforge/security)
|
|
29
27
|
2. Click "Report a vulnerability"
|
|
@@ -126,7 +124,7 @@ GraphForge uses SQLite for persistence:
|
|
|
126
124
|
|
|
127
125
|
### 2. Query Execution
|
|
128
126
|
|
|
129
|
-
- **No query timeout:** Long-running queries can cause DoS
|
|
127
|
+
- **No query timeout:** Long-running queries can cause DoS
|
|
130
128
|
- **No resource limits:** No built-in limits on memory/CPU usage
|
|
131
129
|
- **No access control:** No user authentication/authorization system
|
|
132
130
|
|
|
@@ -134,18 +132,6 @@ GraphForge uses SQLite for persistence:
|
|
|
134
132
|
|
|
135
133
|
- **MessagePack:** Uses msgpack for serialization (ensure trusted data only)
|
|
136
134
|
|
|
137
|
-
## Security Roadmap
|
|
138
|
-
|
|
139
|
-
Future security enhancements planned:
|
|
140
|
-
|
|
141
|
-
- [ ] Query timeout mechanisms
|
|
142
|
-
- [ ] Resource usage limits (memory, CPU)
|
|
143
|
-
- [ ] Query complexity analysis
|
|
144
|
-
- [ ] Access control system
|
|
145
|
-
- [ ] Audit logging
|
|
146
|
-
- [ ] Encrypted database files
|
|
147
|
-
- [ ] Security scanning in CI/CD (Dependabot, CodeQL)
|
|
148
|
-
|
|
149
135
|
## Security-Related Configuration
|
|
150
136
|
|
|
151
137
|
### Bandit (Security Linting)
|
|
@@ -174,19 +160,11 @@ safety check
|
|
|
174
160
|
- **CVE assignment:** We'll request CVEs for significant vulnerabilities
|
|
175
161
|
- **Security advisories:** Published on GitHub Security Advisories
|
|
176
162
|
|
|
177
|
-
## Contact
|
|
178
|
-
|
|
179
|
-
For security-related questions (non-vulnerability):
|
|
180
|
-
|
|
181
|
-
- **Email:** [Add your contact email]
|
|
182
|
-
- **Discussions:** [GitHub Discussions](https://github.com/DecisionNerd/graphforge/discussions)
|
|
183
|
-
|
|
184
163
|
## Attribution
|
|
185
164
|
|
|
186
165
|
We believe in recognizing security researchers who help improve GraphForge. With your permission, we'll:
|
|
187
166
|
|
|
188
167
|
- Credit you in security advisories
|
|
189
|
-
- List you in our security hall of fame (coming soon)
|
|
190
168
|
- Mention you in release notes
|
|
191
169
|
|
|
192
170
|
## Additional Resources
|
|
@@ -197,6 +175,6 @@ We believe in recognizing security researchers who help improve GraphForge. With
|
|
|
197
175
|
|
|
198
176
|
---
|
|
199
177
|
|
|
200
|
-
**Last Updated:**
|
|
178
|
+
**Last Updated:** 2026-05-06
|
|
201
179
|
|
|
202
180
|
Thank you for helping keep GraphForge secure!
|
|
@@ -6,12 +6,15 @@ on:
|
|
|
6
6
|
paths:
|
|
7
7
|
- 'docs/**'
|
|
8
8
|
- 'mkdocs.yml'
|
|
9
|
+
- 'src/graphforge/**'
|
|
10
|
+
- 'pyproject.toml'
|
|
9
11
|
- '.github/workflows/docs.yml'
|
|
10
12
|
pull_request:
|
|
11
13
|
branches: [main]
|
|
12
14
|
paths:
|
|
13
15
|
- 'docs/**'
|
|
14
16
|
- 'mkdocs.yml'
|
|
17
|
+
- 'src/graphforge/**'
|
|
15
18
|
workflow_dispatch:
|
|
16
19
|
|
|
17
20
|
permissions:
|
|
@@ -19,7 +22,6 @@ permissions:
|
|
|
19
22
|
pages: write
|
|
20
23
|
id-token: write
|
|
21
24
|
|
|
22
|
-
# Allow only one concurrent deployment
|
|
23
25
|
concurrency:
|
|
24
26
|
group: pages
|
|
25
27
|
cancel-in-progress: false
|
|
@@ -28,30 +30,30 @@ jobs:
|
|
|
28
30
|
build:
|
|
29
31
|
name: Build Documentation
|
|
30
32
|
runs-on: ubuntu-latest
|
|
31
|
-
|
|
32
33
|
steps:
|
|
33
|
-
- name: Checkout
|
|
34
|
+
- name: Checkout
|
|
34
35
|
uses: actions/checkout@v6
|
|
35
36
|
with:
|
|
36
|
-
fetch-depth: 0
|
|
37
|
+
fetch-depth: 0
|
|
37
38
|
|
|
38
39
|
- name: Install uv
|
|
39
40
|
uses: astral-sh/setup-uv@v8.1.0
|
|
41
|
+
with:
|
|
42
|
+
enable-cache: true
|
|
40
43
|
|
|
41
44
|
- name: Set up Python
|
|
42
45
|
uses: actions/setup-python@v6
|
|
43
46
|
with:
|
|
44
47
|
python-version: '3.12'
|
|
45
48
|
|
|
46
|
-
- name: Install
|
|
47
|
-
run:
|
|
48
|
-
uv pip install --system -e ".[docs]"
|
|
49
|
+
- name: Install docs dependencies
|
|
50
|
+
run: uv sync --group docs
|
|
49
51
|
|
|
50
52
|
- name: Build documentation
|
|
51
|
-
run: mkdocs build --strict
|
|
53
|
+
run: uv run mkdocs build --strict
|
|
52
54
|
|
|
53
55
|
- name: Upload Pages artifact
|
|
54
|
-
if:
|
|
56
|
+
if: github.event_name != 'pull_request'
|
|
55
57
|
uses: actions/upload-pages-artifact@v5
|
|
56
58
|
with:
|
|
57
59
|
path: site/
|
|
@@ -59,7 +61,7 @@ jobs:
|
|
|
59
61
|
deploy:
|
|
60
62
|
name: Deploy to GitHub Pages
|
|
61
63
|
needs: build
|
|
62
|
-
if:
|
|
64
|
+
if: github.event_name != 'pull_request'
|
|
63
65
|
runs-on: ubuntu-latest
|
|
64
66
|
|
|
65
67
|
environment:
|
|
@@ -266,7 +266,7 @@ jobs:
|
|
|
266
266
|
|
|
267
267
|
- name: Report TCK performance metrics
|
|
268
268
|
if: always()
|
|
269
|
-
run: uv run python3 scripts/tck_perf_report.py test-results-tck.xml --threshold
|
|
269
|
+
run: uv run python3 scripts/tck_perf_report.py test-results-tck.xml --threshold 2
|
|
270
270
|
|
|
271
271
|
- name: Upload TCK results to Codecov
|
|
272
272
|
uses: codecov/codecov-action@v6
|
|
@@ -7,6 +7,34 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.4.0] - 2026-05-07
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- **`db.gds` graph algorithm surface** (#484, PRs #514–#516) — 8 compiled algorithms dispatched to igraph (preferred) or NetworkX: `pagerank`, `betweenness_centrality`, `closeness_centrality`, `degree_centrality`, `louvain`, `connected_components`, `clustering_coefficient`, `triangle_count`. Stream mode returns `dict[node_id, scalar]`; write mode persists results via `set_node_properties()`. Optional `node_label`, `rel_type`, `directed` filters.
|
|
14
|
+
- **`db.search` hybrid retrieval surface** (#476, PRs #517 #533–#539) — FTS5 text search (`db.search.text()`), vector cosine similarity (`db.search.vector()`), and RRF-fused hybrid (`db.search()` / `db.search.hybrid()`). All methods return `list[SearchHit]` with `.ref`, `.score`, `.sources`, `.text_score`, `.vector_score`. Multi-space vector storage: `set_node_vector(id, vec, space="model-name")`. Bring-your-own-vectors; `space` can represent text embeddings, geo coordinates, temporal features, or any numeric feature array.
|
|
15
|
+
- **`SearchHit` result type** — frozen dataclass with score provenance; every `.ref.id` is directly addressable in `db.execute()`.
|
|
16
|
+
- **`set_node_properties()` bulk write-back** (#480, PR #515) — batch-update node properties from a `dict[node_id, dict[prop, value]]`.
|
|
17
|
+
- **`directed` and `node_id_property` export parameters** (#478 #479, PR #514) — `to_networkx(directed=True)`, `to_igraph(node_id_property="name")`, etc.
|
|
18
|
+
- **`graphforge.recipes.neighbourhood()`** (#492, PR #518) — n-hop subgraph expansion returning `list[dict]` for LLM context building.
|
|
19
|
+
- **Benchmark suite** (#388, PR #519) — `make benchmark` runs real-dataset benchmarks through M-tier (XS/S/M/L).
|
|
20
|
+
- **Integration tests for three-surface interoperability** (PR #541) — GDS write-back readable via Cypher, search results addressable via `id()`, cross-surface PageRank threshold queries.
|
|
21
|
+
- **Use-case documentation** (PR #542, closes #523 #524 #525 #526) — `db.gds` examples in `network-analysis.md`; `db.search` + `recipes` in `llm-workflows.md`; deduplication pattern in `knowledge-graph-construction.md`; hybrid tool selection in `agent-grounding.md`.
|
|
22
|
+
|
|
23
|
+
## [0.3.10] - 2026-05-06
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
- **Schema introspection API** (#469, #499) — `labels()`, `relationship_types()`, `node_count(label=None)`, `relationship_count(type=None)` on `GraphForge`; efficient set-union over storage backend
|
|
27
|
+
- **JSON export/import** (#470, #500) — `gf.to_json(path, metadata, indent)` serialises the full graph to a portable JSON file; `GraphForge.from_json(path)` reconstructs it; Hypothesis roundtrip property test
|
|
28
|
+
- **`merge_node()` safe upsert** (#471, #501) — `merge_node(labels, match_on, on_create, on_match)` with regex label validation, index-safe on_match updates, and create/match semantics matching MERGE clause behaviour
|
|
29
|
+
- **`add_graph_documents()` LangChain-compatible ingestion** (#472, #502) — duck-typed batch ingestion accepting any object with `.nodes`/`.relationships` attributes; idempotent edges; rel type pre-check; no `langchain-community` import required
|
|
30
|
+
- **Parse/plan LRU cache** (#464, #504) — `GraphForge(cache_size=N)` caches parsed+planned query pipelines; `clear_cache()` and `cache_info()` for introspection; thread-safe; default size 128
|
|
31
|
+
|
|
32
|
+
### Fixed
|
|
33
|
+
- **ORDER BY on aliased RETURN DISTINCT property no longer raises UndefinedVariable** (#481, #494) — planner now records `(variable, property)` paths for aliased `PropertyAccess` return items, so `RETURN DISTINCT a.year AS year ORDER BY a.year` resolves correctly
|
|
34
|
+
- **Variable reuse across WITH boundary no longer raises KeyError** (#482, #495) — optimizer's redundant-traversal-elimination pass now treats `Aggregate` as a scope boundary (same as `With`/`Union`/`Subquery`), preventing fresh post-WITH variable bindings from being silently dropped
|
|
35
|
+
- **EXISTS {} subquery crash on anonymous inner node with outer-scope property** (#474, #496) — `_plan_match` now passes `var_name` (always set, from pattern variable or generated) instead of `node_pattern.variable` (can be None) to `_properties_to_predicate`
|
|
36
|
+
- **`shortestPath()` / `allShortestPaths()` parse correctly and raise NotImplementedError** (#468, #497) — previously caused unhelpful `SyntaxError: Unexpected token`; now parsed into `ShortestPathExpression` AST nodes; planner raises `NotImplementedError` with BFS workaround: `MATCH path = (a)-[*1..N]-(b) RETURN length(path) ORDER BY length(path) LIMIT 1`
|
|
37
|
+
|
|
10
38
|
## [0.3.9] - 2026-05-04
|
|
11
39
|
|
|
12
40
|
### Added
|
|
@@ -111,7 +111,17 @@ PYTEST_WORKERS=2 make test
|
|
|
111
111
|
|
|
112
112
|
**When to use `pre-push-fast`:** iterating on non-test changes (refactors, docs, config). Always run the full `pre-push` before opening a PR.
|
|
113
113
|
|
|
114
|
-
## Architecture:
|
|
114
|
+
## Architecture: Three-Surface API
|
|
115
|
+
|
|
116
|
+
GraphForge has three independent API surfaces that share a single storage layer. **Each surface has a distinct code path. Not every feature flows through all four Cypher layers.**
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
db.execute("MATCH ...") → Cypher path (4-layer pipeline below)
|
|
120
|
+
db.gds.pagerank(...) → Algorithm path (bypasses parser/planner/executor)
|
|
121
|
+
db.search(...) → Search path (bypasses parser/planner/executor)
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Cypher Path (db.execute)
|
|
115
125
|
|
|
116
126
|
```
|
|
117
127
|
User Code (Python API / Cypher)
|
|
@@ -142,12 +152,90 @@ User Code (Python API / Cypher)
|
|
|
142
152
|
└─────────────────────────────────────────────────┘
|
|
143
153
|
```
|
|
144
154
|
|
|
155
|
+
### Algorithm Path (db.gds)
|
|
156
|
+
|
|
157
|
+
`db.gds.*` methods do **not** follow the 4-layer pattern. They live in `src/graphforge/algorithms/` and bypass the parser, planner, and executor entirely.
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
_export_for_algorithm(node_label, rel_type, directed)
|
|
161
|
+
↓
|
|
162
|
+
_resolve_backend() → native (future) → igraph → NetworkX
|
|
163
|
+
↓
|
|
164
|
+
backend.compute(G, **kwargs) → dict[node_id, scalar]
|
|
165
|
+
↓
|
|
166
|
+
set_node_properties({nid: {write_property: val} …}) ← if write_property set
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Key files:
|
|
170
|
+
- `src/graphforge/algorithms/gds.py` — `GraphDataScience` accessor class
|
|
171
|
+
- `src/graphforge/algorithms/_dispatch.py` — `_resolve_backend()` + dispatch helpers
|
|
172
|
+
- `src/graphforge/algorithms/centrality.py` — pagerank, betweenness, closeness, degree
|
|
173
|
+
- `src/graphforge/algorithms/community.py` — louvain, connected_components
|
|
174
|
+
- `src/graphforge/algorithms/structural.py` — clustering_coefficient, triangle_count
|
|
175
|
+
|
|
176
|
+
#### Adding a db.gds Algorithm
|
|
177
|
+
|
|
178
|
+
1. Implement in `algorithms/<category>.py`
|
|
179
|
+
2. Add dispatch branch in `_dispatch.py` for each supported backend
|
|
180
|
+
3. Expose method on `GraphDataScience` class in `gds.py`
|
|
181
|
+
4. Tests: unit test per backend + integration test via `db.gds.<name>()`
|
|
182
|
+
|
|
183
|
+
#### Adding a New Backend Tier
|
|
184
|
+
|
|
185
|
+
1. Add detection logic in `_resolve_backend()`
|
|
186
|
+
2. Implement algorithm dispatch in the new backend branch
|
|
187
|
+
3. Test priority fallback (native → igraph → NX)
|
|
188
|
+
4. API and existing tests do not change
|
|
189
|
+
|
|
190
|
+
### Search Path (db.search)
|
|
191
|
+
|
|
192
|
+
`db.search.*` operates on SQLite FTS5 virtual tables and BLOB vector columns — not the graph execution engine. It does not parse Cypher.
|
|
193
|
+
|
|
194
|
+
Primary entry point: `db.search(query, vector=...)` — hybrid by default.
|
|
195
|
+
Named methods: `db.search.text(query)`, `db.search.vector(vec)`, `db.search.hybrid(query, vec)`.
|
|
196
|
+
All methods return `list[SearchHit]` with `.ref`, `.score`, `.sources`, `.text_score`, `.vector_score`.
|
|
197
|
+
|
|
198
|
+
**Bring-your-own-vectors contract:** GraphForge stores and queries vectors but does not generate them.
|
|
199
|
+
The `space` parameter identifies what a vector *represents* — vectors are not limited to text embeddings.
|
|
200
|
+
Common uses: text embeddings (`"text-embedding-3-small"`, SBERT), geographic coordinates (`[lat, lon]`),
|
|
201
|
+
temporal features (`[unix_timestamp, ...]`), or any numeric feature array. For each space, cosine
|
|
202
|
+
similarity finds the closest stored vectors to a query vector. Callers are responsible for consistent
|
|
203
|
+
encoding and dimensionality between stored and query vectors. `db.search.text()` works standalone.
|
|
204
|
+
A recipe for embedding + indexing in one call is tracked in issue #540.
|
|
205
|
+
|
|
206
|
+
Key files:
|
|
207
|
+
- `src/graphforge/search/search.py` — `GraphSearch` class (text, vector, hybrid, index_node, index_all)
|
|
208
|
+
- `src/graphforge/search/types.py` — `SearchHit` frozen dataclass
|
|
209
|
+
- FTS5 virtual tables: `node_fts`, `edge_fts`
|
|
210
|
+
- Vector store: `node_vector`, `edge_vector` (BLOB columns + NumPy, composite PK `(node_id, space)`)
|
|
211
|
+
|
|
212
|
+
### Recipes Module (graphforge.recipes)
|
|
213
|
+
|
|
214
|
+
`graphforge.recipes` is a collection of standalone helper functions (not a `db.*` accessor). Each recipe composes Cypher + API calls into a reusable pattern. Import directly from `graphforge.recipes`.
|
|
215
|
+
|
|
216
|
+
Key files:
|
|
217
|
+
- `src/graphforge/recipes/__init__.py` — All recipe functions
|
|
218
|
+
|
|
219
|
+
Current recipes:
|
|
220
|
+
- `neighbourhood(db, canonical, hops, *, label, canonical_prop)` — n-hop neighbourhood expansion returning `list[dict]`
|
|
221
|
+
|
|
222
|
+
### Design Constraint: No Cypher Extensions
|
|
223
|
+
|
|
224
|
+
**Neither `db.gds` nor `db.search` modifies `cypher.lark`.** If you are adding a feature and find yourself editing the grammar, you are in the wrong surface.
|
|
225
|
+
|
|
226
|
+
| Feature type | Surface | Touches parser? |
|
|
227
|
+
|---|---|---|
|
|
228
|
+
| New Cypher clause or function | `db.execute` | Yes — all 4 layers |
|
|
229
|
+
| New graph algorithm | `db.gds` | No |
|
|
230
|
+
| New search capability | `db.search` | No |
|
|
231
|
+
|
|
145
232
|
### Key Principles
|
|
146
233
|
|
|
147
234
|
1. **Each layer is independent** - Parser knows nothing about execution
|
|
148
235
|
2. **AST is the contract** - Parser produces AST, planner consumes it
|
|
149
236
|
3. **Operators are composable** - Planner emits list, executor chains them
|
|
150
237
|
4. **Storage is pluggable** - Executor uses Graph interface
|
|
238
|
+
5. **Surfaces are independent** - `db.gds` and `db.search` bypass the Cypher pipeline
|
|
151
239
|
|
|
152
240
|
### Adding Cypher Features
|
|
153
241
|
|
|
@@ -364,6 +452,27 @@ def test_create_node():
|
|
|
364
452
|
|
|
365
453
|
## Common Development Tasks
|
|
366
454
|
|
|
455
|
+
### Adding a db.gds Algorithm
|
|
456
|
+
|
|
457
|
+
1. Implement in `src/graphforge/algorithms/<category>.py`
|
|
458
|
+
2. Add dispatch in `_dispatch.py` for each backend
|
|
459
|
+
3. Expose method on `GraphDataScience` in `gds.py`
|
|
460
|
+
4. Tests: unit per backend + integration via `db.gds.<name>()`
|
|
461
|
+
|
|
462
|
+
### Adding a db.search Feature
|
|
463
|
+
|
|
464
|
+
1. Add schema migration in search layer (FTS or vector table)
|
|
465
|
+
2. Implement in `src/graphforge/search/<feature>.py`
|
|
466
|
+
3. Expose method on `GraphSearch` accessor
|
|
467
|
+
4. Tests: unit + integration; verify `NodeRef` results are addressable in `db.execute()`
|
|
468
|
+
|
|
469
|
+
### Adding a Recipe
|
|
470
|
+
|
|
471
|
+
1. Implement in `src/graphforge/recipes/__init__.py`
|
|
472
|
+
2. Compose from `db.execute()`, `db.gds.*`, or `db.search.*` — recipes are convenience wrappers
|
|
473
|
+
3. Tests: unit test in `tests/unit/recipes/`
|
|
474
|
+
4. Recipe should return plain Python types (list, dict), not CypherValues
|
|
475
|
+
|
|
367
476
|
### Adding a New Cypher Clause
|
|
368
477
|
|
|
369
478
|
1. Grammar: Add to `cypher.lark`
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
.PHONY: help lint format type-check security test pre-push pre-push-fast clean test-tck docstring-coverage test-network test-perf test-perf-xs test-perf-slow test-perf-large coverage coverage-quick coverage-report coverage-diff coverage-strict check-coverage check-patch-coverage test-durations test-analytics
|
|
1
|
+
.PHONY: help lint format type-check security test pre-push pre-push-fast clean test-tck docstring-coverage test-network benchmark test-perf test-perf-xs test-perf-slow test-perf-large coverage coverage-quick coverage-report coverage-diff coverage-strict check-coverage check-patch-coverage test-durations test-analytics docs-serve docs-build docs-clean
|
|
2
2
|
|
|
3
3
|
help: ## Show this help message
|
|
4
4
|
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
|
|
@@ -33,6 +33,9 @@ test-integration: ## Run integration tests in parallel (excludes snap/network d
|
|
|
33
33
|
test-network: ## Run external network/download tests (snap datasets; requires internet)
|
|
34
34
|
uv run pytest tests/ -m "snap" -v
|
|
35
35
|
|
|
36
|
+
benchmark: ## Run db.gds algorithm benchmarks on snap-ego-facebook; updates benchmarks/baseline.md
|
|
37
|
+
PYTHONPATH=src uv run python benchmarks/algorithms/bench_gds.py
|
|
38
|
+
|
|
36
39
|
test-perf-xs: ## Run perf QA for XS/S datasets only (karate + ego-facebook, ~3 MB total)
|
|
37
40
|
uv run pytest tests/perf/ -m "perf and not perf_large and not perf_slow" -k "xs or s_face" -v -s
|
|
38
41
|
|
|
@@ -178,3 +181,12 @@ clean: ## Clean up cache files
|
|
|
178
181
|
find . -type f -name "*.pyc" -delete 2>/dev/null || true
|
|
179
182
|
rm -f test-results*.xml coverage.xml 2>/dev/null || true
|
|
180
183
|
rm -rf htmlcov/ 2>/dev/null || true
|
|
184
|
+
|
|
185
|
+
docs-serve: ## Serve docs locally with live reload (http://127.0.0.1:8000)
|
|
186
|
+
uv run --group docs mkdocs serve
|
|
187
|
+
|
|
188
|
+
docs-build: ## Build docs site to site/ (strict mode)
|
|
189
|
+
uv run --group docs mkdocs build --strict
|
|
190
|
+
|
|
191
|
+
docs-clean: ## Remove built docs
|
|
192
|
+
rm -rf site/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: graphforge
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Composable graph tooling for analysis, construction, and refinement
|
|
5
5
|
Project-URL: Homepage, https://github.com/DecisionNerd/graphforge
|
|
6
6
|
Project-URL: Repository, https://github.com/DecisionNerd/graphforge
|
|
@@ -29,6 +29,10 @@ Requires-Dist: msgpack>=1.0
|
|
|
29
29
|
Requires-Dist: pydantic>=2.6
|
|
30
30
|
Requires-Dist: python-dateutil>=2.8.2
|
|
31
31
|
Requires-Dist: pyyaml>=6.0.3
|
|
32
|
+
Provides-Extra: analytics
|
|
33
|
+
Requires-Dist: networkx>=3.0; extra == 'analytics'
|
|
34
|
+
Requires-Dist: pandas>=2.0; extra == 'analytics'
|
|
35
|
+
Requires-Dist: python-igraph>=0.11; extra == 'analytics'
|
|
32
36
|
Provides-Extra: dev
|
|
33
37
|
Requires-Dist: hypothesis>=6.0; extra == 'dev'
|
|
34
38
|
Requires-Dist: pytest-bdd>=7.0; extra == 'dev'
|
|
@@ -39,11 +43,12 @@ Requires-Dist: pytest-timeout>=2.0; extra == 'dev'
|
|
|
39
43
|
Requires-Dist: pytest-xdist>=3.0; extra == 'dev'
|
|
40
44
|
Requires-Dist: pytest>=9.0.3; extra == 'dev'
|
|
41
45
|
Requires-Dist: ruff==0.15.12; extra == 'dev'
|
|
42
|
-
Provides-Extra:
|
|
43
|
-
Requires-Dist:
|
|
44
|
-
|
|
45
|
-
Requires-Dist:
|
|
46
|
-
|
|
46
|
+
Provides-Extra: igraph
|
|
47
|
+
Requires-Dist: python-igraph>=0.11; extra == 'igraph'
|
|
48
|
+
Provides-Extra: networkx
|
|
49
|
+
Requires-Dist: networkx>=3.0; extra == 'networkx'
|
|
50
|
+
Provides-Extra: pandas
|
|
51
|
+
Requires-Dist: pandas>=2.0; extra == 'pandas'
|
|
47
52
|
Description-Content-Type: text/markdown
|
|
48
53
|
|
|
49
54
|
<h1 align="center">GraphForge</h1>
|
|
@@ -104,9 +109,13 @@ Modern data science and ML workflows increasingly produce graph-shaped data —
|
|
|
104
109
|
|
|
105
110
|
† *Traversal queries with LIMIT scale to ~20M edges; full-scan aggregations are practical up to ~1M edges.*
|
|
106
111
|
|
|
107
|
-
### v0.
|
|
112
|
+
### v0.4.0 — Three-Surface API
|
|
108
113
|
|
|
109
|
-
v0.
|
|
114
|
+
v0.4.0 ships two new API surfaces alongside the existing Cypher executor:
|
|
115
|
+
|
|
116
|
+
- **`db.gds`** — 8 compiled graph algorithms (PageRank, betweenness, Louvain, triangle count, and more) dispatched to igraph or NetworkX. Results write back to node properties and are immediately queryable via Cypher.
|
|
117
|
+
- **`db.search`** — hybrid retrieval combining FTS5 text search and vector cosine similarity via RRF fusion. Returns `SearchHit` objects with score provenance; every result is addressable in `db.execute()`.
|
|
118
|
+
- **`graphforge.recipes`** — composable helper functions; `neighbourhood()` builds n-hop context for LLM prompts.
|
|
110
119
|
|
|
111
120
|
See [CHANGELOG.md](CHANGELOG.md) for the full list of changes.
|
|
112
121
|
|
|
@@ -176,6 +185,36 @@ bob = db.create_node(['Person'], name='Bob', age=25)
|
|
|
176
185
|
db.create_relationship(alice, bob, 'KNOWS', since=2020)
|
|
177
186
|
```
|
|
178
187
|
|
|
188
|
+
### Graph algorithms
|
|
189
|
+
|
|
190
|
+
```python
|
|
191
|
+
# Compute PageRank and write scores back to nodes
|
|
192
|
+
db.gds.pagerank(write_property="rank")
|
|
193
|
+
|
|
194
|
+
# Query the written scores via Cypher
|
|
195
|
+
top = db.execute("MATCH (n) RETURN n.name, n.rank ORDER BY n.rank DESC LIMIT 5")
|
|
196
|
+
|
|
197
|
+
# Stream mode — returns dict[node_id, score] without mutating the graph
|
|
198
|
+
bc = db.gds.betweenness_centrality()
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Hybrid search
|
|
202
|
+
|
|
203
|
+
```python
|
|
204
|
+
db = GraphForge("research.db")
|
|
205
|
+
|
|
206
|
+
# Index node text for full-text search
|
|
207
|
+
db.search.index_all(node_label="Paper", properties=["title", "abstract"])
|
|
208
|
+
|
|
209
|
+
# Store a precomputed embedding (bring your own model)
|
|
210
|
+
db.search.set_node_vector(node_id, embedding, space="text-embedding-3-small")
|
|
211
|
+
|
|
212
|
+
# Hybrid retrieval — text + vector signals fused via RRF
|
|
213
|
+
results = db.search("graph neural networks", vector=query_embedding, top_k=10)
|
|
214
|
+
for hit in results:
|
|
215
|
+
print(hit.ref.properties["title"].value, hit.score, hit.sources)
|
|
216
|
+
```
|
|
217
|
+
|
|
179
218
|
### Access result values
|
|
180
219
|
|
|
181
220
|
Results contain `CypherValue` objects — use `.value` to get the Python value:
|
|
@@ -326,7 +365,15 @@ finally:
|
|
|
326
365
|
|
|
327
366
|
## Architecture
|
|
328
367
|
|
|
329
|
-
GraphForge
|
|
368
|
+
GraphForge exposes three independent API surfaces over a shared storage layer:
|
|
369
|
+
|
|
370
|
+
```
|
|
371
|
+
db.execute("MATCH ...") → Cypher path (Parser → Planner → Executor → Storage)
|
|
372
|
+
db.gds.pagerank(...) → Algorithm path (export → compiled backend → write-back)
|
|
373
|
+
db.search.fts(...) → Search path (SQLite FTS5 / vector index → NodeRef list)
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
The Cypher path is four independent layers:
|
|
330
377
|
|
|
331
378
|
```
|
|
332
379
|
┌─────────────────────────────────────────────────┐
|
|
@@ -336,11 +383,11 @@ GraphForge is built in four independent layers:
|
|
|
336
383
|
├─────────────────────────────────────────────────┤
|
|
337
384
|
│ Executor executor.py + evaluator.py │ Plan → Results
|
|
338
385
|
├─────────────────────────────────────────────────┤
|
|
339
|
-
│ Storage memory.py + sqlite_backend.py │ In-memory + SQLite
|
|
386
|
+
│ Storage memory.py + sqlite_backend.py │ In-memory + SQLite WAL
|
|
340
387
|
└─────────────────────────────────────────────────┘
|
|
341
388
|
```
|
|
342
389
|
|
|
343
|
-
|
|
390
|
+
The algorithm and search paths bypass the Cypher executor entirely — `db.gds` and `db.search` are Python-method surfaces, not Cypher extensions. Storage uses **MessagePack** for efficient binary encoding of graph properties.
|
|
344
391
|
|
|
345
392
|
---
|
|
346
393
|
|
|
@@ -369,9 +416,8 @@ make coverage
|
|
|
369
416
|
|---------|-------|--------|
|
|
370
417
|
| v0.3.8 | Full TCK compliance (3,885/3,885) | **Released** |
|
|
371
418
|
| v0.3.9 | Performance: LALR parser, property indexes, bulk ingest, SQLite tuning, LIMIT short-circuit | **Released** |
|
|
372
|
-
| v0.3.10 | Analytics integration: NetworkX/igraph export, parse/plan cache |
|
|
373
|
-
| v0.4.0 |
|
|
374
|
-
| v1.0 | Production-ready: thread safety, large graph support | Future |
|
|
419
|
+
| v0.3.10 | Analytics integration: NetworkX/igraph export, parse/plan cache, `add_graph_documents()` | **Released** |
|
|
420
|
+
| v0.4.0 | Three-surface API: `db.gds.*` graph algorithms + `db.search.*` hybrid retrieval | **Released** |
|
|
375
421
|
|
|
376
422
|
See [CHANGELOG.md](CHANGELOG.md) for full release history.
|
|
377
423
|
|
|
@@ -56,9 +56,13 @@ Modern data science and ML workflows increasingly produce graph-shaped data —
|
|
|
56
56
|
|
|
57
57
|
† *Traversal queries with LIMIT scale to ~20M edges; full-scan aggregations are practical up to ~1M edges.*
|
|
58
58
|
|
|
59
|
-
### v0.
|
|
59
|
+
### v0.4.0 — Three-Surface API
|
|
60
60
|
|
|
61
|
-
v0.
|
|
61
|
+
v0.4.0 ships two new API surfaces alongside the existing Cypher executor:
|
|
62
|
+
|
|
63
|
+
- **`db.gds`** — 8 compiled graph algorithms (PageRank, betweenness, Louvain, triangle count, and more) dispatched to igraph or NetworkX. Results write back to node properties and are immediately queryable via Cypher.
|
|
64
|
+
- **`db.search`** — hybrid retrieval combining FTS5 text search and vector cosine similarity via RRF fusion. Returns `SearchHit` objects with score provenance; every result is addressable in `db.execute()`.
|
|
65
|
+
- **`graphforge.recipes`** — composable helper functions; `neighbourhood()` builds n-hop context for LLM prompts.
|
|
62
66
|
|
|
63
67
|
See [CHANGELOG.md](CHANGELOG.md) for the full list of changes.
|
|
64
68
|
|
|
@@ -128,6 +132,36 @@ bob = db.create_node(['Person'], name='Bob', age=25)
|
|
|
128
132
|
db.create_relationship(alice, bob, 'KNOWS', since=2020)
|
|
129
133
|
```
|
|
130
134
|
|
|
135
|
+
### Graph algorithms
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
# Compute PageRank and write scores back to nodes
|
|
139
|
+
db.gds.pagerank(write_property="rank")
|
|
140
|
+
|
|
141
|
+
# Query the written scores via Cypher
|
|
142
|
+
top = db.execute("MATCH (n) RETURN n.name, n.rank ORDER BY n.rank DESC LIMIT 5")
|
|
143
|
+
|
|
144
|
+
# Stream mode — returns dict[node_id, score] without mutating the graph
|
|
145
|
+
bc = db.gds.betweenness_centrality()
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Hybrid search
|
|
149
|
+
|
|
150
|
+
```python
|
|
151
|
+
db = GraphForge("research.db")
|
|
152
|
+
|
|
153
|
+
# Index node text for full-text search
|
|
154
|
+
db.search.index_all(node_label="Paper", properties=["title", "abstract"])
|
|
155
|
+
|
|
156
|
+
# Store a precomputed embedding (bring your own model)
|
|
157
|
+
db.search.set_node_vector(node_id, embedding, space="text-embedding-3-small")
|
|
158
|
+
|
|
159
|
+
# Hybrid retrieval — text + vector signals fused via RRF
|
|
160
|
+
results = db.search("graph neural networks", vector=query_embedding, top_k=10)
|
|
161
|
+
for hit in results:
|
|
162
|
+
print(hit.ref.properties["title"].value, hit.score, hit.sources)
|
|
163
|
+
```
|
|
164
|
+
|
|
131
165
|
### Access result values
|
|
132
166
|
|
|
133
167
|
Results contain `CypherValue` objects — use `.value` to get the Python value:
|
|
@@ -278,7 +312,15 @@ finally:
|
|
|
278
312
|
|
|
279
313
|
## Architecture
|
|
280
314
|
|
|
281
|
-
GraphForge
|
|
315
|
+
GraphForge exposes three independent API surfaces over a shared storage layer:
|
|
316
|
+
|
|
317
|
+
```
|
|
318
|
+
db.execute("MATCH ...") → Cypher path (Parser → Planner → Executor → Storage)
|
|
319
|
+
db.gds.pagerank(...) → Algorithm path (export → compiled backend → write-back)
|
|
320
|
+
db.search.fts(...) → Search path (SQLite FTS5 / vector index → NodeRef list)
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
The Cypher path is four independent layers:
|
|
282
324
|
|
|
283
325
|
```
|
|
284
326
|
┌─────────────────────────────────────────────────┐
|
|
@@ -288,11 +330,11 @@ GraphForge is built in four independent layers:
|
|
|
288
330
|
├─────────────────────────────────────────────────┤
|
|
289
331
|
│ Executor executor.py + evaluator.py │ Plan → Results
|
|
290
332
|
├─────────────────────────────────────────────────┤
|
|
291
|
-
│ Storage memory.py + sqlite_backend.py │ In-memory + SQLite
|
|
333
|
+
│ Storage memory.py + sqlite_backend.py │ In-memory + SQLite WAL
|
|
292
334
|
└─────────────────────────────────────────────────┘
|
|
293
335
|
```
|
|
294
336
|
|
|
295
|
-
|
|
337
|
+
The algorithm and search paths bypass the Cypher executor entirely — `db.gds` and `db.search` are Python-method surfaces, not Cypher extensions. Storage uses **MessagePack** for efficient binary encoding of graph properties.
|
|
296
338
|
|
|
297
339
|
---
|
|
298
340
|
|
|
@@ -321,9 +363,8 @@ make coverage
|
|
|
321
363
|
|---------|-------|--------|
|
|
322
364
|
| v0.3.8 | Full TCK compliance (3,885/3,885) | **Released** |
|
|
323
365
|
| v0.3.9 | Performance: LALR parser, property indexes, bulk ingest, SQLite tuning, LIMIT short-circuit | **Released** |
|
|
324
|
-
| v0.3.10 | Analytics integration: NetworkX/igraph export, parse/plan cache |
|
|
325
|
-
| v0.4.0 |
|
|
326
|
-
| v1.0 | Production-ready: thread safety, large graph support | Future |
|
|
366
|
+
| v0.3.10 | Analytics integration: NetworkX/igraph export, parse/plan cache, `add_graph_documents()` | **Released** |
|
|
367
|
+
| v0.4.0 | Three-surface API: `db.gds.*` graph algorithms + `db.search.*` hybrid retrieval | **Released** |
|
|
327
368
|
|
|
328
369
|
See [CHANGELOG.md](CHANGELOG.md) for full release history.
|
|
329
370
|
|