# pylint: disable=no-init, too-few-public-methods, missing-docstring

class Node:
    """ Base class for all CST nodes.

    Exports a couple of attributes, which can be
    find in any CST node:

    * parent: the parent of this node or None, if the node
      doesn't have a parent, as in the case of the root node.

    * grammar: The grammar from which this node was built.

    """

    parent = None
    grammar = None


class ScriptBlock(Node):
    _fields = ('statements', 'named_blocks')


class NamedBlock(Node):
    _fields = ('block_name', 'statements')

# pylint: disable=no-init, too-few-public-methods, missing-docstring
# pylint: disable=protected-access

from inspect import Parameter as SignatureParameter, Signature


def make_signature(names):
    """ Build a Signature object from a list of names. """
    return Signature(
        SignatureParameter(name,
                           SignatureParameter.POSITIONAL_OR_KEYWORD,
                           default=None)
        for name in names)


class NodeMeta(type):
    """
    Metaclass which reads the '_fields' attribute
    and builds a signature from it. This allows a class
    to be defined either as ::

       m = MyClass(a=1, b=2)

    or as ::

       m = MyClass()
       m.a = 1
       m.b = 2
    """

    def __new__(mcs, name, bases, clsdict):
        clsobj = super().__new__(mcs, name, bases, clsdict)
        sig = make_signature(clsobj._fields)
        setattr(clsobj, '__signature__', sig)
        return clsobj


class Node(metaclass=NodeMeta):
    """ Base class for all CST nodes.

    Exports a couple of attributes, which can be
    find in any CST node:

    * parent: the parent of this node or None, if the node
      doesn't have a parent, as in the case of the root node.

    * grammar: The grammar from which this node was built.

    """

    parent = None
    grammar = None
    _fields = ()

    def __init__(self, *args, **kwargs):
        # pylint: disable=no-member
        bound = self.__signature__.bind(*args, **kwargs)
        for name, val in bound.arguments.items():
            setattr(self, name, val)


class ScriptBlock(Node):
    _fields = ('statements', 'named_blocks')


class NamedBlock(Node):
    _fields = ('block_name', 'statements')

Allow creating AST nodes using call syntax, through signatures.
Allow creating AST nodes using call syntax, through signatures.

By using Python 3's signatures, we can create AST nodes using
call syntax, as in Name(value=...). This also improves the
introspection.

  # pylint: disable=no-init, too-few-public-methods, missing-docstring
+ # pylint: disable=protected-access
  
- class Node:
+ from inspect import Parameter as SignatureParameter, Signature
+ 
+ 
+ def make_signature(names):
+     """ Build a Signature object from a list of names. """
+     return Signature(
+         SignatureParameter(name,
+                            SignatureParameter.POSITIONAL_OR_KEYWORD,
+                            default=None)
+         for name in names)
+ 
+ 
+ class NodeMeta(type):
+     """
+     Metaclass which reads the '_fields' attribute
+     and builds a signature from it. This allows a class
+     to be defined either as ::
+ 
+        m = MyClass(a=1, b=2)
+ 
+     or as ::
+ 
+        m = MyClass()
+        m.a = 1
+        m.b = 2
+     """
+ 
+     def __new__(mcs, name, bases, clsdict):
+         clsobj = super().__new__(mcs, name, bases, clsdict)
+         sig = make_signature(clsobj._fields)
+         setattr(clsobj, '__signature__', sig)
+         return clsobj
+ 
+ 
+ class Node(metaclass=NodeMeta):
      """ Base class for all CST nodes.
  
      Exports a couple of attributes, which can be
      find in any CST node:
  
      * parent: the parent of this node or None, if the node
        doesn't have a parent, as in the case of the root node.
  
      * grammar: The grammar from which this node was built.
  
      """
  
      parent = None
      grammar = None
+     _fields = ()
+ 
+     def __init__(self, *args, **kwargs):
+         # pylint: disable=no-member
+         bound = self.__signature__.bind(*args, **kwargs)
+         for name, val in bound.arguments.items():
+             setattr(self, name, val)
  
  
  class ScriptBlock(Node):
      _fields = ('statements', 'named_blocks')
  
  
  class NamedBlock(Node):
      _fields = ('block_name', 'statements')
  
Allow creating AST nodes using call syntax, through signatures.
## Code Before:
# pylint: disable=no-init, too-few-public-methods, missing-docstring

class Node:
    """ Base class for all CST nodes.

    Exports a couple of attributes, which can be
    find in any CST node:

    * parent: the parent of this node or None, if the node
      doesn't have a parent, as in the case of the root node.

    * grammar: The grammar from which this node was built.

    """

    parent = None
    grammar = None


class ScriptBlock(Node):
    _fields = ('statements', 'named_blocks')


class NamedBlock(Node):
    _fields = ('block_name', 'statements')

## Instruction:
Allow creating AST nodes using call syntax, through signatures.
## Code After:
# pylint: disable=no-init, too-few-public-methods, missing-docstring
# pylint: disable=protected-access

from inspect import Parameter as SignatureParameter, Signature


def make_signature(names):
    """ Build a Signature object from a list of names. """
    return Signature(
        SignatureParameter(name,
                           SignatureParameter.POSITIONAL_OR_KEYWORD,
                           default=None)
        for name in names)


class NodeMeta(type):
    """
    Metaclass which reads the '_fields' attribute
    and builds a signature from it. This allows a class
    to be defined either as ::

       m = MyClass(a=1, b=2)

    or as ::

       m = MyClass()
       m.a = 1
       m.b = 2
    """

    def __new__(mcs, name, bases, clsdict):
        clsobj = super().__new__(mcs, name, bases, clsdict)
        sig = make_signature(clsobj._fields)
        setattr(clsobj, '__signature__', sig)
        return clsobj


class Node(metaclass=NodeMeta):
    """ Base class for all CST nodes.

    Exports a couple of attributes, which can be
    find in any CST node:

    * parent: the parent of this node or None, if the node
      doesn't have a parent, as in the case of the root node.

    * grammar: The grammar from which this node was built.

    """

    parent = None
    grammar = None
    _fields = ()

    def __init__(self, *args, **kwargs):
        # pylint: disable=no-member
        bound = self.__signature__.bind(*args, **kwargs)
        for name, val in bound.arguments.items():
            setattr(self, name, val)


class ScriptBlock(Node):
    _fields = ('statements', 'named_blocks')


class NamedBlock(Node):
    _fields = ('block_name', 'statements')
