Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions conda/dev-environment-unix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ dependencies:
- codespell>=2.2.6,<2.3
- compilers
- cyrus-sasl
- deprecated
- exprtk
- flex
- graphviz
Expand Down
1 change: 1 addition & 0 deletions conda/dev-environment-win.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ dependencies:
- codespell>=2.2.6,<2.3
- compilers
- cyrus-sasl
- deprecated
- exprtk
- graphviz
- gtest
Expand Down
4 changes: 2 additions & 2 deletions csp/adapters/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]

Expand Down
2 changes: 1 addition & 1 deletion csp/build/csp_autogen.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
4 changes: 2 additions & 2 deletions csp/impl/pandas_accessor.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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)
Expand Down
19 changes: 15 additions & 4 deletions csp/impl/struct.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -235,18 +236,28 @@ 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)
}
for fld, struct in child_structs.items():
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)
43 changes: 27 additions & 16 deletions csp/tests/impl/test_struct.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down Expand Up @@ -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():
Expand Down Expand Up @@ -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,
Expand All @@ -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"])
Expand All @@ -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())
Expand All @@ -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())
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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]
Expand Down
4 changes: 2 additions & 2 deletions csp/tests/test_baselib.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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()
Expand Down
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -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",
Expand All @@ -19,6 +20,7 @@ requires-python = ">=3.8"

dependencies = [
"backports.zoneinfo; python_version<'3.9'",
"deprecated",
"numpy<2",
"packaging",
"pandas",
Expand Down