diff --git a/sdk/basyx/aas/backend/local_file.py b/sdk/basyx/aas/backend/local_file.py index 4008497a..72d5605a 100644 --- a/sdk/basyx/aas/backend/local_file.py +++ b/sdk/basyx/aas/backend/local_file.py @@ -150,7 +150,7 @@ def __len__(self) -> int: :return: The number of objects (determined from the number of documents) """ logger.debug("Fetching number of documents from database ...") - return len(os.listdir(self.directory_path)) + return sum(1 for f in os.listdir(self.directory_path) if f.lower().endswith(".json")) def __iter__(self) -> Iterator[model.Identifiable]: """ @@ -161,7 +161,8 @@ def __iter__(self) -> Iterator[model.Identifiable]: """ logger.debug("Iterating over objects in database ...") for name in os.listdir(self.directory_path): - yield self.get_identifiable_by_hash(name.rstrip(".json")) + if name.lower().endswith(".json"): + yield self.get_identifiable_by_hash(name[:-5]) @staticmethod def _transform_id(identifier: model.Identifier) -> str: diff --git a/sdk/test/backend/test_local_file.py b/sdk/test/backend/test_local_file.py index adcbfcc7..f1080240 100644 --- a/sdk/test/backend/test_local_file.py +++ b/sdk/test/backend/test_local_file.py @@ -107,6 +107,33 @@ def test_key_errors(self) -> None: self.assertEqual("'No AAS object with id https://example.org/Test_Submodel exists in " "local file database'", str(cm.exception)) + def test_add_and_len_consistent(self) -> None: + # Each add() must increment len() by exactly 1 + example_data = list(create_full_example()) + for i, item in enumerate(example_data): + self.identifiable_store.add(item) + self.assertEqual(i + 1, len(self.identifiable_store)) + + # Stray non-json file must not be counted + stray = os.path.join(store_path, ".DS_Store") + with open(stray, "w") as f: + f.write("stray") + self.assertEqual(len(example_data), len(self.identifiable_store)) + os.remove(stray) + + def test_iter_ignores_non_json_files(self) -> None: + example_data = create_full_example() + for item in example_data: + self.identifiable_store.add(item) + + # Stray files must not crash the iterator or be yielded + stray = os.path.join(store_path, ".DS_Store") + with open(stray, "w") as f: + f.write("stray") + items = list(self.identifiable_store) + self.assertEqual(5, len(items)) + os.remove(stray) + def test_reload_discard(self) -> None: # Load example submodel example_submodel = create_example_submodel()