Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Native python types #8559

Closed
wants to merge 15 commits into from
7 changes: 4 additions & 3 deletions mypy-baseline.txt
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,6 @@ src/inmanta/ast/type.py:0: error: Function is missing a return type annotation
src/inmanta/ast/type.py:0: note: Use "-> None" if function does not return a value
src/inmanta/ast/type.py:0: error: Call to untyped function "__init__" in typed context [no-untyped-call]
src/inmanta/ast/type.py:0: error: Return type "str | None" of "type_string" incompatible with return type "str" in supertype "List" [override]
src/inmanta/ast/type.py:0: error: Function is missing a type annotation for one or more arguments [no-untyped-def]
src/inmanta/ast/type.py:0: error: Function is missing a return type annotation [no-untyped-def]
src/inmanta/ast/type.py:0: error: Function is missing a return type annotation [no-untyped-def]
src/inmanta/ast/type.py:0: error: Function is missing a type annotation [no-untyped-def]
src/inmanta/ast/type.py:0: error: Item "Locatable" of "Locatable | None" has no attribute "name" [union-attr]
Expand Down Expand Up @@ -790,9 +788,12 @@ src/inmanta/protocol/rest/client.py:0: error: Argument "result" to "Result" has
src/inmanta/plugins.py:0: error: Missing type parameters for generic type "ResultVariable" [type-arg]
src/inmanta/plugins.py:0: error: Argument 1 to "add_function" of "PluginMeta" has incompatible type "PluginMeta"; expected "type[Plugin]" [arg-type]
src/inmanta/plugins.py:0: error: "type[Plugin]" has no attribute "__fq_plugin_name__" [attr-defined]
src/inmanta/plugins.py:0: error: Call to untyped function "List" in typed context [no-untyped-call]
src/inmanta/plugins.py:0: error: Non-overlapping identity check (left operand type: "type[object]", right operand type: "<typing special form>") [comparison-overlap]
src/inmanta/plugins.py:0: error: Argument 1 to "to_dsl_type" has incompatible type "Type"; expected "type[object]" [arg-type]
src/inmanta/plugins.py:0: error: Argument 1 to "issubclass" has incompatible type "Any | None"; expected "type" [arg-type]
src/inmanta/plugins.py:0: error: Argument 1 to "issubclass" has incompatible type "Any | None"; expected "type" [arg-type]
src/inmanta/plugins.py:0: error: Incompatible types in assignment (expression has type "tuple[Any, ...]", variable has type "list[type[object]]") [assignment]
src/inmanta/plugins.py:0: error: Call to untyped function "List" in typed context [no-untyped-call]
src/inmanta/plugins.py:0: error: Invalid index type "object" for "dict[str | None, Type]"; expected type "str | None" [index]
src/inmanta/plugins.py:0: error: Argument 1 to "to_dsl_type" has incompatible type "object"; expected "type[object]" [arg-type]
src/inmanta/plugins.py:0: error: Incompatible return value type (got "Type | None", expected "Type") [return-value]
Expand Down
19 changes: 15 additions & 4 deletions src/inmanta/ast/type.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,15 @@ def with_base_type(self, base_type: "Type") -> "Type":
"""
return base_type

def __eq__(self, other):
def __eq__(self, other: object) -> bool:
if type(self) != Type: # noqa: E721
# Not for children
return NotImplemented
return type(self) == type(other) # noqa: E721

def __hash__(self) -> int:
return hash(type(self))


class NamedType(Type, Named):
def get_double_defined_exception(self, other: "NamedType") -> "DuplicateException":
Expand All @@ -111,6 +114,14 @@ def get_double_defined_exception(self, other: "NamedType") -> "DuplicateExceptio
def type_string(self) -> str:
return self.get_full_name()

def __eq__(self, other: object) -> bool:
if not isinstance(other, NamedType):
return False
return self.get_full_name() == other
wouterdb marked this conversation as resolved.
Show resolved Hide resolved

def __hash__(self) -> int:
return hash(self.get_full_name())


@stable_api
class NullableType(Type):
Expand Down Expand Up @@ -412,7 +423,7 @@ def type_string_internal(self) -> str:
def get_location(self) -> None:
return None

def __eq__(self, other):
def __eq__(self, other: object) -> bool:
return type(self) == type(other) # noqa: E721


Expand Down Expand Up @@ -639,7 +650,7 @@ def normalize(self) -> None:
assert self.expression is not None
self.expression.normalize()

def set_constraint(self, expression) -> None:
def set_constraint(self, expression: "ExpressionStatement") -> None:
"""
Set the constraint for this type. This baseclass for constraint
types requires the constraint to be set as a regex that can be
Expand All @@ -648,7 +659,7 @@ def set_constraint(self, expression) -> None:
self.expression = expression
self._constraint = create_function(self, expression)

def get_constraint(self):
def get_constraint(self) -> "ExpressionStatement | None":
"""
Get the string representation of the constraint
"""
Expand Down
8 changes: 6 additions & 2 deletions src/inmanta/plugins.py
sanderr marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -291,13 +291,17 @@ def to_dsl_type(python_type: type[object]) -> inmanta_type.Type:

return inmanta_type.TypedDict(to_dsl_type(args[1]))

# List, set, ...
if issubclass(origin, collections.abc.Collection):
# List
if issubclass(origin, collections.abc.Sequence):
args = typing.get_args(python_type)
if not args:
return inmanta_type.List()
return inmanta_type.TypedList(to_dsl_type(args[0]))

# Set
if issubclass(origin, collections.abc.Set):
raise TypingException(None, f"invalid type {python_type}, set is not supported on the plugin boundary")

# TODO annotated types
# if typing.get_origin(t) is typing.Annotated:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this one should also be easy enough to support for 7.4

# args: Sequence[object] = typing.get_args(python_type)
Expand Down
4 changes: 3 additions & 1 deletion tests/compiler/test_plugin_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ def test_conversion():
assert inmanta_type.NullableType(inmanta_type.Float()) == to_dsl_type(float | None)
assert inmanta_type.List() == to_dsl_type(list)
assert inmanta_type.TypedList(inmanta_type.String()) == to_dsl_type(list[str])
assert inmanta_type.TypedList(inmanta_type.String()) == to_dsl_type(set[str])
assert inmanta_type.TypedList(inmanta_type.String()) == to_dsl_type(Sequence[str])
assert inmanta_type.TypedList(inmanta_type.String()) == to_dsl_type(collections.abc.Sequence[str])
assert inmanta_type.TypedDict(inmanta_type.Type()) == to_dsl_type(dict)
Expand All @@ -46,3 +45,6 @@ def test_conversion():

with pytest.raises(RuntimeException):
to_dsl_type(dict[int, int])

with pytest.raises(RuntimeException):
to_dsl_type(set[str])