Skip to content

Commit fdccfb6

Browse files
authored
Merge branch 'main' into tkp/ruffclean
2 parents 3fe608f + 40c0f4d commit fdccfb6

File tree

8 files changed

+57
-10
lines changed

8 files changed

+57
-10
lines changed

CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# Project Configuration #
33
#########################
44
cmake_minimum_required(VERSION 3.20.0)
5-
project(csp VERSION "0.0.10")
5+
project(csp VERSION "0.0.11")
66
set(CMAKE_CXX_STANDARD 20)
77

88
###################################################################################################################################################

csp/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131

3232
from . import stats
3333

34-
__version__ = "0.0.10"
34+
__version__ = "0.0.11"
3535

3636

3737
def get_include_path():

csp/impl/types/pydantic_types.py

+16
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,14 @@ class CspTypeVarType(Generic[_T]):
3636
@classmethod
3737
def __get_pydantic_core_schema__(cls, source_type: Any, handler: GetCoreSchemaHandler) -> CoreSchema:
3838
typ = _check_source_type(cls, source_type)
39+
if not typ or not typ[0].isalpha():
40+
if typ and typ[0] == "~":
41+
raise SyntaxError(
42+
f"Invalid generic type: {typ}. The generic type annotation (i.e. `~T`) is only allowed at the top level (i.e. `value: '~T'`)."
43+
)
44+
raise SyntaxError(
45+
f"Invalid generic type: {typ}. Generic types in csp must start with an alphabetic character."
46+
)
3947

4048
def _validator(v: Any, info: ValidationInfo) -> Any:
4149
# info.context should be an instance of TVarValidationContext, but we don't check for performance
@@ -56,6 +64,14 @@ class CspTypeVar(Generic[_T]):
5664
@classmethod
5765
def __get_pydantic_core_schema__(cls, source_type: Any, handler: GetCoreSchemaHandler) -> CoreSchema:
5866
tvar = _check_source_type(cls, source_type)
67+
if not tvar or not tvar[0].isalpha():
68+
if tvar and tvar[0] == "~":
69+
raise SyntaxError(
70+
f"Invalid generic type: {tvar}. The generic type annotation (i.e. `~T`) is only allowed at the top level (i.e. `value: '~T'`)."
71+
)
72+
raise SyntaxError(
73+
f"Invalid generic type: {tvar}. Generic types in csp must start with an alphabetic character. "
74+
)
5975

6076
def _validator(v: Any, info: ValidationInfo) -> Any:
6177
# info.context should be an instance of TVarValidationContext, but we don't check for performance

csp/impl/types/typing_utils.py

