microsoft / yardl

Tooling for streaming instrument data
https://microsoft.github.io/yardl/
MIT License
29 stars 5 forks source link

Python TypeError instantiating record that contains aliased generic field #82

Closed naegelejd closed 8 months ago

naegelejd commented 8 months ago

Using yardl commit ab1e2b with the following model:

GenericRecord<T>: !record
  fields:
    v: T

AliasedRecord<T>: GenericRecord<T>

MyRecord: !record
  fields:
    myField: AliasedRecord<int>

To reproduce, generate Python for this model, then import the generated Python module and create an instance of MyRecord with no arguments. Python will complain that MyRecord.__init__() is missing the keyword argument for my_field:

Python 3.11.3 | packaged by conda-forge | (main, Apr  6 2023, 08:57:19) [GCC 11.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import issue_082
>>> r = issue_082.MyRecord()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: MyRecord.__init__() missing 1 required keyword-only argument: 'my_field'

The generated code for MyRecord looks like this:

class MyRecord:
    my_field: AliasedRecord[yardl.Int32]

    def __init__(self, *,
        my_field: AliasedRecord[yardl.Int32],
    ):
        self.my_field = my_field

If I remove the AliasedRecord from the model and use GenericRecord directly, I get the expected class definition for MyRecord, and it works:

class MyRecord:
    my_field: GenericRecord[yardl.Int32]

    def __init__(self, *,
        my_field: typing.Optional[GenericRecord[yardl.Int32]] = None,
    ):
        self.my_field = my_field if my_field is not None else GenericRecord(v=0)

The relevant code is https://github.com/microsoft/yardl/blob/ae9b826d94a88c3640002839e9ded57ce3ab1e2b/tooling/internal/python/types/types.go#L179-L195