diff --git a/conda/dev-environment-unix.yml b/conda/dev-environment-unix.yml index 65d72f4f..fa3740a5 100644 --- a/conda/dev-environment-unix.yml +++ b/conda/dev-environment-unix.yml @@ -11,6 +11,7 @@ dependencies: - codespell>=2.2.6,<2.3 - compilers - cyrus-sasl + - deprecated - exprtk - flex - graphviz diff --git a/conda/dev-environment-win.yml b/conda/dev-environment-win.yml index 5610ce3f..8ca2482d 100644 --- a/conda/dev-environment-win.yml +++ b/conda/dev-environment-win.yml @@ -10,6 +10,7 @@ dependencies: - codespell>=2.2.6,<2.3 - compilers - cyrus-sasl + - deprecated - exprtk - graphviz - gtest diff --git a/csp/adapters/db.py b/csp/adapters/db.py index 8316c1a6..d4529bc2 100644 --- a/csp/adapters/db.py +++ b/csp/adapters/db.py @@ -267,9 +267,9 @@ def schema_struct(self): table = db.Table(self._table_name, db_metadata, autoload_with=self._connection) struct_metadata = {col: col_obj.type.python_type for col, col_obj in table.columns.items()} - from csp.impl.struct import defineStruct + from csp.impl.struct import define_struct - typ = defineStruct(name, struct_metadata) + typ = define_struct(name, struct_metadata) globals()[name] = typ return globals()[name] diff --git a/csp/build/csp_autogen.py b/csp/build/csp_autogen.py index 4c050d52..4e121da5 100644 --- a/csp/build/csp_autogen.py +++ b/csp/build/csp_autogen.py @@ -498,7 +498,7 @@ class Derived(Test): flt: float -# Test2 = csp.impl.struct.defineStruct( 'Test2', { 'A' + str(i) : bool for i in range(25 )}) +# Test2 = csp.impl.struct.define_struct( 'Test2', { 'A' + str(i) : bool for i in range(25 )}) if __name__ == "__main__": parser = argparse.ArgumentParser() diff --git a/csp/impl/pandas_accessor.py b/csp/impl/pandas_accessor.py index ec029913..13445c4b 100644 --- a/csp/impl/pandas_accessor.py +++ b/csp/impl/pandas_accessor.py @@ -8,7 +8,7 @@ import csp from csp import ts from csp.impl.pandas_ext_type import TsDtype, is_csp_type -from csp.impl.struct import defineNestedStruct +from csp.impl.struct import define_nested_struct from csp.impl.wiring.edge import Edge T = TypeVar("T") @@ -615,7 +615,7 @@ def collect(self, columns=None, struct_type=None, delim=" "): datatree[parts[-1]] = self._obj[col] if not struct_type: - struct_type = defineNestedStruct("_C", metadata, defaults) + struct_type = define_nested_struct("_C", metadata, defaults) if not data: return csp.null_ts(struct_type) diff --git a/csp/impl/struct.py b/csp/impl/struct.py index 88910edf..502df68f 100644 --- a/csp/impl/struct.py +++ b/csp/impl/struct.py @@ -2,6 +2,7 @@ import ruamel.yaml import typing from copy import deepcopy +from deprecated import deprecated import csp from csp.impl.__csptypesimpl import _csptypesimpl @@ -226,7 +227,7 @@ def __dir__(self): return self.__full_metadata_typed__.keys() -def defineStruct(name, metadata: dict, defaults: dict = {}, base=Struct): +def define_struct(name, metadata: dict, defaults: dict = {}, base=Struct): """Helper method to dynamically create struct types""" dct = deepcopy(defaults) @@ -235,13 +236,13 @@ def defineStruct(name, metadata: dict, defaults: dict = {}, base=Struct): return clazz -def defineNestedStruct(name, metadata: dict, defaults: dict = {}, base=Struct): +def define_nested_struct(name, metadata: dict, defaults: dict = {}, base=Struct): """Helper method to dynamically create nested struct types. metadata and defaults can be a nested dictionaries""" metadata = deepcopy(metadata) defaults = deepcopy(defaults) child_structs = { - field: defineNestedStruct(f"{name}_{field}", submeta, defaults.get(field, {})) + field: define_nested_struct(f"{name}_{field}", submeta, defaults.get(field, {})) for field, submeta in metadata.items() if isinstance(submeta, dict) } @@ -249,4 +250,14 @@ def defineNestedStruct(name, metadata: dict, defaults: dict = {}, base=Struct): if fld in defaults: defaults[fld] = struct() metadata.update(child_structs) - return defineStruct(name, metadata, defaults, base) + return define_struct(name, metadata, defaults, base) + + +@deprecated(version="0.0.6", reason="Replaced by define_struct") +def defineStruct(name, metadata: dict, defaults: dict = {}, base=Struct): + return define_struct(name, metadata, defaults, base) + + +@deprecated(version="0.0.6", reason="Replaced by define_nested_struct") +def defineNestedStruct(name, metadata: dict, defaults: dict = {}, base=Struct): + return define_nested_struct(name, metadata, defaults, base) diff --git a/csp/tests/impl/test_struct.py b/csp/tests/impl/test_struct.py index f70ee290..4a5a6681 100644 --- a/csp/tests/impl/test_struct.py +++ b/csp/tests/impl/test_struct.py @@ -7,7 +7,7 @@ from datetime import date, datetime, time, timedelta import csp -from csp.impl.struct import defineStruct +from csp.impl.struct import define_nested_struct, define_struct, defineNestedStruct, defineStruct from csp.impl.types.typing_utils import FastList @@ -761,9 +761,7 @@ def test_update(self): self.assertEqual(dest, DerivedPartialNative(l=[2, 3, 4], f=3.14, b=False, i=5, s="bar")) def test_multibyte_mask(self): - from csp.impl.struct import defineStruct - - BigStruct = defineStruct("BigStruct", {k: float for k in "abcdefghijklmnopqrdtuvwxyz"}) + BigStruct = define_struct("BigStruct", {k: float for k in "abcdefghijklmnopqrdtuvwxyz"}) s = BigStruct() for key in BigStruct.metadata().keys(): @@ -1062,9 +1060,18 @@ def graph2(): for _ in range(100): csp.run(graph2, starttime=datetime(2020, 1, 1), endtime=timedelta(seconds=1000)) - def test_defineNestedStruct(self): - from csp.impl.struct import defineNestedStruct + def test_deprecated_defineStruct(self): + metadata = { + "a": float, + "b": int, + } + defaults = {"a": 0.0, "b": 1} + TestStruct = define_struct("TestStruct", metadata, defaults) + TestStruct2 = defineStruct("TestStruct", metadata, defaults) + self.assertEqual(TestStruct.metadata(), TestStruct2.metadata()) + self.assertEqual(TestStruct.__defaults__, TestStruct2.__defaults__) + def test_define_nested_struct(self): metadata = { "a": float, "b": int, @@ -1084,7 +1091,7 @@ def test_defineNestedStruct(self): }, "d": {"s": object, "t": [object, True]}, } - TestStruct = defineNestedStruct("TestStruct", metadata) + TestStruct = define_nested_struct("TestStruct", metadata) self.assertEqual(TestStruct.__name__, "TestStruct") self.assertEqual(list(TestStruct.metadata().keys()), list(normalized_metadata.keys())) self.assertEqual(TestStruct.metadata()["a"], normalized_metadata["a"]) @@ -1099,20 +1106,26 @@ def test_defineNestedStruct(self): self.assertEqual(d.metadata(), normalized_metadata["d"]) defaults = {"a": 0.0, "c": {"y": []}, "d": {}} - TestStruct2 = defineNestedStruct("TestStruct2", metadata, defaults) + TestStruct2 = define_nested_struct("TestStruct2", metadata, defaults) s = TestStruct2() self.assertEqual(s.a, 0.0) self.assertEqual(s.c, s.metadata()["c"]()) self.assertEqual(s.c.y, []) self.assertEqual(s.d, s.metadata()["d"]()) - def test_all_fields_set(self): - from csp.impl.struct import defineStruct + # Make sure deprecated function still works without raising + TestStruct3 = defineNestedStruct("TestStruct3", metadata, defaults) + s = TestStruct3() + self.assertEqual(s.a, 0.0) + self.assertEqual(s.c, s.metadata()["c"]()) + self.assertEqual(s.c.y, []) + self.assertEqual(s.d, s.metadata()["d"]()) + def test_all_fields_set(self): types = [int, bool, list, str] for num_fields in range(1, 25): meta = {chr(ord("a") + x): types[x % len(types)] for x in range(num_fields)} - stype = defineStruct("foo", meta) + stype = define_struct("foo", meta) s = stype() self.assertFalse(s.all_fields_set()) keys = list(meta.keys()) @@ -1125,7 +1138,7 @@ def test_all_fields_set(self): # Test derived structs meta2 = {k + "2": t for k, t in meta.items()} - stype2 = defineStruct("foo", meta2, base=stype) + stype2 = define_struct("foo", meta2, base=stype) s2 = stype2() self.assertFalse(s2.all_fields_set()) keys = list(stype2.metadata().keys()) @@ -1160,12 +1173,10 @@ def test_struct_pickle(self): self.assertNotEqual(id(foo), id(foo_unpickled)) def test_struct_type_alloc(self): - from csp.impl.struct import defineStruct - for i in range(1000): name = f"struct_{i}" fieldname = f"field{i}" - S = defineStruct(name, {fieldname: int}) + S = define_struct(name, {fieldname: int}) s = S() setattr(s, fieldname, i) ts = getattr(csp.const(s), fieldname) @@ -1352,7 +1363,7 @@ class Outer(csp.Struct): all = [] for i in range(10000): - sType = defineStruct("foo", {"a": dict}) + sType = define_struct("foo", {"a": dict}) all.append(Outer(s=sType(a={"foo": "bar"}))) repr(all) all = all[:100] diff --git a/csp/tests/test_baselib.py b/csp/tests/test_baselib.py index 5a624cbc..20e858fb 100644 --- a/csp/tests/test_baselib.py +++ b/csp/tests/test_baselib.py @@ -10,7 +10,7 @@ import csp from csp import ts from csp.baselib import _convert_ts_object_for_print -from csp.impl.struct import defineStruct +from csp.impl.struct import define_struct class TestBaselib(unittest.TestCase): @@ -1074,7 +1074,7 @@ def graph(): # test log dominated graph (proper thread waiting/joining) fields = 1000 - LargeStruct = defineStruct("LargeStruct", {f"{i}": int for i in range(fields)}) # struct with 1000 int fields + LargeStruct = define_struct("LargeStruct", {f"{i}": int for i in range(fields)}) # struct with 1000 int fields structs = [] for i in range(60): struct = LargeStruct() diff --git a/pyproject.toml b/pyproject.toml index 48d48d1e..511405e8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,7 @@ [build-system] requires = [ "cmake", + "deprecated", # Because used in csp.impl.struct, which is used in autogen "oldest-supported-numpy", "pyarrow>=7.0.0", "ruamel.yaml", @@ -19,6 +20,7 @@ requires-python = ">=3.8" dependencies = [ "backports.zoneinfo; python_version<'3.9'", + "deprecated", "numpy<2", "packaging", "pandas",