+11-4
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,9 @@ class TsTypeValidator:
100100
For example, this is to make sure that:
101101
ts[List] can validate as ts[List[float]]
102102
ts[Dict[str, List[str]] won't validate as ts[Dict[str, List[float]]
103-
ts["T"], ts[TypeVar("T")], ts[List["T"]], etc are allowed
104-
ts[Optional[float]], ts[Union[float, int]], ts[Annotated[float, None]], etc are not allowed
105-
etc
103+
Notes:
104+
ts["T"], ts[TypeVar("T")], ts[List["T"]], ts[Optional[float]], ts[Union[float, int]], ts[Any] are allowed
105+
ts[Annotated[float, None]], are not allowed
106106
For validation of csp baskets, this piece becomes the bottleneck
107107
"""
108108

@@ -126,7 +126,7 @@ def __init__(self, source_type: type):
126126
self._source_is_union = CspTypingUtils.is_union_type(source_type)
127127
self._source_args = typing.get_args(source_type)
128128
self._source_adapter = None
129-
if type(source_type) in (typing.ForwardRef, typing.TypeVar):
129+
if type(source_type) in (typing.ForwardRef, typing.TypeVar) or source_type is typing.Any:
130130
pass # Will handle these separately as part of type checking
131131
elif self._source_origin is None and isinstance(self._source_type, type):
132132
# self._source_adapter = TypeAdapter(typing.Type[source_type])
@@ -163,12 +163,19 @@ def validate(self, value_type, info=None):
163163
self._last_value_type = value_type
164164
self._last_context = info.context if info is not None else None
165165

166+
if value_type is typing.Any:
167+
# https://docs.python.org/3/library/typing.html#the-any-type
168+
# "Notice that no type checking is performed when assigning a value of type Any to a more precise type."
169+
return value_type
170+
166171
# Fast path because while we could use the source adapter in the next block to validate,
167172
# it's about 10x faster to do a simple validation with issubclass, and this adds up on baskets
168173
if self._source_origin is None:
169174
# Want to allow int to be passed for float (i.e. in resolution of TVars)
170175
if self._source_type is float and value_type is int:
171176
return self._source_type
177+
if self._source_type is typing.Any:
178+
return value_type
172179
try:
173180
if issubclass(value_type, self._source_type):
174181
return value_type

csp/tests/impl/types/test_pydantic_type_resolver.py

+12
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,12 @@ def test_forced_tvar(self):
9292
context.resolve_tvars()
9393
self.assertDictEqual(context.tvars, {"T": float})
9494

95+
def test_bad_variable_name(self):
96+
self.assertRaises(SyntaxError, lambda: CspTypeVar[""])
97+
self.assertRaises(SyntaxError, TypeAdapter, CspTypeVar["~T"])
98+
self.assertRaises(SyntaxError, TypeAdapter, CspTypeVar["1"])
99+
_ = TypeAdapter(CspTypeVar["T1"])
100+
95101

96102
class TestPydanticTypeResolver_CspTypeVarType(TestCase):
97103
def test_one_value(self):
@@ -183,6 +189,12 @@ def test_TsType_nested(self):
183189
context.resolve_tvars()
184190
self.assertDictEqual(context.tvars, {"T": float})
185191

192+
def test_bad_variable_name(self):
193+
self.assertRaises(SyntaxError, lambda: CspTypeVarType[""])
194+
self.assertRaises(SyntaxError, TypeAdapter, CspTypeVarType["~T"])
195+
self.assertRaises(SyntaxError, TypeAdapter, CspTypeVarType["1"])
196+
_ = TypeAdapter(CspTypeVarType["T1"])
197+
186198

187199
T = TypeVar("T")
188200

csp/tests/impl/types/test_tstype.py

+13-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import sys
2-
from typing import Dict, ForwardRef, Generic, List, Mapping, TypeVar, Union, get_args, get_origin
2+
from typing import Any, Dict, ForwardRef, Generic, List, Mapping, TypeVar, Union, get_args, get_origin
33
from unittest import TestCase
44

55
import numpy as np
@@ -106,6 +106,18 @@ def test_allow_null(self):
106106
ta.validate_python(csp.null_ts(float), context=context)
107107
ta.validate_python(None, context=context)
108108

109+
def test_any(self):
110+
ta = TypeAdapter(TsType[Any])
111+
ta.validate_python(csp.null_ts(float))
112+
ta.validate_python(csp.null_ts(object))
113+
ta.validate_python(csp.null_ts(List[str]))
114+
ta.validate_python(csp.null_ts(Dict[str, List[float]]))
115+
116+
# https://docs.python.org/3/library/typing.html#the-any-type
117+
# "Notice that no type checking is performed when assigning a value of type Any to a more precise type."
118+
ta = TypeAdapter(TsType[float])
119+
ta.validate_python(csp.null_ts(Any))
120+
109121

110122
class TestOutputValidation(TestCase):
111123
def test_validation(self):

pyproject.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ name = "csp"
1616
authors = [{name = "the csp authors", email = "[email protected]"}]
1717
description="csp is a high performance reactive stream processing library, written in C++ and Python"
1818
readme = "README.md"
19-
version = "0.0.10"
19+
version = "0.0.11"
2020
requires-python = ">=3.9"
2121

2222
dependencies = [
@@ -116,7 +116,7 @@ slack = [
116116
]
117117

118118
[tool.bumpversion]
119-
current_version = "0.0.10"
119+
current_version = "0.0.11"
120120
commit = false
121121
tag = false
122122
commit_args = "-s"

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@
122122

123123
setup(
124124
name="csp",
125-
version="0.0.10",
125+
version="0.0.11",
126126
packages=["csp"],
127127
cmake_install_dir="csp",
128128
cmake_args=cmake_args,

0 commit comments

Comments
 (0)