def _get_full_name(cls): if not inspect.isclass(cls): raise CodegenError("Base type has to be a class") module = inspect.getmodule(cls) if not module: raise CodegenError("Base type has to be inside a module") modulename = module.__name__ if PY33: name = cls.__qualname__ else: name = cls.__name__ # Try to reference the class try: idents = name.split('.') _cls = getattr(module, idents[0]) for ident in idents[1:]: _cls = getattr(_cls, ident) assert _cls == cls except AttributeError: raise CodegenError("Couldn't find base type, it has to be importable") return modulename, name
def _find_renderer_class(self, item): if not isinstance(item, Node): return None name = item.__class__.__name__ renderer = globals().get(name) if not renderer or not issubclass(renderer, ModelRenderer): raise CodegenError('Renderer for %s not found' % name) return renderer
def _find_renderer_class(self, node): if not isinstance(node, Node): return None name = node.__class__.__name__ renderer = globals().get(name) if not renderer or not issubclass(renderer, Base): raise CodegenError('Renderer for %s not found' % name) return renderer
def get_renderer(self, item): if not isinstance(item, Node): return None renderer_class = self._find_renderer_class(item) if renderer_class is None: raise CodegenError('Renderer not found for %s' % type(item).__name__) try: assert issubclass(renderer_class, ModelRenderer) return renderer_class(self, item) except Exception as e: raise type(e)(str(e), renderer_class.__name__)
def _find_renderer_class(self, node): if not isinstance(node, Node): return None node_class_name = node.__class__.__name__ classes = [node.__class__] while classes: cls = classes.pop() name = cls.__name__ if name in self._renderers: renderer = self._renderers[name] self._renderers[node_class_name] = renderer return renderer for base in cls.__bases__: if base not in classes: classes.append(base) raise CodegenError('Renderer for %s not found' % node_class_name)
def render(self, **fields): if {()} in self.node.exp.lookahead(): raise CodegenError('may repeat empty sequence') return '\n' + super().render(**fields)
def render(self, **fields): try: return super().render(**fields) except CodegenError as e: raise CodegenError(f'{self.node.name}={e}') from e
def codegen(model, target='python'): if target.lower() == 'python': from tatsu.codegen import python return python.codegen(model) else: raise CodegenError('Unknown target language: %s' % target)
def render(self, **fields): if {()} in self.node.exp.firstset: raise CodegenError('may repeat empty sequence') return '\n' + super(Join, self).render(**fields)