Skip to content

Commit 21989c9

Browse files
committed
Issue #330: Enable deep copy
- properly handle collection features that have None value
1 parent 2c1f21e commit 21989c9

File tree

2 files changed

+55
-3
lines changed

2 files changed

+55
-3
lines changed

cassis/cas.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,13 +1038,21 @@ def _build_fs_list(referenced_list: List[Optional[int]]) -> FeatureStructure:
10381038
if ts.is_primitive(feature.rangeType):
10391039
fs_copy[feature.name] = fs.get(feature.name)
10401040
elif ts.is_primitive_collection(feature.rangeType):
1041+
val = fs.get(feature.name)
1042+
if val is None:
1043+
continue
1044+
10411045
fs_copy[feature.name] = ts.get_type(feature.rangeType.name)()
1042-
fs_copy[feature.name].elements = fs.get(feature.name).elements
1046+
fs_copy[feature.name].elements = val.elements
10431047
elif ts.is_array(feature.rangeType):
1048+
val = fs[feature.name]
1049+
if val is None:
1050+
continue
1051+
10441052
fs_copy[feature.name] = ts.get_type(TYPE_NAME_FS_ARRAY)()
10451053
# collect referenced xmiIDs for mapping later and preserve None placeholders
10461054
referenced_list = []
1047-
for item in fs[feature.name].elements:
1055+
for item in val.elements:
10481056
if item is None:
10491057
referenced_list.append(None)
10501058
elif hasattr(item, "xmiID") and item.xmiID is not None:

tests/test_cas.py

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1018,7 +1018,7 @@ def test_crop_sofa_string_transitive_references_remain(small_typesystem_xml):
10181018
cas = Cas(typesystem=typesystem)
10191019

10201020
# Create parent and child types and a feature on parent referencing child
1021-
typesystem.create_type("test.Child")
1021+
Child = typesystem.create_type("test.Child")
10221022
Parent = typesystem.create_type("test.Parent")
10231023
typesystem.create_feature("test.Parent", "child", "test.Child")
10241024

@@ -1179,6 +1179,50 @@ def test_deep_copy_none_non_primitive_feature():
11791179
assert getattr(copied_parent, "child") is None
11801180

11811181

1182+
def test_deep_copy_none_fsarray_feature():
1183+
"""Ensure an FSArray feature set to None is preserved in the copy."""
1184+
typesystem = TypeSystem()
1185+
Foo = typesystem.create_type("test.Foo")
1186+
typesystem.create_feature(
1187+
Foo,
1188+
"arr",
1189+
rangeType=typesystem.get_type("uima.cas.FSArray"),
1190+
elementType=typesystem.get_type(TYPE_NAME_TOP),
1191+
multipleReferencesAllowed=True,
1192+
)
1193+
1194+
cas = Cas(typesystem=typesystem)
1195+
foo = Foo()
1196+
foo.arr = None
1197+
cas.add(foo)
1198+
1199+
copy = cas.deep_copy(copy_typesystem=False)
1200+
copied_foo = list(copy.select("test.Foo"))[0]
1201+
assert getattr(copied_foo, "arr") is None
1202+
1203+
1204+
def test_deep_copy_none_primitive_collection_feature():
1205+
"""Ensure a primitive collection feature set to None is preserved in the copy."""
1206+
typesystem = TypeSystem()
1207+
Foo = typesystem.create_type("test.Foo")
1208+
typesystem.create_feature(
1209+
Foo,
1210+
"ints",
1211+
rangeType=typesystem.get_type(TYPE_NAME_INTEGER_ARRAY),
1212+
elementType=typesystem.get_type(TYPE_NAME_INTEGER),
1213+
multipleReferencesAllowed=True,
1214+
)
1215+
1216+
cas = Cas(typesystem=typesystem)
1217+
foo = Foo()
1218+
foo.ints = None
1219+
cas.add(foo)
1220+
1221+
copy = cas.deep_copy(copy_typesystem=False)
1222+
copied_foo = list(copy.select("test.Foo"))[0]
1223+
assert getattr(copied_foo, "ints") is None
1224+
1225+
11821226
def test_deep_copy_empty_array():
11831227
"""Ensure empty FSArray is preserved as empty in the copy."""
11841228
typesystem = TypeSystem()

0 commit comments

Comments
 (0)