[ https://issues.apache.org/jira/browse/THRIFT-2642?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15856364#comment-15856364 ]
Lars Schöning commented on THRIFT-2642: --------------------------------------- I also just came across this issue. Fbthrift has a straightforward enough fix for this. I don't fully understand the IP situation with fbthrift, so maybe using their approach is out of the question. In either case, there are two parts to this problem: (1) to solve recursive and cyclic dependencies between structs themselves, (2) solve cycles of {{<Struct>.thrift_spec}}. The first part is adequately solved by setting {{<Struct>.thrift_spec}} at the bottom of the file. {code} class A(object): thrift_spec = None class B(object): thrift_spec = None A.thrift_spec = # (...) B.thrift_spec = # (...) {code} However, since the thrift_spec tuple has the format {{(<Struct>, <Struct>.thrift_spec)}}, this won't work. There are three approaches now. The fbthrift approach is to change {{(<Struct>, <Struct>.thrift_spec)}} to a list {{\[<Struct>, None\]}} and fill in the missing bit with a function call. https://github.com/facebook/fbthrift/blob/3ef868c969464e935b39e336807af1486b2739c3/thrift/lib/py/util/Recursive.py A simpler alternative is to make {{thrift_spec}} itself a list and update the code like so: {code} class Cyclic(object): thrift_spec = [] Cyclic.thrift_spec += # [...] {code} I don't know what the performance implications are. Iterating over a tuple should be slightly faster than iterating over a list, however the fbthrift solution also requires accessing lists. Both solutions make {{thrift_spec}} mutable. The third alternative is to change {{(<Struct>, <Struct>.thrift_spec)}} to just {{<Struct>}}. As far as I can see {{thrift_spec}} is only used by {{TProtocol.readStruct()}}. So the signature of {{TProtocol.readStruct(self, obj, thrift_spec, is_immutable=False)}} should be changed to {{TProtocol.readStruct(self, obj, is_immutable=False)}} and the access to {{thrift_spec}} should be changed to {{obj.thrift_spec}}. As far as I can see, {{readStruct()}} is only called from {{TBase.read()}} and {{TFrozenBase.read()}}, so this would be a simple change. The method is also undocumented. But I don't know how you feel about signature changes. > Recursive structs don't work in python > -------------------------------------- > > Key: THRIFT-2642 > URL: https://issues.apache.org/jira/browse/THRIFT-2642 > Project: Thrift > Issue Type: Bug > Components: Python - Compiler, Python - Library > Affects Versions: 0.9.2 > Reporter: Igor Kostenko > > Recursive structs in 0.9.2 work fine in c++ & c#, but not in python, because > generated code trying to use objects which not constructed yet. > Struct: > {code} > struct Recursive { > 1: list<Recursive> Children > } > {code} > Python code: > {code} > class Recursive: > thrift_spec = ( > None, # 0 > (1, TType.LIST, 'Children', (TType.STRUCT,(Recursive, > Recursive.thrift_spec)), None, ), # 1 > ) > {code} > Error message: > {code} > Traceback (most recent call last): > File "ttypes.py", line 20, in <module> > class Recursive: > File "ttypes.py", line 28, in Recursive > (1, TType.LIST, 'Children', (TType.STRUCT,(Recursive, > Recursive.thrift_spec)), None, ), # 1 > NameError: name 'Recursive' is not defined > {code} -- This message was sent by Atlassian JIRA (v6.3.15#6346)