From c834c7b52dec52d3b8a7427eeef99657cb02df31 Mon Sep 17 00:00:00 2001 From: Daniel Chalef <131175+danielchalef@users.noreply.github.com> Date: Sat, 30 Aug 2025 08:53:57 -0700 Subject: [PATCH] docs: Add pre-commit formatting and linting requirements to CLAUDE.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add explicit instructions to always run formatting before commits - Include both make commands and direct uv commands - Emphasize this is a required step, not optional - Place in Development Guidelines section for visibility This ensures all code contributions maintain consistent style and quality. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- CLAUDE.md | 17 ++++++++++++++++ graphiti_core/search/search_utils.py | 4 +--- mcp_server/src/services/factories.py | 2 +- pyproject.toml | 5 +++++ tests/test_graphiti_mock.py | 30 +++++++++++++++++++--------- tests/test_node_int.py | 4 +++- uv.lock | 10 +++++++++- 7 files changed, 57 insertions(+), 15 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 7b02a6fb..89272924 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -118,6 +118,23 @@ docker-compose up - Type checking with Pyright is enforced - Main project uses `typeCheckingMode = "basic"`, server uses `typeCheckingMode = "standard"` +### Pre-Commit Requirements + +**IMPORTANT:** Always format and lint code before committing: + +```bash +# Format code (required before commit) +make format # or: uv run ruff format + +# Lint code (required before commit) +make lint # or: uv run ruff check --fix && uv run pyright + +# Run all checks (format + lint + test) +make check +``` + +**Never commit code without running these commands first.** This ensures code quality and consistency across the codebase. + ### Testing Requirements - Run tests with `make test` or `pytest` diff --git a/graphiti_core/search/search_utils.py b/graphiti_core/search/search_utils.py index 6c61ab24..b13c3188 100644 --- a/graphiti_core/search/search_utils.py +++ b/graphiti_core/search/search_utils.py @@ -605,9 +605,7 @@ async def node_fulltext_search( + (group_ids[0].replace('-', '') if group_ids is not None else '') ) query = ( - get_nodes_query( - index_name, '$query', limit=limit, provider=driver.provider - ) + get_nodes_query(index_name, '$query', limit=limit, provider=driver.provider) + yield_query + filter_query + """ diff --git a/mcp_server/src/services/factories.py b/mcp_server/src/services/factories.py index 683685dc..21f43a4e 100644 --- a/mcp_server/src/services/factories.py +++ b/mcp_server/src/services/factories.py @@ -339,7 +339,7 @@ class DatabaseDriverFactory: uri = os.environ.get('FALKORDB_URI', falkor_config.uri) password = os.environ.get('FALKORDB_PASSWORD', falkor_config.password) - + # Parse the URI to extract host and port parsed = urlparse(uri) host = parsed.hostname or 'localhost' diff --git a/pyproject.toml b/pyproject.toml index 134c7077..6bc1efab 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -97,3 +97,8 @@ docstring-code-format = true include = ["graphiti_core"] pythonVersion = "3.10" typeCheckingMode = "basic" + +[dependency-groups] +dev = [ + "pyright>=1.1.404", +] diff --git a/tests/test_graphiti_mock.py b/tests/test_graphiti_mock.py index 9426dc9f..f2ba89ec 100644 --- a/tests/test_graphiti_mock.py +++ b/tests/test_graphiti_mock.py @@ -116,9 +116,7 @@ def mock_cross_encoder_client(): @pytest.mark.asyncio -async def test_add_bulk( - graph_driver, mock_llm_client, mock_embedder, mock_cross_encoder_client -): +async def test_add_bulk(graph_driver, mock_llm_client, mock_embedder, mock_cross_encoder_client): if graph_driver.provider == GraphProvider.FALKORDB: pytest.skip('Skipping as test fails on FalkorDB') @@ -143,7 +141,7 @@ async def test_add_bulk( source_description='conversation message', content='Alice likes Bob', valid_at=now, - entity_edges=[], # Filled in later + entity_edges=[], # Filled in later ) episode_node_2 = EpisodicNode( name='test_episode_2', @@ -154,7 +152,7 @@ async def test_add_bulk( source_description='conversation message', content='Bob adores Alice', valid_at=now, - entity_edges=[], # Filled in later + entity_edges=[], # Filled in later ) # Create entity nodes @@ -269,8 +267,22 @@ async def test_add_bulk( mock_embedder, ) - node_ids = [episode_node_1.uuid, episode_node_2.uuid, entity_node_1.uuid, entity_node_2.uuid, entity_node_3.uuid, entity_node_4.uuid] - edge_ids = [episodic_edge_1.uuid, episodic_edge_2.uuid, episodic_edge_3.uuid, episodic_edge_4.uuid, entity_edge_1.uuid, entity_edge_2.uuid] + node_ids = [ + episode_node_1.uuid, + episode_node_2.uuid, + entity_node_1.uuid, + entity_node_2.uuid, + entity_node_3.uuid, + entity_node_4.uuid, + ] + edge_ids = [ + episodic_edge_1.uuid, + episodic_edge_2.uuid, + episodic_edge_3.uuid, + episodic_edge_4.uuid, + entity_edge_1.uuid, + entity_edge_2.uuid, + ] node_count = await get_node_count(graph_driver, node_ids) assert node_count == len(node_ids) edge_count = await get_edge_count(graph_driver, edge_ids) @@ -290,7 +302,6 @@ async def test_add_bulk( retrieved_entity_node = await EntityNode.get_by_uuid(graph_driver, entity_node_2.uuid) await assert_entity_node_equals(graph_driver, retrieved_entity_node, entity_node_2) - retrieved_entity_node = await EntityNode.get_by_uuid(graph_driver, entity_node_3.uuid) await assert_entity_node_equals(graph_driver, retrieved_entity_node, entity_node_3) @@ -317,6 +328,7 @@ async def test_add_bulk( retrieved_entity_edge = await EntityEdge.get_by_uuid(graph_driver, entity_edge_2.uuid) await assert_entity_edge_equals(graph_driver, retrieved_entity_edge, entity_edge_2) + @pytest.mark.asyncio async def test_remove_episode( graph_driver, mock_llm_client, mock_embedder, mock_cross_encoder_client @@ -342,7 +354,7 @@ async def test_remove_episode( source_description='conversation message', content='Alice likes Bob', valid_at=now, - entity_edges=[], # Filled in later + entity_edges=[], # Filled in later ) # Create entity nodes diff --git a/tests/test_node_int.py b/tests/test_node_int.py index edaa017a..7e73b856 100644 --- a/tests/test_node_int.py +++ b/tests/test_node_int.py @@ -103,7 +103,9 @@ async def test_entity_node(sample_entity_node, graph_driver): await assert_entity_node_equals(graph_driver, retrieved[0], sample_entity_node) # Get node by group ids - retrieved = await EntityNode.get_by_group_ids(graph_driver, [group_id], limit=2, with_embeddings=True) + retrieved = await EntityNode.get_by_group_ids( + graph_driver, [group_id], limit=2, with_embeddings=True + ) assert len(retrieved) == 1 await assert_entity_node_equals(graph_driver, retrieved[0], sample_entity_node) diff --git a/uv.lock b/uv.lock index 43eb12c2..38b18a27 100644 --- a/uv.lock +++ b/uv.lock @@ -600,7 +600,7 @@ name = "exceptiongroup" version = "1.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.13'" }, + { name = "typing-extensions", marker = "python_full_version < '3.12'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749 } wheels = [ @@ -869,6 +869,11 @@ voyageai = [ { name = "voyageai" }, ] +[package.dev-dependencies] +dev = [ + { name = "pyright" }, +] + [package.metadata] requires-dist = [ { name = "anthropic", marker = "extra == 'anthropic'", specifier = ">=0.49.0" }, @@ -913,6 +918,9 @@ requires-dist = [ { name = "voyageai", marker = "extra == 'voyageai'", specifier = ">=0.2.3" }, ] +[package.metadata.requires-dev] +dev = [{ name = "pyright", specifier = ">=1.1.404" }] + [[package]] name = "groq" version = "0.31.0"