-
Notifications
You must be signed in to change notification settings - Fork 966
Cog 475 local file endpoint deletion #391
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 12 commits
f6800b9
ee6bc17
d9368c6
c139d52
418cb65
1406b6f
6cb7fef
7232b04
d7195f9
a4fe33c
450bef4
14dbe6c
e631161
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,4 +17,4 @@ async def delete_data(data: Data): | |
|
|
||
| db_engine = get_relational_engine() | ||
|
|
||
| return await db_engine.delete_data_by_id(data.__tablename__, data.id) | ||
| return await db_engine.delete_data_entity(data.id) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Codebase verification Based on the gathered information, I can now provide the final response: Error handling improvements needed for file operations The
However, the file deletion operation using
Action items:
🔗 Analysis chainVerify error handling in delete_data_entity The function now uses
Let me gather more information about the error handling implementation since the previous results were truncated. Let me check one more aspect to see how the file deletion errors are handled. 🏁 Scripts executedThe following scripts were executed for the analysis: Script: #!/bin/bash
# Description: Look for error handling in the delete_data_entity implementation
echo "Checking error handling in delete_data_entity implementation..."
rg -A 10 "async def delete_data_entity"
echo "\nChecking for try-catch blocks around file operations..."
ast-grep --pattern 'try {
$$$
delete_data_entity
$$$
}'
Length of output: 1758 Script: #!/bin/bash
# Get full implementation of delete_data_entity including try-catch blocks
rg -A 20 "async def delete_data_entity"
# Look for any file deletion operations in the same file
echo "\nChecking file deletion operations..."
rg "unlink|remove|delete.*file" cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py
Length of output: 3324 Script: #!/bin/bash
# Look for try-catch blocks around the file deletion operation
rg -B 5 -A 5 "os.remove\(.*raw_data_location" cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py
# Check if there are any custom exceptions defined for file operations
echo "\nChecking for file operation related exceptions..."
rg "class.*Error" cognee/infrastructure/databases/relational/sqlalchemy/SqlAlchemyAdapter.py
Length of output: 940 |
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,12 +2,53 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||
| import logging | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import pathlib | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import cognee | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from cognee.modules.data.models import Data | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from cognee.api.v1.search import SearchType | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from cognee.modules.retrieval.brute_force_triplet_search import brute_force_triplet_search | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from cognee.modules.users.methods import get_default_user | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logging.basicConfig(level=logging.DEBUG) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async def test_local_file_deletion(data_text, file_location): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from sqlalchemy import select | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import hashlib | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from cognee.infrastructure.databases.relational import get_relational_engine | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| engine = get_relational_engine() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async with engine.get_async_session() as session: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Get hash of data contents | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| encoded_text = data_text.encode("utf-8") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| data_hash = hashlib.md5(encoded_text).hexdigest() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+22
to
+23
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider using a more secure hashing algorithm MD5 is cryptographically weak and susceptible to hash collisions. Consider using a more secure algorithm like SHA-256. - encoded_text = data_text.encode("utf-8")
- data_hash = hashlib.md5(encoded_text).hexdigest()
+ encoded_text = data_text.encode("utf-8")
+ data_hash = hashlib.sha256(encoded_text).hexdigest()📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Get data entry from database based on hash contents | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| data = (await session.scalars(select(Data).where(Data.content_hash == data_hash))).one() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert os.path.isfile(data.raw_data_location), f"Data location doesn't exist: {data.raw_data_location}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
borisarzentar marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Test deletion of data along with local files created by cognee | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await engine.delete_data_entity(data.id) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert not os.path.exists( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| data.raw_data_location), f"Data location still exists after deletion: {data.raw_data_location}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async with engine.get_async_session() as session: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Get data entry from database based on file path | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| data = (await session.scalars(select(Data).where(Data.raw_data_location == file_location))).one() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert os.path.isfile(data.raw_data_location), f"Data location doesn't exist: {data.raw_data_location}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Test local files not created by cognee won't get deleted | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await engine.delete_data_entity(data.id) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert os.path.exists(data.raw_data_location), f"Data location doesn't exists: {data.raw_data_location}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async def test_getting_of_documents(dataset_name_1): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Test getting of documents for search per dataset | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from cognee.modules.users.permissions.methods import get_document_ids_for_user | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| user = await get_default_user() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| document_ids = await get_document_ids_for_user(user.id, [dataset_name_1]) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert len(document_ids) == 1, f"Number of expected documents doesn't match {len(document_ids)} != 1" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Test getting of documents for search when no dataset is provided | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| user = await get_default_user() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| document_ids = await get_document_ids_for_user(user.id) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert len(document_ids) == 2, f"Number of expected documents doesn't match {len(document_ids)} != 2" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+40
to
+50
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Improve test function structure and assertions Several improvements needed:
async def test_getting_of_documents(dataset_name_1):
+ """
+ Test document retrieval functionality:
+ 1. Verify correct document count when filtering by dataset
+ 2. Verify correct document count when no dataset filter is applied
+ """
# Test getting of documents for search per dataset
from cognee.modules.users.permissions.methods import get_document_ids_for_user
user = await get_default_user()
document_ids = await get_document_ids_for_user(user.id, [dataset_name_1])
- assert len(document_ids) == 1, f"Number of expected documents doesn't match {len(document_ids)} != 1"
+ assert len(document_ids) == 1, f"Expected 1 document when filtering by dataset, but got {len(document_ids)}"
# Test getting of documents for search when no dataset is provided
- user = await get_default_user() # Duplicate user retrieval
document_ids = await get_document_ids_for_user(user.id)
- assert len(document_ids) == 2, f"Number of expected documents doesn't match {len(document_ids)} != 2"
+ assert len(document_ids) == 2, f"Expected 2 documents without dataset filter, but got {len(document_ids)}"📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async def main(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cognee.config.set_vector_db_config( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -67,16 +108,7 @@ async def main(): | |||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from cognee.infrastructure.databases.vector import get_vector_engine | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Test getting of documents for search per dataset | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from cognee.modules.users.permissions.methods import get_document_ids_for_user | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| user = await get_default_user() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| document_ids = await get_document_ids_for_user(user.id, [dataset_name_1]) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert len(document_ids) == 1, f"Number of expected documents doesn't match {len(document_ids)} != 1" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Test getting of documents for search when no dataset is provided | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| user = await get_default_user() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| document_ids = await get_document_ids_for_user(user.id) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert len(document_ids) == 2, f"Number of expected documents doesn't match {len(document_ids)} != 2" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await test_getting_of_documents(dataset_name_1) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| vector_engine = get_vector_engine() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| random_node = (await vector_engine.search("entity_name", "Quantum computer"))[0] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -106,6 +138,8 @@ async def main(): | |||||||||||||||||||||||||||||||||||||||||||||||||||||
| results = await brute_force_triplet_search('What is a quantum computer?') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert len(results) > 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await test_local_file_deletion(text, explanation_file_path) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await cognee.prune.prune_data() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert not os.path.isdir(data_directory_path), "Local data files are not deleted" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.