Skip to content

Commit

Permalink
push current code
Browse files Browse the repository at this point in the history
  • Loading branch information
BrentBlanckaert committed Nov 29, 2024
1 parent 2077865 commit 1585f25
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 74 deletions.
6 changes: 3 additions & 3 deletions tested/dsl/ast_translator.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
)
from tested.parsing import get_converter
from tested.serialisation import (
Assignment,
AbstractAssignment,
Expression,
FunctionCall,
FunctionType,
Expand Down Expand Up @@ -95,7 +95,7 @@ def _is_type_cast(node: ast.expr) -> bool:
return any(node.func.id in x.__members__.values() for x in get_args(AllTypes))


def _convert_ann_assignment(node: ast.AnnAssign) -> Assignment:
def _convert_ann_assignment(node: ast.AnnAssign) -> AbstractAssignment:
if not isinstance(node.target, ast.Name):
actual = ast.dump(node)
raise InvalidDslError(
Expand Down Expand Up @@ -127,7 +127,7 @@ def _convert_ann_assignment(node: ast.AnnAssign) -> Assignment:
)


def _convert_assignment(node: ast.Assign) -> Assignment:
def _convert_assignment(node: ast.Assign) -> AbstractAssignment:
if n := len(node.targets) != 1:
raise InvalidDslError(
f"You must assign to exactly one variable, but got {n} variables."
Expand Down
2 changes: 1 addition & 1 deletion tested/languages/kotlin/generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
)
from tested.languages.utils import convert_unknown_type
from tested.serialisation import (
Assignment,
AbstractAssignment,
Expression,
FunctionCall,
FunctionType,
Expand Down
6 changes: 3 additions & 3 deletions tested/languages/preparation.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
submission_name,
)
from tested.serialisation import (
Assignment,
AbstractAssignment,
Expression,
FunctionCall,
FunctionType,
Expand Down Expand Up @@ -201,7 +201,7 @@ def prepare_argument(
return prepare_expression(bundle, argument)


def prepare_assignment(bundle: Bundle, assignment: Assignment) -> Assignment:
def prepare_assignment(bundle: Bundle, assignment: AbstractAssignment) -> AbstractAssignment:
if isinstance(assignment, VariableAssignment):
if isinstance(assignment.type, VariableType):
class_type = conventionalize_class(bundle.language, assignment.type.data)
Expand Down Expand Up @@ -409,7 +409,7 @@ def prepare_testcase(
names.append(evaluator_name)
if result_channel == IgnoredChannel.IGNORED:
value_function_call = None
elif isinstance(testcase.input, Assignment):
elif isinstance(testcase.input, AbstractAssignment):
command = prepare_assignment(bundle, testcase.input)
assert (
result_channel == IgnoredChannel.IGNORED
Expand Down
2 changes: 1 addition & 1 deletion tested/languages/python/generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
)
from tested.languages.utils import convert_unknown_type
from tested.serialisation import (
Assignment,
AbstractAssignment,
Expression,
FunctionCall,
FunctionType,
Expand Down
111 changes: 49 additions & 62 deletions tested/serialisation.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,50 +153,38 @@ class SpecialNumbers(StrEnum):
NEG_INFINITY = "-inf"


@define
class Statement(WithFeatures, WithFunctions):
"""
Base class for representing Statements which represent Expressions and Assignments
"""
def accept(self, visitor: "ConvertStatementVisitor") -> None:
visitor.visit(self)


@define
class Expression(Statement):
# class Statement(WithFeatures, WithFunctions):
# """
# Base class for representing Statements which represent Expressions and Assignments
# """
#
# def accept(self, visitor: "ConvertStatementVisitor") -> None:
# visitor.visit(self)

Check notice

Code scanning / CodeQL

Commented-out code Note test

This comment appears to contain commented-out code.
#

class Expression(WithFeatures, WithFunctions):
"""
Base class for representing Expressions which represent Values, Identifiers
and FunctionCalls.
"""
pass

@define
class Value(Expression):
"""
Base class for representing values with associated type, data, and diagnostics.
Intended for use by subclasses.
"""
type: any = field(default=None,
metadata={"description": "The type of the value"})
data: any = field(default=None, metadata={
"description": "The actual data stored in the value"
})
diagnostics: any = field(default=None, metadata={
"description": "Diagnostics or metadata for the value"
})

type: Any
data: Any
diagnostic: Any

# These visitors are defined for the generation files of each language.
@define
class ConvertStatementVisitor:

@abstractmethod
def visit(self, statement: Statement) -> str:
raise AssertionError(f"Unknown statement: {statement!r}")
#
#
# # These visitors are defined for the generation files of each language.
# @define
# class ConvertStatementVisitor:
#
# @abstractmethod
# def visit(self, statement: Statement) -> str:
# raise AssertionError(f"Unknown statement: {statement!r}")


@define
class NumberType(Value):
class NumberType(Expression):
type: NumericTypes = field(validator=validators.instance_of(NumericTypes))
data: SpecialNumbers | int | float | Decimal = field(
validator=validators.instance_of(Union[SpecialNumbers, int, float, Decimal])
Expand All @@ -205,15 +193,15 @@ class NumberType(Value):

def __attrs_post_init__(self):
if (
isinstance(self.data, SpecialNumbers)
and resolve_to_basic(self.type) == BasicNumericTypes.INTEGER
isinstance(self.data, SpecialNumbers)
and resolve_to_basic(self.type) == BasicNumericTypes.INTEGER
):
raise ValueError(
f"SpecialNumber '{self.data}' is only supported for " f"real numbers."
)

if resolve_to_basic(self.type) == BasicNumericTypes.INTEGER and isinstance(
self.data, Decimal
self.data, Decimal
):
self.data = self.data.to_integral_value()

Expand All @@ -225,7 +213,7 @@ def get_functions(self) -> Iterable["FunctionCall"]:


@define
class StringType(Value):
class StringType(Expression):
type: StringTypes = field(validator=validators.instance_of(StringTypes))
data: str = field(validator=validators.instance_of(str))

Expand All @@ -243,7 +231,7 @@ def get_functions(self) -> Iterable["FunctionCall"]:


@define
class BooleanType(Value):
class BooleanType(Expression):
type: BooleanTypes = field(validator=validators.instance_of(BooleanTypes))
data: bool = field(validator=validators.instance_of(bool))
diagnostic: Literal[None] = None # Unused in this type.
Expand All @@ -256,7 +244,7 @@ def get_functions(self) -> Iterable["FunctionCall"]:


@define
class SequenceType(Value):
class SequenceType(Expression):
type: SequenceTypes = field(validator=validators.instance_of(SequenceTypes))
data: list["Expression"]
diagnostic: Literal[None] = None # Unused in this type.
Expand Down Expand Up @@ -319,7 +307,7 @@ def get_functions(self) -> Iterable["FunctionCall"]:


@define
class ObjectType(Value):
class ObjectType(Expression):
type: ObjectTypes = field(validator=validators.instance_of(ObjectTypes))
data: list[ObjectKeyValuePair]
diagnostic: Literal[None] = None # Unused in this type.
Expand Down Expand Up @@ -355,7 +343,7 @@ def get_functions(self) -> Iterable["FunctionCall"]:


@define
class NothingType(Value):
class NothingType(Expression):
type: NothingTypes = field(
default=BasicNothingTypes.NOTHING,
validator=validators.instance_of(NothingTypes), # type: ignore
Expand All @@ -371,9 +359,9 @@ def get_functions(self) -> Iterable["FunctionCall"]:


# A value is one of the preceding types.
# Value = Union[
# NumberType, StringType, BooleanType, SequenceType, ObjectType, NothingType
# ]
Value = Union[
NumberType, StringType, BooleanType, SequenceType, ObjectType, NothingType
]


class Identifier(str, Expression):
Expand Down Expand Up @@ -456,8 +444,8 @@ def get_used_features(self) -> FeatureSet:

# Get OOP features.
if self.type in (
FunctionType.PROPERTY,
FunctionType.CONSTRUCTOR,
FunctionType.PROPERTY,
FunctionType.CONSTRUCTOR,
) or not isinstance(self.namespace, (Identifier, NoneType)):
constructs.add(Construct.OBJECTS)

Expand Down Expand Up @@ -490,11 +478,11 @@ class VariableType:
type: Literal["custom"] = "custom"


# Expression = Identifier | Value | FunctionCall
Expression = Identifier | Value | FunctionCall


@define
class Assignment(Statement):
class AbstractAssignment(WithFeatures, WithFunctions):
"""
Assign the result of an expression to a variable or property.
Expand All @@ -521,9 +509,8 @@ def replace_expression(self, expression: Expression) -> Self:
raise NotImplementedError()



@define
class VariableAssignment(Assignment):
class VariableAssignment(AbstractAssignment):
"""
Assign the result of an expression to a variable.
Expand Down Expand Up @@ -555,7 +542,7 @@ def replace_expression(self, expression: Expression) -> "VariableAssignment":


@define
class PropertyAssignment(Assignment):
class PropertyAssignment(AbstractAssignment):
"""
Assign the result of an expression to a property.
"""
Expand Down Expand Up @@ -583,10 +570,10 @@ def replace_property(self, prop: FunctionCall) -> "PropertyAssignment":
return PropertyAssignment(property=prop, expression=self.expression)


#Assignment = VariableAssignment | PropertyAssignment
Assignment = VariableAssignment | PropertyAssignment

# If changing this, also update is_statement_strict in the utils.
# Statements = Assignment | Expression
Statement = Assignment | Expression


# Update the forward references, which fixes the schema generation.
Expand Down Expand Up @@ -642,8 +629,8 @@ def _convert_to_python(value: Value | None, for_printing=False) -> Any:
if isinstance(value.type, SimpleTypes):
# If we have floats or ints, convert them to Python.
if value.type in (
AdvancedNumericTypes.SINGLE_PRECISION,
AdvancedNumericTypes.DOUBLE_PRECISION,
AdvancedNumericTypes.SINGLE_PRECISION,
AdvancedNumericTypes.DOUBLE_PRECISION,
):
return float(str(value.data))
if value.type != AdvancedNumericTypes.FIXED_PRECISION:
Expand Down Expand Up @@ -785,11 +772,11 @@ def to_python_comparable(value: Value | None) -> Any:
assert isinstance(value, NumberType)
return value.data
if basic_type in (
BasicBooleanTypes.BOOLEAN,
BasicStringTypes.TEXT,
BasicNothingTypes.NOTHING,
BasicStringTypes.ANY,
BasicStringTypes.UNKNOWN,
BasicBooleanTypes.BOOLEAN,
BasicStringTypes.TEXT,
BasicNothingTypes.NOTHING,
BasicStringTypes.ANY,
BasicStringTypes.UNKNOWN,
):
return value.data

Expand Down
8 changes: 4 additions & 4 deletions tested/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from typing import get_args as typing_get_args

if TYPE_CHECKING:
from tested.serialisation import Assignment
from tested.serialisation import AbstractAssignment

Check failure

Code scanning / CodeQL

Module-level cyclic import Error test

'AbstractAssignment' may not be defined if module
tested.serialisation
is imported before module
tested.utils
, as the
definition
of AbstractAssignment occurs after the cyclic
import
of tested.utils.
'AbstractAssignment' may not be defined if module
tested.serialisation
is imported before module
tested.utils
, as the
definition
of AbstractAssignment occurs after the cyclic
import
of tested.utils.

Check warning on line 14 in tested/utils.py

View check run for this annotation

Codecov / codecov/patch

tested/utils.py#L14

Added line #L14 was not covered by tests

_logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -316,14 +316,14 @@ def timsort(list_t: list[T], timgroup: int = 32) -> list[T]:
return no_dup


def is_statement_strict(statement: Any) -> TypeGuard["Assignment"]:
def is_statement_strict(statement: Any) -> TypeGuard["AbstractAssignment"]:
"""
Check that the given value is a strict statement: it must be a statement but
not an expression.
:param statement: The potential statement to check.
:return: True if it is, False otherwise.
"""
from tested.serialisation import Assignment
from tested.serialisation import AbstractAssignment

return isinstance(statement, Assignment)
return isinstance(statement, AbstractAssignment)

0 comments on commit 1585f25

Please sign in to comment.