##
# Portions Copyright (c) 2008-2010 MagicStack Inc.
# Portions Copyright (c) 2008 Armin Ronacher.
# All rights reserved.
#
# This code is licensed under the PSFL license.
##


import itertools

from .visitor import NodeVisitor


class SourceGenerator(NodeVisitor):
    """This visitor is able to transform a well formed syntax tree into python
    sourcecode.  For more details have a look at the docstring of the
    `node_to_source` function.
    """

    def __init__(self, indent_with=' '*4, add_line_information=False,
                       pretty=True):
        self.result = []
        self.indent_with = indent_with
        self.add_line_information = add_line_information
        self.indentation = 0
        self.new_lines = 0
        self.current_line = 1
        self.pretty = pretty

    def write(self, *x, delimiter=None):
        if self.new_lines:
            if self.result and self.pretty:
                self.current_line += self.new_lines
                self.result.append('\n' * self.new_lines)
            if self.pretty:
                self.result.append(self.indent_with * self.indentation)
            else:
                self.result.append(' ')
            self.new_lines = 0
        if delimiter:
            self.result.append(x[0])
            chain = itertools.chain.from_iterable
            chunks = chain((delimiter, v) for v in x[1:])
        else:
            chunks = x

        for chunk in chunks:
            if chunk is None:
                raise ValueError('invalid text chunk in codegen')
            self.result.append(chunk)

    def visit_list(self, items, *, newlines=True):
        for i, item in enumerate(items):
            if i > 0:
                self.write(',')
                if newlines:
                    self.new_lines = 1
                else:
                    self.write(' ')
            self.visit(item)

    def newline(self, node=None, extra=0):
        self.new_lines = max(self.new_lines, 1 + extra)
        if node is not None and self.add_line_information:
            self.write('# line: %s' % node.lineno)
            self.new_lines = 1

    @classmethod
    def to_source(cls, node, indent_with=' '*4, add_line_information=False,
                             pretty=True):
        generator = cls(indent_with, add_line_information, pretty=pretty)
        generator.visit(node)
        return ''.join(generator.result)

@@ -1457,21 +1457,34 @@
  if 
-chunk is None
+not isinstance(chunk, str)
 :%0A  
@@ -1514,16 +1514,37 @@
 ueError(
+%0A                    
 'invalid
@@ -1565,17 +1565,35 @@
  codegen
-'
+: %25r'.format(chunk)
 )%0A      

Raise when write() is called with a non-string argument