Skip to content

Commit e51e2f8

Browse files
authored
adapter.aasx: Add rename_file to DictSupplementaryFileContainer (#434)
`adapter.aasx`: Add `rename_file` to `DictSupplementaryFileContainer` Before: There was no supported way to rename supplementary files in `DictSupplementaryFileContainer`. Workflow had to manipulate internals or create duplicates, making file handling error-prone. Now: A public rename operation preserves content de-duplication and resolves name conflicts, simplifying AASX read/write flows and reducing inconsistent mappings.
1 parent 562b967 commit e51e2f8

File tree

2 files changed

+45
-11
lines changed

2 files changed

+45
-11
lines changed

sdk/basyx/aas/adapter/aasx.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -860,15 +860,25 @@ def add_file(self, name: str, file: IO[bytes], content_type: str) -> str:
860860
if hash not in self._store:
861861
self._store[hash] = data
862862
self._store_refcount[hash] = 0
863-
name_map_data = (hash, content_type)
863+
return self._assign_unique_name(name, hash, content_type)
864+
865+
def rename_file(self, old_name: str, new_name: str) -> str:
866+
if old_name not in self._name_map:
867+
raise KeyError(f"File with name {old_name} not found in SupplementaryFileContainer.")
868+
if new_name == old_name:
869+
return new_name
870+
file_hash, file_content_type = self._name_map[old_name]
871+
del self._name_map[old_name]
872+
return self._assign_unique_name(new_name, file_hash, file_content_type)
873+
874+
def _assign_unique_name(self, name: str, sha: bytes, content_type: str) -> str:
864875
new_name = name
865876
i = 1
866877
while True:
867878
if new_name not in self._name_map:
868-
self._name_map[new_name] = name_map_data
869-
self._store_refcount[hash] += 1
879+
self._name_map[new_name] = (sha, content_type)
870880
return new_name
871-
elif self._name_map[new_name] == name_map_data:
881+
elif self._name_map[new_name] == (sha, content_type):
872882
return new_name
873883
new_name = self._append_counter(name, i)
874884
i += 1

sdk/test/adapter/aasx/test_aasx.py

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,43 @@ class TestAASXUtils(unittest.TestCase):
2222
def test_supplementary_file_container(self) -> None:
2323
container = aasx.DictSupplementaryFileContainer()
2424
with open(os.path.join(os.path.dirname(__file__), 'TestFile.pdf'), 'rb') as f:
25-
new_name = container.add_file("/TestFile.pdf", f, "application/pdf")
25+
saved_file_name = container.add_file("/TestFile.pdf", f, "application/pdf")
2626
# Name should not be modified, since there is no conflict
27-
self.assertEqual("/TestFile.pdf", new_name)
27+
self.assertEqual("/TestFile.pdf", saved_file_name)
2828
f.seek(0)
29-
container.add_file("/TestFile.pdf", f, "application/pdf")
29+
# Add the same file again with the same name
30+
same_file_with_same_name = container.add_file("/TestFile.pdf", f, "application/pdf")
3031
# Name should not be modified, since there is still no conflict
31-
self.assertEqual("/TestFile.pdf", new_name)
32+
self.assertEqual("/TestFile.pdf", same_file_with_same_name)
3233

34+
# Add other file with the same name to create a conflict
3335
with open(__file__, 'rb') as f:
34-
new_name = container.add_file("/TestFile.pdf", f, "application/pdf")
36+
saved_file_name_2 = container.add_file("/TestFile.pdf", f, "application/pdf")
3537
# Now, we have a conflict
36-
self.assertNotEqual("/TestFile.pdf", new_name)
37-
self.assertIn(new_name, container)
38+
self.assertNotEqual(saved_file_name, saved_file_name_2)
39+
self.assertIn(saved_file_name_2, container)
40+
41+
# Rename file to a new unique name
42+
renamed = container.rename_file(saved_file_name_2, "/RenamedTestFile.pdf")
43+
self.assertIn(renamed, container)
44+
# Old name should no longer exist
45+
self.assertNotIn(saved_file_name_2, container)
46+
self.assertEqual(renamed, "/RenamedTestFile.pdf")
47+
48+
# Renaming to the same name should be no-op
49+
renamed_same = container.rename_file(renamed, renamed)
50+
self.assertEqual(renamed, renamed_same)
51+
52+
# Renaming to an existing name should create a conflict
53+
renamed_conflict = container.rename_file(renamed, "/TestFile.pdf")
54+
self.assertNotEqual(renamed_conflict, "/TestFile.pdf")
55+
self.assertIn(renamed_conflict, container)
56+
57+
# Renaming a non-existing file should raise KeyError
58+
with self.assertRaises(KeyError):
59+
container.rename_file("/NonExistingFile.pdf", "/AnotherName.pdf")
60+
61+
new_name = renamed_conflict
3862

3963
# Check metadata
4064
self.assertEqual("application/pdf", container.get_content_type("/TestFile.pdf"))

0 commit comments

Comments
 (0)