Skip to content

Commit

Permalink
Merge pull request #327 from Point72/pit/define_struct
Browse files Browse the repository at this point in the history
Deprecate defineStruct and defineNestedStruct in favor of define_struct and define_nested_struct
  • Loading branch information
timkpaine authored Jul 13, 2024
2 parents c6fd90e + 71fbf26 commit 323122e
Show file tree
Hide file tree
Showing 9 changed files with 53 additions and 27 deletions.
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

0 comments on commit 323122e

Please sign in to comment.