import ast

from .context import ContextScope
from .parser import Parser
from .utils import Helpers


def kompile(src, raw=False, filename='<compiler>'):
    '''
    Creates a new class based on the supplied template, and returnsit.

    class Template(object):
        def __call__(self, context):
            return ''.join(self._iterator(context))

        def _iterator(self, context):
            return map(str, self._root(context)

        def _root(self, context):
            yield ''
            yield ...
            yield from self.head(context)

    Blocks create new methods, and add a 'yield from self.{block}(context)' to
    the current function

    '''

    parser = Parser(src)
    parser.load_library('knights.tags')
    parser.load_library('knights.helpers')

    parser.build_method('_root')

    if parser.parent:
        # Remove _root from the method list
        parser.methods = [
            method for method in parser.methods if method.name != '_root'
        ]

    klass = parser.build_class()

    # Wrap it in a module
    inst = ast.Module(body=[klass])

    ast.fix_missing_locations(inst)

    # Compile code to create class
    code = compile(inst, filename=filename, mode='exec', optimize=2)

    # Execute it and return the instance
    g = {
        '_': Helpers(parser.helpers),
        'parent': parser.parent,
        'ContextScope': ContextScope,
    }
    eval(code, g)

    klass = g['Template']
    if raw:
        return klass
    return klass()

import ast

from .context import ContextScope
from .parser import Parser
from .utils import Helpers


def kompile(src, raw=False, filename='<compiler>', **kwargs):
    '''
    Creates a new class based on the supplied template, and returnsit.

    class Template(object):
        def __call__(self, context):
            return ''.join(self._iterator(context))

        def _iterator(self, context):
            return map(str, self._root(context)

        def _root(self, context):
            yield ''
            yield ...
            yield from self.head(context)

    Blocks create new methods, and add a 'yield from self.{block}(context)' to
    the current function

    '''

    parser = Parser(src)
    parser.load_library('knights.tags')
    parser.load_library('knights.helpers')

    parser.build_method('_root')

    if parser.parent:
        # Remove _root from the method list
        parser.methods = [
            method for method in parser.methods if method.name != '_root'
        ]

    klass = parser.build_class()

    # Wrap it in a module
    inst = ast.Module(body=[klass])

    ast.fix_missing_locations(inst)

    if kwargs.get('astor', False):
        import astor
        print(astor.to_source(inst))

    # Compile code to create class
    code = compile(inst, filename=filename, mode='exec', optimize=2)

    # Execute it and return the instance
    g = {
        '_': Helpers(parser.helpers),
        'parent': parser.parent,
        'ContextScope': ContextScope,
    }
    eval(code, g)

    klass = g['Template']
    if raw:
        return klass
    return klass()

Add option to print astor reconstructed source of template
Add option to print astor reconstructed source of template

  import ast
  
  from .context import ContextScope
  from .parser import Parser
  from .utils import Helpers
  
  
- def kompile(src, raw=False, filename='<compiler>'):
+ def kompile(src, raw=False, filename='<compiler>', **kwargs):
      '''
      Creates a new class based on the supplied template, and returnsit.
  
      class Template(object):
          def __call__(self, context):
              return ''.join(self._iterator(context))
  
          def _iterator(self, context):
              return map(str, self._root(context)
  
          def _root(self, context):
              yield ''
              yield ...
              yield from self.head(context)
  
      Blocks create new methods, and add a 'yield from self.{block}(context)' to
      the current function
  
      '''
  
      parser = Parser(src)
      parser.load_library('knights.tags')
      parser.load_library('knights.helpers')
  
      parser.build_method('_root')
  
      if parser.parent:
          # Remove _root from the method list
          parser.methods = [
              method for method in parser.methods if method.name != '_root'
          ]
  
      klass = parser.build_class()
  
      # Wrap it in a module
      inst = ast.Module(body=[klass])
  
      ast.fix_missing_locations(inst)
  
+     if kwargs.get('astor', False):
+         import astor
+         print(astor.to_source(inst))
+ 
      # Compile code to create class
      code = compile(inst, filename=filename, mode='exec', optimize=2)
  
      # Execute it and return the instance
      g = {
          '_': Helpers(parser.helpers),
          'parent': parser.parent,
          'ContextScope': ContextScope,
      }
      eval(code, g)
  
      klass = g['Template']
      if raw:
          return klass
      return klass()
  
Add option to print astor reconstructed source of template
## Code Before:
import ast

from .context import ContextScope
from .parser import Parser
from .utils import Helpers


def kompile(src, raw=False, filename='<compiler>'):
    '''
    Creates a new class based on the supplied template, and returnsit.

    class Template(object):
        def __call__(self, context):
            return ''.join(self._iterator(context))

        def _iterator(self, context):
            return map(str, self._root(context)

        def _root(self, context):
            yield ''
            yield ...
            yield from self.head(context)

    Blocks create new methods, and add a 'yield from self.{block}(context)' to
    the current function

    '''

    parser = Parser(src)
    parser.load_library('knights.tags')
    parser.load_library('knights.helpers')

    parser.build_method('_root')

    if parser.parent:
        # Remove _root from the method list
        parser.methods = [
            method for method in parser.methods if method.name != '_root'
        ]

    klass = parser.build_class()

    # Wrap it in a module
    inst = ast.Module(body=[klass])

    ast.fix_missing_locations(inst)

    # Compile code to create class
    code = compile(inst, filename=filename, mode='exec', optimize=2)

    # Execute it and return the instance
    g = {
        '_': Helpers(parser.helpers),
        'parent': parser.parent,
        'ContextScope': ContextScope,
    }
    eval(code, g)

    klass = g['Template']
    if raw:
        return klass
    return klass()

## Instruction:
Add option to print astor reconstructed source of template
## Code After:
import ast

from .context import ContextScope
from .parser import Parser
from .utils import Helpers


def kompile(src, raw=False, filename='<compiler>', **kwargs):
    '''
    Creates a new class based on the supplied template, and returnsit.

    class Template(object):
        def __call__(self, context):
            return ''.join(self._iterator(context))

        def _iterator(self, context):
            return map(str, self._root(context)

        def _root(self, context):
            yield ''
            yield ...
            yield from self.head(context)

    Blocks create new methods, and add a 'yield from self.{block}(context)' to
    the current function

    '''

    parser = Parser(src)
    parser.load_library('knights.tags')
    parser.load_library('knights.helpers')

    parser.build_method('_root')

    if parser.parent:
        # Remove _root from the method list
        parser.methods = [
            method for method in parser.methods if method.name != '_root'
        ]

    klass = parser.build_class()

    # Wrap it in a module
    inst = ast.Module(body=[klass])

    ast.fix_missing_locations(inst)

    if kwargs.get('astor', False):
        import astor
        print(astor.to_source(inst))

    # Compile code to create class
    code = compile(inst, filename=filename, mode='exec', optimize=2)

    # Execute it and return the instance
    g = {
        '_': Helpers(parser.helpers),
        'parent': parser.parent,
        'ContextScope': ContextScope,
    }
    eval(code, g)

    klass = g['Template']
    if raw:
        return klass
    return klass()
