def _subs_tree(cls, tvars=None, args=None):
 if (cls.__origin__ is None):
  return cls
 current = cls.__origin__
 orig_chain = []
 while (current.__origin__ is not None):
  orig_chain.append(current)
  current = current.__origin__
 tree_args = []
 for arg in cls.__args__:
  tree_args.append(_replace_arg(arg, tvars, args))
 for ocls in orig_chain:
  new_tree_args = []
  for (i, arg) in enumerate(ocls.__args__):
   new_tree_args.append(_replace_arg(arg, ocls.__parameters__, tree_args))
  tree_args = new_tree_args
 return tree_args

def _subs_tree ( cls , tvars = None , args = None ) : if ( cls . __origin__ is None ) : return cls current = cls . __origin__ orig_chain = [ ] while ( current . __origin__ is not None ) : orig_chain . append ( current ) current = current . __origin__ tree_args = [ ] for arg in cls . __args__ : tree_args . append ( _replace_arg ( arg , tvars , args ) ) for ocls in orig_chain : new_tree_args = [ ] for ( i , arg ) in enumerate ( ocls . __args__ ) : new_tree_args . append ( _replace_arg ( arg , ocls . __parameters__ , tree_args ) ) tree_args = new_tree_args return tree_args
an internal helper function: calculate substitution tree for generic cls after replacing its type parameters with substitutions in tvars -> args .