44from datetime import datetime , timezone
55
66from basic_memory .models .knowledge import Entity
7- from basic_memory .models .project import Project
87from basic_memory .repository .entity_repository import EntityRepository
98from basic_memory .repository .project_repository import ProjectRepository
109
@@ -246,22 +245,22 @@ async def test_upsert_entity_gap_in_suffixes(entity_repository: EntityRepository
246245
247246 # Should get the next available suffix - our implementation finds gaps
248247 # so it should be "test/gap-2" (filling the gap)
249- assert result .permalink == "test/gap-2"
248+ assert result .permalink == "test/gap-2"
250249 assert result .title == "Gap Filler"
251250
252251
253252@pytest .mark .asyncio
254253async def test_upsert_entity_project_scoping_isolation (session_maker ):
255254 """Test that upsert_entity properly scopes entities by project_id.
256-
255+
257256 This test ensures that the fix for issue #167 works correctly by verifying:
258257 1. Entities with same permalinks/file_paths can exist in different projects
259258 2. Upsert operations properly scope queries by project_id
260259 3. No "multiple rows" errors occur when similar entities exist across projects
261260 """
262261 # Create two separate projects
263262 project_repository = ProjectRepository (session_maker )
264-
263+
265264 project1_data = {
266265 "name" : "project-1" ,
267266 "description" : "First test project" ,
@@ -270,20 +269,20 @@ async def test_upsert_entity_project_scoping_isolation(session_maker):
270269 "is_default" : False ,
271270 }
272271 project1 = await project_repository .create (project1_data )
273-
272+
274273 project2_data = {
275- "name" : "project-2" ,
274+ "name" : "project-2" ,
276275 "description" : "Second test project" ,
277276 "path" : "/tmp/project2" ,
278277 "is_active" : True ,
279278 "is_default" : False ,
280279 }
281280 project2 = await project_repository .create (project2_data )
282-
281+
283282 # Create entity repositories for each project
284283 repo1 = EntityRepository (session_maker , project_id = project1 .id )
285284 repo2 = EntityRepository (session_maker , project_id = project2 .id )
286-
285+
287286 # Create entities with identical permalinks and file_paths in different projects
288287 entity1 = Entity (
289288 project_id = project1 .id ,
@@ -295,22 +294,22 @@ async def test_upsert_entity_project_scoping_isolation(session_maker):
295294 created_at = datetime .now (timezone .utc ),
296295 updated_at = datetime .now (timezone .utc ),
297296 )
298-
297+
299298 entity2 = Entity (
300299 project_id = project2 .id ,
301300 title = "Shared Entity" ,
302- entity_type = "note" ,
301+ entity_type = "note" ,
303302 permalink = "docs/shared-name" , # Same permalink
304303 file_path = "docs/shared-name.md" , # Same file_path
305304 content_type = "text/markdown" ,
306305 created_at = datetime .now (timezone .utc ),
307306 updated_at = datetime .now (timezone .utc ),
308307 )
309-
308+
310309 # These should succeed without "multiple rows" errors
311310 result1 = await repo1 .upsert_entity (entity1 )
312311 result2 = await repo2 .upsert_entity (entity2 )
313-
312+
314313 # Verify both entities were created successfully
315314 assert result1 .id is not None
316315 assert result2 .id is not None
@@ -319,7 +318,7 @@ async def test_upsert_entity_project_scoping_isolation(session_maker):
319318 assert result2 .project_id == project2 .id
320319 assert result1 .permalink == "docs/shared-name"
321320 assert result2 .permalink == "docs/shared-name"
322-
321+
323322 # Test updating entities in different projects (should also work without conflicts)
324323 entity1_update = Entity (
325324 project_id = project1 .id ,
@@ -331,7 +330,7 @@ async def test_upsert_entity_project_scoping_isolation(session_maker):
331330 created_at = datetime .now (timezone .utc ),
332331 updated_at = datetime .now (timezone .utc ),
333332 )
334-
333+
335334 entity2_update = Entity (
336335 project_id = project2 .id ,
337336 title = "Also Updated Shared Entity" ,
@@ -342,21 +341,21 @@ async def test_upsert_entity_project_scoping_isolation(session_maker):
342341 created_at = datetime .now (timezone .utc ),
343342 updated_at = datetime .now (timezone .utc ),
344343 )
345-
344+
346345 # Updates should work without conflicts
347346 updated1 = await repo1 .upsert_entity (entity1_update )
348347 updated2 = await repo2 .upsert_entity (entity2_update )
349-
348+
350349 # Should update existing entities (same IDs)
351350 assert updated1 .id == result1 .id
352351 assert updated2 .id == result2 .id
353352 assert updated1 .title == "Updated Shared Entity"
354353 assert updated2 .title == "Also Updated Shared Entity"
355-
354+
356355 # Verify cross-project queries don't interfere
357356 found_in_project1 = await repo1 .get_by_permalink ("docs/shared-name" )
358357 found_in_project2 = await repo2 .get_by_permalink ("docs/shared-name" )
359-
358+
360359 assert found_in_project1 is not None
361360 assert found_in_project2 is not None
362361 assert found_in_project1 .id == updated1 .id
@@ -368,14 +367,14 @@ async def test_upsert_entity_project_scoping_isolation(session_maker):
368367@pytest .mark .asyncio
369368async def test_upsert_entity_permalink_conflict_within_project_only (session_maker ):
370369 """Test that permalink conflicts only occur within the same project.
371-
370+
372371 This ensures that the project scoping fix allows entities with identical
373- permalinks to exist across different projects without triggering
372+ permalinks to exist across different projects without triggering
374373 permalink conflict resolution.
375374 """
376375 # Create two separate projects
377376 project_repository = ProjectRepository (session_maker )
378-
377+
379378 project1_data = {
380379 "name" : "conflict-project-1" ,
381380 "description" : "First conflict test project" ,
@@ -384,20 +383,20 @@ async def test_upsert_entity_permalink_conflict_within_project_only(session_make
384383 "is_default" : False ,
385384 }
386385 project1 = await project_repository .create (project1_data )
387-
386+
388387 project2_data = {
389388 "name" : "conflict-project-2" ,
390- "description" : "Second conflict test project" ,
389+ "description" : "Second conflict test project" ,
391390 "path" : "/tmp/conflict2" ,
392391 "is_active" : True ,
393392 "is_default" : False ,
394393 }
395394 project2 = await project_repository .create (project2_data )
396-
395+
397396 # Create entity repositories for each project
398397 repo1 = EntityRepository (session_maker , project_id = project1 .id )
399398 repo2 = EntityRepository (session_maker , project_id = project2 .id )
400-
399+
401400 # Create first entity in project1
402401 entity1 = Entity (
403402 project_id = project1 .id ,
@@ -409,10 +408,10 @@ async def test_upsert_entity_permalink_conflict_within_project_only(session_make
409408 created_at = datetime .now (timezone .utc ),
410409 updated_at = datetime .now (timezone .utc ),
411410 )
412-
411+
413412 result1 = await repo1 .upsert_entity (entity1 )
414413 assert result1 .permalink == "test/conflict-permalink"
415-
414+
416415 # Create entity with same permalink in project2 (should NOT get suffix)
417416 entity2 = Entity (
418417 project_id = project2 .id ,
@@ -424,11 +423,11 @@ async def test_upsert_entity_permalink_conflict_within_project_only(session_make
424423 created_at = datetime .now (timezone .utc ),
425424 updated_at = datetime .now (timezone .utc ),
426425 )
427-
426+
428427 result2 = await repo2 .upsert_entity (entity2 )
429428 # Should keep original permalink (no suffix) since it's in a different project
430429 assert result2 .permalink == "test/conflict-permalink"
431-
430+
432431 # Now create entity with same permalink in project1 (should get suffix)
433432 entity3 = Entity (
434433 project_id = project1 .id ,
@@ -440,11 +439,11 @@ async def test_upsert_entity_permalink_conflict_within_project_only(session_make
440439 created_at = datetime .now (timezone .utc ),
441440 updated_at = datetime .now (timezone .utc ),
442441 )
443-
442+
444443 result3 = await repo1 .upsert_entity (entity3 )
445444 # Should get suffix since it conflicts within the same project
446445 assert result3 .permalink == "test/conflict-permalink-1"
447-
446+
448447 # Verify all entities exist correctly
449448 assert result1 .id != result2 .id != result3 .id
450449 assert result1 .project_id == project1 .id
0 commit comments