SRserves85 / avro-to-python

Light tool for compiling avro schema files (.avsc) to python classes
MIT License
25 stars 19 forks source link

Circular references and class names clashes #37

Closed fmiguelez closed 3 months ago

fmiguelez commented 4 months ago

Definitions with circular references are not supported. The same for class name clashes (same class name in different namespace).

Consider following test definition.

{
    "type": "record",
    "name": "RecordWithCircularReference",
    "namespace": "records",
    "fields": [
        {
            "name": "tree",
            "type": {
                "type": "record",
                "name": "Node",
                "fields": [
                    {
                        "name": "id",
                        "type": "string"
                    },
                    {
                        "name": "parent",
                        "type": [
                            "null",
                            "Node"
                        ],
                        "default": null
                    },
                    {
                        "name": "children",
                        "type": [
                            "null",
                            {
                                "type": "array",
                                "items": "Node"
                            }
                        ],
                        "default": null
                    }
                ]
            }
        },
        {
            "name": "altTree",
            "type": {
                "type": "record",
                "name": "Node",
                "namespace": "records.nested",
                "fields": [
                    {
                        "name": "name",
                        "type": "string"
                    }
                ]
            }
        }
    ]
}

Notice the two Node definitions and the circular references inside first Node.

Consider also following test in test_compiled_files.py that should succeed:

    def test_record_with_circular_reference(self):
        """ tests records with circular references """

        from records import RecordWithCircularReference
        from records import Node
        import records.nested.Node

        data1 = {'tree': {'id': '0',
                          'children': [Node({'id': '00', 'parent': Node({'id': '0'})}),
                                       {'id': '01', 'parent': {'id': '0'},
                                        'children': [{'id': '010', 'parent': Node({'id': '01'})},
                                                     {'id': '011',
                                                      'parent': Node({'id': '01'})}]}]},
                 'altTree': records.nested.Node({'name': 'x'})}
        data2 = ('{"tree": {"id": "0", "children": [{"id": "00", "parent": {"id": "0"}}, '
                 '{"id": "01", "parent": {"id": "0"}, "children": [{"id": "010", "parent": {"id": "01"}}, '
                 '{"id": "011", "parent": {"id": "01"}}]}]}, "altTree": {"name": "x"}}')

        record1 = RecordWithCircularReference(data1)
        record2 = RecordWithCircularReference(data2)

        self.assertEqual(
            record1.serialize(),
            record2.serialize(),
            'records with circular references should be equal'
        )

If such test is executed it fails with following error:

tests\writer\test_compiled_files.py:128 (PathTests.test_record_with_circular_reference)
self = <test_compiled_files.PathTests testMethod=test_record_with_circular_reference>

    def test_record_with_circular_reference(self):
        """ tests records with circular references """

>       from records import RecordWithCircularReference

test_compiled_files.py:132: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
O:\ws\mdp\avro-to-python\tests\avsc\records\records\__init__.py:8: in <module>
    ???
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

>   ???
E   ImportError: cannot import name 'Node' from partially initialized module 'records.Node' (most likely due to a circular import) (O:\ws\mdp\avro-to-python\tests\avsc\records\records\Node.py)

O:\ws\mdp\avro-to-python\tests\avsc\records\records\Node.py:8: ImportError