def find_sourcemap_comment(filepath, block_size=100):
    """
    Seeks and removes the sourcemap comment. If found, the sourcemap line is
    returned.

    Bundled output files can have massive amounts of lines, and the sourceMap
    comment is always at the end. So, to extract it efficiently, we read out the
    lines of the file starting from the end. We look back at most 2 lines.

    :param:filepath: path to output bundle file containing the sourcemap comment
    :param:blocksize: integer saying how many bytes to read at once
    :return:string with the sourcemap comment or None
    """

    MAX_TRACKBACK = 2  # look back at most 2 lines, catching potential blank line at the end

    block_number = -1
    # blocks of size block_size, in reverse order starting from the end of the file
    blocks = []
    sourcemap = None

    try:
        # open file in binary read+write mode, so we can seek with negative offsets
        of = io.open(filepath, 'br+')
        # figure out what's the end byte
        of.seek(0, os.SEEK_END)
        block_end_byte = of.tell()

        # track back for maximum MAX_TRACKBACK lines and while we can track back
        while block_end_byte > 0 and MAX_TRACKBACK > 0:
            if (block_end_byte - block_size > 0):
                # read the last block we haven't yet read
                of.seek(block_number*block_size, os.SEEK_END)
                blocks.append(of.read(block_size))
            else:
                # file too small, start from begining
                of.seek(0, os.SEEK_SET)
                # only read what was not read
                blocks = [of.read(block_end_byte)]

            # update variables that control while loop
            content = b''.join(reversed(blocks))
            lines_found = content.count(b'\n')
            MAX_TRACKBACK -= lines_found
            block_end_byte -= block_size
            block_number -= 1

            # early check and bail out if we found the sourcemap comment
            if SOURCEMAPPING_URL_COMMENT in content:
                offset = 0
                # splitlines eats the last \n if its followed by a blank line
                lines = content.split(b'\n')
                for i, line in enumerate(lines):
                    if line.startswith(SOURCEMAPPING_URL_COMMENT):
                        offset = len(line)
                        sourcemap = line
                        break
                while i+1 < len(lines):
                    offset += 1  # for the newline char
                    offset += len(lines[i+1])
                    i += 1
                # track back until the start of the comment, and truncate the comment
                if sourcemap:
                    offset += 1  # for the newline before the sourcemap comment
                    of.seek(-offset, os.SEEK_END)
                    of.truncate()
                return force_text(sourcemap)
    finally:
        of.close()
    return sourcemap

Seeks and removes the sourcemap comment . If found the sourcemap line is returned .


def needs_ext(self):
        """
        Check whether `self.app` is missing the '.js' extension and if it needs it.
        """
        if settings.SYSTEMJS_DEFAULT_JS_EXTENSIONS:
            name, ext = posixpath.splitext(self.app)
            if not ext:
                return True
        return False

def needs_ext ( self ) : if settings . SYSTEMJS_DEFAULT_JS_EXTENSIONS : name , ext = posixpath . splitext ( self . app ) if not ext : return True return False

Check whether self . app is missing the . js extension and if it needs it .


def bundle(self):
        """
        Bundle the app and return the static url to the bundle.
        """
        outfile, rel_path = self.get_paths()

        options = self.opts
        if self.system._has_jspm_log():
            self.command += ' --log {log}'
            options.setdefault('log', 'err')

        if options.get('minify'):
            self.command += ' --minify'

        if options.get('skip_source_maps'):
            self.command += ' --skip-source-maps'

        try:
            cmd = self.command.format(app=self.app, outfile=outfile, **options)
            proc = subprocess.Popen(
                cmd, shell=True, cwd=self.system.cwd, stdout=self.stdout,
                stdin=self.stdin, stderr=self.stderr)

            result, err = proc.communicate()  # block until it's done
            if err and self.system._has_jspm_log():
                fmt = 'Could not bundle \'%s\': \n%s'
                logger.warn(fmt, self.app, err)
                raise BundleError(fmt % (self.app, err))
            if result.strip():
                logger.info(result)
        except (IOError, OSError) as e:
            if isinstance(e, BundleError):
                raise
            raise BundleError('Unable to apply %s (%r): %s' % (
                              self.__class__.__name__, cmd, e))
        else:
            if not options.get('sfx'):
                # add the import statement, which is missing for non-sfx bundles
                sourcemap = find_sourcemap_comment(outfile)
                with open(outfile, 'a') as of:
                    of.write("\nSystem.import('{app}{ext}');\n{sourcemap}".format(
                        app=self.app,
                        ext='.js' if self.needs_ext() else '',
                        sourcemap=sourcemap if sourcemap else '',
                    ))
        return rel_path

Bundle the app and return the static url to the bundle .


def trace(self, app):
        """
        Trace the dependencies for app.

        A tracer-instance is shortlived, and re-tracing the same app should
        yield the same results. Since tracing is an expensive process, cache
        the result on the tracer instance.
        """
        if app not in self._trace_cache:
            process = subprocess.Popen(
                "trace-deps.js {}".format(app), shell=True,
                stdout=subprocess.PIPE, stderr=subprocess.PIPE,
                env=self.env, universal_newlines=True, cwd=self._package_json_dir
            )
            out, err = process.communicate()
            if err:
                raise TraceError(err)
            self._trace_cache[app] = json.loads(out)
        return self._trace_cache[app]

def
trace
(
self
,
app
)
:
if
app
not
in
self
.
_trace_cache
:
process
=
subprocess
.
Popen
(
"trace-deps.js {}"
.
format
(
app
)
,
shell
=
True
,
stdout
=
subprocess
.
PIPE
,
stderr
=
subprocess
.
PIPE
,
env
=
self
.
env
,
universal_newlines
=
True
,
cwd
=
self
.
_package_json_dir
)
out
,
err
=
process
.
communicate
(
)
if
err
:
raise
TraceError
(
err
)
self
.
_trace_cache
[
app
]
=
json
.
loads
(
out
)
return
self
.
_trace_cache
[
app
]


def hashes_match(self, dep_tree):
        """
        Compares the app deptree file hashes with the hashes stored in the
        cache.
        """
        hashes = self.get_hashes()
        for module, info in dep_tree.items():
            md5 = self.get_hash(info['path'])
            if md5 != hashes[info['path']]:
                return False
        return True

def hashes_match ( self , dep_tree ) : hashes = self . get_hashes ( ) for module , info in dep_tree . items ( ) : md5 = self . get_hash ( info [ 'path' ] ) if md5 != hashes [ info [ 'path' ] ] : return False return True

Compares the app deptree file hashes with the hashes stored in the cache .


def format_hexdump(arg):
    """Convert the bytes object to a hexdump.

    The output format will be:

    <offset, 4-byte>  <16-bytes of output separated by 1 space>  <16 ascii characters>
    """

    line = ''

    for i in range(0, len(arg), 16):
        if i > 0:
            line += '\n'
        chunk = arg[i:i + 16]
        hex_chunk = hexlify(chunk).decode('utf-8')
        hex_line = ' '.join(hex_chunk[j:j + 2] for j in range(0, len(hex_chunk), 2))

        if len(hex_line) < (3 * 16) - 1:
            hex_line += ' ' * (((3 * 16) - 1) - len(hex_line))

        ascii_line = ''.join(_convert_to_ascii(x) for x in chunk)
        offset_line = '%08x' % i

        line += "%s  %s  %s" % (offset_line, hex_line, ascii_line)

    return line

def
format_hexdump
(
arg
)
:
line
=
''
for
i
in
range
(
0
,
len
(
arg
)
,
16
)
:
if
i
>
0
:
line
+=
'\n'
chunk
=
arg
[
i
:
i
+
16
]
hex_chunk
=
hexlify
(
chunk
)
.
decode
(
'utf-8'
)
hex_line
=
' '
.
join
(
hex_chunk
[
j
:
j
+
2
]
for
j
in
range
(
0
,
len
(
hex_chunk
)
,
2
)
)
if
len
(
hex_line
)
<
(
3
*
16
)
1
:
hex_line
+=
' '
*
(
(
(
3
*
16
)
1
)
len
(
hex_line
)
)
ascii_line
=
''
.
join
(
_convert_to_ascii
(
x
)
for
x
in
chunk
)
offset_line
=
'%08x'
%
i
line
+=
"%s  %s  %s"
%
(
offset_line
,
hex_line
,
ascii_line
)
return
line


def parse_docstring(doc):
    """Parse a docstring into ParameterInfo and ReturnInfo objects."""

    doc = inspect.cleandoc(doc)
    lines = doc.split('\n')
    section = None
    section_indent = None

    params = {}
    returns = None

    for line in lines:
        line = line.rstrip()

        if len(line) == 0:
            continue
        elif str(line) == 'Args:':
            section = 'args'
            section_indent = None
            continue
        elif str(line) == 'Returns:':
            section = 'return'
            section_indent = None
            continue

        if section is not None:
            stripped = line.lstrip()
            margin = len(line) - len(stripped)

            if section_indent is None:
                section_indent = margin

            if margin != section_indent:
                continue

            # These are all the param lines in the docstring that are
            # not continuations of the previous line
            if section == 'args':
                param_name, type_info = parse_param(stripped)
                params[param_name] = type_info
            elif section == 'return':
                returns = parse_return(stripped)

    return params, returns

Parse a docstring into ParameterInfo and ReturnInfo objects .


def valid_identifiers(self):
        """Get a list of all valid identifiers for the current context.

        Returns:
            list(str): A list of all of the valid identifiers for this context
        """

        funcs = list(utils.find_all(self.contexts[-1])) + list(self.builtins)
        return funcs

def valid_identifiers ( self ) : funcs = list ( utils . find_all ( self . contexts [ - 1 ] ) ) + list ( self . builtins ) return funcs

Get a list of all valid identifiers for the current context .


def _deferred_add(cls, add_action):
        """Lazily load a callable.

        Perform a lazy import of a context so that we don't have a huge initial startup time
        loading all of the modules that someone might want even though they probably only
        will use a few of them.
        """

        module, _, obj = add_action.partition(',')

        mod = importlib.import_module(module)
        if obj == "":
            _, con = annotate.context_from_module(mod)
            return con

        if hasattr(mod, obj):
            return getattr(mod, obj)

        raise ArgumentError("Attempted to import nonexistent object from module", module=module, object=obj)


def _split_line(self, line):
        """Split a line into arguments using shlex and a dequoting routine."""

        parts = shlex.split(line, posix=self.posix_lex)
        if not self.posix_lex:
            parts = [self._remove_quotes(x) for x in parts]

        return parts

def _split_line ( self , line ) : parts = shlex . split ( line , posix = self . posix_lex ) if not self . posix_lex : parts = [ self . _remove_quotes ( x ) for x in parts ] return parts

Split a line into arguments using shlex and a dequoting routine .


def _check_initialize_context(self):
        """
        Check if our context matches something that we have initialization commands
        for.  If so, run them to initialize the context before proceeding with other
        commands.
        """

        path = ".".join([annotate.context_name(x) for x in self.contexts])

        #Make sure we don't clutter up the output with return values from
        #initialization functions
        old_interactive = type_system.interactive
        type_system.interactive = False

        for key, cmds in self.init_commands.items():
            if path.endswith(key):
                for cmd in cmds:
                    line = self._split_line(cmd)
                    self.invoke(line)

        type_system.interactive = old_interactive

Check if our context matches something that we have initialization commands for . If so run them to initialize the context before proceeding with other commands .


def _builtin_help(self, args):
        """Return help information for a context or function."""

        if len(args) == 0:
            return self.list_dir(self.contexts[-1])
        if len(args) == 1:
            func = self.find_function(self.contexts[-1], args[0])
            return annotate.get_help(func)

        help_text = "Too many arguments: " + str(args) + "\n"
        help_text += "Usage: help [function]"
        return help_text

def
_builtin_help
(
self
,
args
)
:
if
len
(
args
)
==
0
:
return
self
.
list_dir
(
self
.
contexts
[
1
]
)
if
len
(
args
)
==
1
:
func
=
self
.
find_function
(
self
.
contexts
[
1
]
,
args
[
0
]
)
return
annotate
.
get_help
(
func
)
help_text
=
"Too many arguments: "
+
str
(
args
)
+
"\n"
help_text
+=
"Usage: help [function]"
return
help_text

Return help information for a context or function .


def find_function(self, context, funname):
        """Find a function in the given context by name.

        This function will first search the list of builtins and if the
        desired function is not a builtin, it will continue to search
        the given context.

        Args:
            context (object): A dict or class that is a typedargs context
            funname (str): The name of the function to find

        Returns:
            callable: The found function.
        """

        if funname in self.builtins:
            return self.builtins[funname]

        func = None
        if isinstance(context, dict):
            if funname in context:
                func = context[funname]

                #Allowed lazy loading of functions
                if isinstance(func, str):
                    func = self._deferred_add(func)
                    context[funname] = func
        elif hasattr(context, funname):
            func = getattr(context, funname)

        if func is None:
            raise NotFoundError("Function not found", function=funname)

        return func

def
find_function
(
self
,
context
,
funname
)
:
if
funname
in
self
.
builtins
:
return
self
.
builtins
[
funname
]
func
=
if
isinstance
(
context
,
dict
)
:
if
funname
in
context
:
func
=
context
[
funname
]
#Allowed lazy loading of functions
if
isinstance
(
func
,
str
)
:
func
=
self
.
_deferred_add
(
func
)
context
[
funname
]
=
func
elif
hasattr
(
context
,
funname
)
:
func
=
getattr
(
context
,
funname
)
if
func
is
:
raise
NotFoundError
(
"Function not found"
,
function
=
funname
)
return
func

Find a function in the given context by name .


def list_dir(self, context):
        """Return a listing of all of the functions in this context including builtins.

        Args:
            context (object): The context to print a directory for.

        Returns:
            str
        """

        doc = inspect.getdoc(context)

        listing = ""
        listing += "\n"

        listing += annotate.context_name(context) + "\n"

        if doc is not None:
            doc = inspect.cleandoc(doc)
            listing += doc + "\n"

        listing += "\nDefined Functions:\n"
        is_dict = False

        if isinstance(context, dict):
            funs = context.keys()
            is_dict = True
        else:
            funs = utils.find_all(context)

        for fun in sorted(funs):
            override_name = None
            if is_dict:
                override_name = fun

            fun = self.find_function(context, fun)

            if isinstance(fun, dict):
                if is_dict:
                    listing += " - " + override_name + '\n'
                else:
                    listing += " - " + fun.metadata.name + '\n'
            else:
                listing += " - " + fun.metadata.signature(name=override_name) + '\n'

            if annotate.short_description(fun) != "":
                listing += "   " + annotate.short_description(fun) + '\n'

        listing += "\nBuiltin Functions\n"
        for bif in sorted(self.builtins.keys()):
            listing += ' - ' + bif + '\n'

        listing += '\n'
        return listing

def
list_dir
(
self
,
context
)
:
doc
=
inspect
.
getdoc
(
context
)
listing
=
""
listing
+=
"\n"
listing
+=
annotate
.
context_name
(
context
)
+
"\n"
if
doc
is
not
:
doc
=
inspect
.
cleandoc
(
doc
)
listing
+=
doc
+
"\n"
listing
+=
"\nDefined Functions:\n"
is_dict
=
False
if
isinstance
(
context
,
dict
)
:
funs
=
context
.
keys
(
)
is_dict
=
True
else
:
funs
=
utils
.
find_all
(
context
)
for
fun
in
sorted
(
funs
)
:
override_name
=
if
is_dict
:
override_name
=
fun
fun
=
self
.
find_function
(
context
,
fun
)
if
isinstance
(
fun
,
dict
)
:
if
is_dict
:
listing
+=
" - "
+
override_name
+
'\n'
else
:
listing
+=
" - "
+
fun
.
metadata
.
name
+
'\n'
else
:
listing
+=
" - "
+
fun
.
metadata
.
signature
(
name
=
override_name
)
+
'\n'
if
annotate
.
short_description
(
fun
)
!=
""
:
listing
+=
"   "
+
annotate
.
short_description
(
fun
)
+
'\n'
listing
+=
"\nBuiltin Functions\n"
for
bif
in
sorted
(
self
.
builtins
.
keys
(
)
)
:
listing
+=
' - '
+
bif
+
'\n'
listing
+=
'\n'
return
listing

Return a listing of all of the functions in this context including builtins .


def _is_flag(cls, arg):
        """Check if an argument is a flag.

        A flag starts with - or -- and the next character must be a letter
        followed by letters, numbers, - or _.  Currently we only check the
        alpha'ness of the first non-dash character to make sure we're not just
        looking at a negative number.

        Returns:
            bool: Whether the argument is a flag.
        """

        if arg == '--':
            return False

        if not arg.startswith('-'):
            return False

        if arg.startswith('--'):
            first_char = arg[2]
        else:
            first_char = arg[1]

        if not first_char.isalpha():
            return False

        return True

def _is_flag ( cls , arg ) : if arg == '--' : return False if not arg . startswith ( '-' ) : return False if arg . startswith ( '--' ) : first_char = arg [ 2 ] else : first_char = arg [ 1 ] if not first_char . isalpha ( ) : return False return True


def process_arguments(self, func, args):
        """Process arguments from the command line into positional and kw args.

        Arguments are consumed until the argument spec for the function is filled
        or a -- is found or there are no more arguments.  Keyword arguments can be
        specified using --field=value, -f value or --field value.  Positional
        arguments are specified just on the command line itself.

        If a keyword argument (`field`) is a boolean, it can be set to True by just passing
        --field or -f without needing to explicitly pass True unless this would cause
        ambiguity in parsing since the next expected positional argument is also a boolean
        or a string.

        Args:
            func (callable): A function previously annotated with type information
            args (list): A list of all of the potential arguments to this function.

        Returns:
            (args, kw_args, unused args): A tuple with a list of args, a dict of
                keyword args and a list of any unused args that were not processed.
        """

        pos_args = []
        kw_args = {}

        while len(args) > 0:
            if func.metadata.spec_filled(pos_args, kw_args) and not self._is_flag(args[0]):
                break

            arg = args.pop(0)

            if arg == '--':
                break
            elif self._is_flag(arg):
                arg_value = None
                arg_name = None

                if len(arg) == 2:
                    arg_name = func.metadata.match_shortname(arg[1:], filled_args=pos_args)
                else:
                    if not arg.startswith('--'):
                        raise ArgumentError("Invalid method of specifying keyword argument that did not start with --", argument=arg)

                    # Skip the --
                    arg = arg[2:]

                    # Check if the value is embedded in the parameter
                    # Make sure we allow the value after the equals sign to also
                    # contain an equals sign.
                    if '=' in arg:
                        arg, arg_value = arg.split('=', 1)

                    arg_name = func.metadata.match_shortname(arg, filled_args=pos_args)

                arg_type = func.metadata.param_type(arg_name)
                if arg_type is None:
                    raise ArgumentError("Attempting to set a parameter from command line that does not have type information", argument=arg_name)

                # If we don't have a value yet, attempt to get one from the next parameter on the command line
                if arg_value is None:
                    arg_value = self._extract_arg_value(arg_name, arg_type, args)

                kw_args[arg_name] = arg_value
            else:
                pos_args.append(arg)

        # Always check if there is a trailing '--' and chomp so that we always
        # start on a function name.  This can happen if there is a gratuitous
        # -- for a 0 arg function or after an implicit boolean flag like -f --
        if len(args) > 0 and args[0] == '--':
            args.pop(0)

        return pos_args, kw_args, args

Process arguments from the command line into positional and kw args .


def _extract_arg_value(cls, arg_name, arg_type, remaining):
        """Try to find the value for a keyword argument."""

        next_arg = None
        should_consume = False
        if len(remaining) > 0:
            next_arg = remaining[0]
            should_consume = True

            if next_arg == '--':
                next_arg = None

        # Generally we just return the next argument, however if the type
        # is bool we allow not specifying anything to mean true if there
        # is no ambiguity
        if arg_type == "bool":
            if next_arg is None or next_arg.startswith('-'):
                next_arg = True
                should_consume = False
        else:
            if next_arg is None:
                raise ArgumentError("Could not find value for keyword argument", argument=arg_name)

        if should_consume:
            remaining.pop(0)

        return next_arg

Try to find the value for a keyword argument .


def invoke_one(self, line):
        """Invoke a function given a list of arguments with the function listed first.

        The function is searched for using the current context on the context stack
        and its annotated type information is used to convert all of the string parameters
        passed in line to appropriate python types.

        Args:
            line (list): The list of command line arguments.

        Returns:
            (object, list, bool): A tuple containing the return value of the function, if any,
                a boolean specifying if the function created a new context (False if a new context
                was created) and a list with the remainder of the command line if this function
                did not consume all arguments.
        """

        funname = line.pop(0)

        context = self.contexts[-1]
        func = self.find_function(context, funname)

        #If this is a context derived from a module or package, just jump to it
        #since there is no initialization function
        if isinstance(func, dict):
            self.contexts.append(func)
            self._check_initialize_context()
            return None, line, False

        # If the function wants arguments directly, do not parse them, otherwise turn them
        # into positional and kw arguments
        if func.takes_cmdline is True:
            val = func(line)
            line = []
        else:
            posargs, kwargs, line = self.process_arguments(func, line)

            #We need to check for not enough args for classes before calling or the call won't make it all the way to __init__
            if inspect.isclass(func) and not func.metadata.spec_filled(posargs, kwargs):
                raise ValidationError("Not enough parameters specified to call function", function=func.metadata.name, signature=func.metadata.signature())

            val = func(*posargs, **kwargs)

        # Update our current context if this function destroyed it or returned a new one.
        finished = True

        if func.finalizer is True:
            self.contexts.pop()
        elif val is not None:
            if func.metadata.returns_data():
                val = func.metadata.format_returnvalue(val)
            else:
                self.contexts.append(val)
                self._check_initialize_context()
                finished = False
                val = None

        return val, line, finished

Invoke a function given a list of arguments with the function listed first .


def invoke(self, line):
        """Invoke a one or more function given a list of arguments.

        The functions are searched for using the current context on the context stack
        and its annotated type information is used to convert all of the string parameters
        passed in line to appropriate python types.

        Args:
            line (list): The list of command line arguments.

        Returns:
            bool: A boolean specifying if the last function created a new context
                (False if a new context was created) and a list with the remainder of the
                command line if this function did not consume all arguments.)
        """

        finished = True

        while len(line) > 0:
            val, line, finished = self.invoke_one(line)
            if val is not None:
                iprint(val)

        return finished

def invoke ( self , line ) : finished = True while len ( line ) > 0 : val , line , finished = self . invoke_one ( line ) if val is not None : iprint ( val ) return finished

Invoke a one or more function given a list of arguments .


def invoke_string(self, line):
        """Parse and invoke a string line.

        Args:
            line (str): The line that we want to parse and invoke.

        Returns:
            bool: A boolean specifying if the last function created a new context
                (False if a new context was created) and a list with the remainder of the
                command line if this function did not consume all arguments.)
        """

        # Make sure line is a unicode string on all python versions
        line = str(line)

        # Ignore empty lines and comments
        if len(line) == 0:
            return True

        if line[0] == u'#':
            return True

        args = self._split_line(line)
        return self.invoke(args)


def parse_param(param, include_desc=False):
    """Parse a single typed parameter statement."""

    param_def, _colon, desc = param.partition(':')
    if not include_desc:
        desc = None
    else:
        desc = desc.lstrip()

    if _colon == "":
        raise ValidationError("Invalid parameter declaration in docstring, missing colon", declaration=param)

    param_name, _space, param_type = param_def.partition(' ')
    if len(param_type) < 2 or param_type[0] != '(' or param_type[-1] != ')':
        raise ValidationError("Invalid parameter type string not enclosed in ( ) characters", param_string=param_def, type_string=param_type)

    param_type = param_type[1:-1]
    return param_name, ParameterInfo(param_type, [], desc)

Parse a single typed parameter statement .


def parse_return(return_line, include_desc=False):
    """Parse a single return statement declaration.

    The valid types of return declarion are a Returns: section heading
    followed a line that looks like:
    type [format-as formatter]: description

    OR

    type [show-as (string | context)]: description sentence
    """

    ret_def, _colon, desc = return_line.partition(':')
    if _colon == "":
        raise ValidationError("Invalid return declaration in docstring, missing colon", declaration=ret_def)

    if not include_desc:
        desc = None

    if 'show-as' in ret_def:
        ret_type, _showas, show_type = ret_def.partition('show-as')
        ret_type = ret_type.strip()
        show_type = show_type.strip()

        if show_type not in ('string', 'context'):
            raise ValidationError("Unkown show-as formatting specifier", found=show_type, expected=['string', 'context'])

        if show_type == 'string':
            return ReturnInfo(None, str, True, desc)

        return ReturnInfo(None, None, False, desc)

    if 'format-as' in ret_def:
        ret_type, _showas, formatter = ret_def.partition('format-as')
        ret_type = ret_type.strip()
        formatter = formatter.strip()

        return ReturnInfo(ret_type, formatter, True, desc)

    return ReturnInfo(ret_def, None, True, desc)

Parse a single return statement declaration .


def _classify_section(cls, section):
        """Attempt to find the canonical name of this section."""

        name = section.lower()

        if name in frozenset(['args', 'arguments', "params", "parameters"]):
            return cls.ARGS_SECTION

        if name in frozenset(['returns', 'return']):
            return cls.RETURN_SECTION

        if name in frozenset(['main']):
            return cls.MAIN_SECTION

        return None

def _classify_section ( cls , section ) : name = section . lower ( ) if name in frozenset ( [ 'args' , 'arguments' , "params" , "parameters" ] ) : return cls . ARGS_SECTION if name in frozenset ( [ 'returns' , 'return' ] ) : return cls . RETURN_SECTION if name in frozenset ( [ 'main' ] ) : return cls . MAIN_SECTION return None

Attempt to find the canonical name of this section .


def _classify_line(cls, line):
        """Classify a line into a type of object."""

        line = line.rstrip()

        if len(line) == 0:
            return BlankLine('')

        if ' ' not in line and line.endswith(':'):
            name = line[:-1]
            return SectionHeader(name)

        if line.startswith('  '):
            return ContinuationLine(line.lstrip())

        if line.startswith(' - '):
            return ListItem('-', line[3:].lstrip())

        if line.startswith('- '):
            return ListItem('-', line[2:].lstrip())

        return Line(line)

def
_classify_line
(
cls
,
line
)
:
line
=
line
.
rstrip
(
)
if
len
(
line
)
==
0
:
return
BlankLine
(
''
)
if
' '
not
in
line
and
line
.
endswith
(
':'
)
:
name
=
line
[
:
1
]
return
SectionHeader
(
name
)
if
line
.
startswith
(
'  '
)
:
return
ContinuationLine
(
line
.
lstrip
(
)
)
if
line
.
startswith
(
' - '
)
:
return
ListItem
(
'-'
,
line
[
3
:
]
.
lstrip
(
)
)
if
line
.
startswith
(
'- '
)
:
return
ListItem
(
'-'
,
line
[
2
:
]
.
lstrip
(
)
)
return
Line
(
line
)


def _join_paragraphs(cls, lines, use_indent=False, leading_blanks=False, trailing_blanks=False):
        """Join adjacent lines together into paragraphs using either a blank line or indent as separator."""

        curr_para = []
        paragraphs = []

        for line in lines:
            if use_indent:
                if line.startswith(' '):
                    curr_para.append(line.lstrip())
                    continue
                elif line == '':
                    continue
                else:
                    if len(curr_para) > 0:
                        paragraphs.append(cls._join_paragraph(curr_para, leading_blanks, trailing_blanks))

                    curr_para = [line.lstrip()]
            else:
                if len(line) != 0:
                    curr_para.append(line)
                else:
                    paragraphs.append(cls._join_paragraph(curr_para, leading_blanks, trailing_blanks))
                    curr_para = []

        # Finish the last paragraph if there is one
        if len(curr_para) > 0:
            paragraphs.append(cls._join_paragraph(curr_para, leading_blanks, trailing_blanks))

        return paragraphs

Join adjacent lines together into paragraphs using either a blank line or indent as separator .


def wrap_and_format(self, width=None, include_params=False, include_return=False, excluded_params=None):
        """Wrap, format and print this docstring for a specific width.

        Args:
            width (int): The number of characters per line.  If set to None
                this will be inferred from the terminal width and default
                to 80 if not passed or if passed as None and the terminal
                width cannot be determined.
            include_return (bool): Include the return information section
                in the output.
            include_params (bool): Include a parameter information section
                in the output.
            excluded_params (list): An optional list of parameter names to exclude.
                Options for excluding things are, for example, 'self' or 'cls'.
        """

        if excluded_params is None:
            excluded_params = []

        out = StringIO()
        if width is None:
            width, _height = get_terminal_size()

        for line in self.maindoc:
            if isinstance(line, Line):
                out.write(fill(line.contents, width=width))
                out.write('\n')
            elif isinstance(line, BlankLine):
                out.write('\n')
            elif isinstance(line, ListItem):
                out.write(fill(line.contents, initial_indent=" %s " % line.marker[0], subsequent_indent="   ", width=width))
                out.write('\n')

        if include_params:
            included_params = set(self.param_info) - set(excluded_params)
            if len(included_params) > 0:
                out.write("\nParameters:\n")

                for param in included_params:
                    info = self.param_info[param]
                    out.write(" - %s (%s):\n" % (param, info.type_name))
                    out.write(fill(info.desc, initial_indent="   ", subsequent_indent="   ", width=width))
                    out.write('\n')

        if include_return:
            print("Returns:")
            print("    " + self.return_info.type_name)
            #pylint:disable=fixme; Issue tracked in #32
            # TODO: Also include description information here

        return out.getvalue()

Wrap format and print this docstring for a specific width .


def convert_to_type(self, value, typename, **kwargs):
        """
        Convert value to type 'typename'

        If the conversion routine takes various kwargs to
        modify the conversion process, \\**kwargs is passed
        through to the underlying conversion function
        """
        try:
            if isinstance(value, bytearray):
                return self.convert_from_binary(value, typename, **kwargs)

            typeobj = self.get_type(typename)

            conv = typeobj.convert(value, **kwargs)
            return conv
        except (ValueError, TypeError) as exc:
            raise ValidationError("Could not convert value", type=typename, value=value, error_message=str(exc))

def
convert_to_type
(
self
,
value
,
typename
,
*
*
kwargs
)
:
try
:
if
isinstance
(
value
,
bytearray
)
:
return
self
.
convert_from_binary
(
value
,
typename
,
*
*
kwargs
)
typeobj
=
self
.
get_type
(
typename
)
conv
=
typeobj
.
convert
(
value
,
*
*
kwargs
)
return
conv
except
(
ValueError
,
TypeError
)
as
exc
:
raise
ValidationError
(
"Could not convert value"
,
type
=
typename
,
value
=
value
,
error_message
=
str
(
exc
)
)


def convert_from_binary(self, binvalue, type, **kwargs):
        """
        Convert binary data to type 'type'.

        'type' must have a convert_binary function.  If 'type'
        supports size checking, the size function is called to ensure
        that binvalue is the correct size for deserialization
        """

        size = self.get_type_size(type)
        if size > 0 and len(binvalue) != size:
            raise ArgumentError("Could not convert type from binary since the data was not the correct size", required_size=size, actual_size=len(binvalue), type=type)

        typeobj = self.get_type(type)

        if not hasattr(typeobj, 'convert_binary'):
            raise ArgumentError("Type does not support conversion from binary", type=type)

        return typeobj.convert_binary(binvalue, **kwargs)


def get_type_size(self, type):
        """
        Get the size of this type for converting a hex string to the
        type. Return 0 if the size is not known.
        """

        typeobj = self.get_type(type)

        if hasattr(typeobj, 'size'):
            return typeobj.size()

        return 0

def get_type_size ( self , type ) : typeobj = self . get_type ( type ) if hasattr ( typeobj , 'size' ) : return typeobj . size ( ) return 0

Get the size of this type for converting a hex string to the type . Return 0 if the size is not known .


def format_value(self, value, type, format=None, **kwargs):
        """
        Convert value to type and format it as a string

        type must be a known type in the type system and format,
        if given, must specify a valid formatting option for the
        specified type.
        """

        typed_val = self.convert_to_type(value, type, **kwargs)
        typeobj = self.get_type(type)

        #Allow types to specify default formatting functions as 'default_formatter'
        #otherwise if not format is specified, just convert the value to a string
        if format is None:
            if hasattr(typeobj, 'default_formatter'):
                format_func = getattr(typeobj, 'default_formatter')
                return format_func(typed_val, **kwargs)

            return str(typed_val)

        formatter = "format_%s" % str(format)
        if not hasattr(typeobj, formatter):
            raise ArgumentError("Unknown format for type", type=type, format=format, formatter_function=formatter)

        format_func = getattr(typeobj, formatter)
        return format_func(typed_val, **kwargs)


def _validate_type(cls, typeobj):
        """
        Validate that all required type methods are implemented.

        At minimum a type must have:
        - a convert() or convert_binary() function
        - a default_formatter() function

        Raises an ArgumentError if the type is not valid
        """

        if not (hasattr(typeobj, "convert") or hasattr(typeobj, "convert_binary")):
            raise ArgumentError("type is invalid, does not have convert or convert_binary function", type=typeobj, methods=dir(typeobj))

        if not hasattr(typeobj, "default_formatter"):
            raise ArgumentError("type is invalid, does not have default_formatter function", type=typeobj, methods=dir(typeobj))

Validate that all required type methods are implemented .


def is_known_type(self, type_name):
        """Check if type is known to the type system.

        Returns:
            bool: True if the type is a known instantiated simple type, False otherwise
        """

        type_name = str(type_name)
        if type_name in self.known_types:
            return True

        return False

def is_known_type ( self , type_name ) : type_name = str ( type_name ) if type_name in self . known_types : return True return False

Check if type is known to the type system .


def split_type(self, typename):
        """
        Given a potentially complex type, split it into its base type and specializers
        """

        name = self._canonicalize_type(typename)
        if '(' not in name:
            return name, False, []

        base, sub = name.split('(')
        if len(sub) == 0 or sub[-1] != ')':
            raise ArgumentError("syntax error in complex type, no matching ) found", passed_type=typename, basetype=base, subtype_string=sub)

        sub = sub[:-1]

        subs = sub.split(',')
        return base, True, subs

Given a potentially complex type split it into its base type and specializers


def instantiate_type(self, typename, base, subtypes):
        """Instantiate a complex type."""

        if base not in self.type_factories:
            raise ArgumentError("unknown complex base type specified", passed_type=typename, base_type=base)

        base_type = self.type_factories[base]

        #Make sure all of the subtypes are valid
        for sub_type in subtypes:
            try:
                self.get_type(sub_type)
            except KeyValueException as exc:
                raise ArgumentError("could not instantiate subtype for complex type", passed_type=typename, sub_type=sub_type, error=exc)

        typeobj = base_type.Build(*subtypes, type_system=self)
        self.inject_type(typename, typeobj)


def get_type(self, type_name):
        """Return the type object corresponding to a type name.

        If type_name is not found, this triggers the loading of
        external types until a matching type is found or until there
        are no more external type sources.
        """

        type_name = self._canonicalize_type(type_name)

        # Add basic transformations on common abbreviations
        if str(type_name) == 'int':
            type_name = 'integer'
        elif str(type_name) == 'str':
            type_name = 'string'
        elif str(type_name) == 'dict':
            type_name = 'basic_dict'

        if self.is_known_type(type_name):
            return self.known_types[type_name]

        base_type, is_complex, subtypes = self.split_type(type_name)
        if is_complex and base_type in self.type_factories:
            self.instantiate_type(type_name, base_type, subtypes)
            return self.known_types[type_name]

        # If we're here, this is a type that we don't know anything about, so go find it.
        i = 0
        for i, (source, name) in enumerate(self._lazy_type_sources):
            if isinstance(source, str):
                import pkg_resources

                for entry in pkg_resources.iter_entry_points(source):
                    try:
                        mod = entry.load()
                        type_system.load_type_module(mod)
                    except:  #pylint:disable=W0702; We want to catch everything here since we don't want external plugins breaking us
                        fail_info = ("Entry point group: %s, name: %s" % (source, entry.name), sys.exc_info)
                        logging.exception("Error loading external type source from entry point, group: %s, name: %s", source, entry.name)
                        self.failed_sources.append(fail_info)
            else:
                try:
                    source(self)
                except:  #pylint:disable=W0702; We want to catch everything here since we don't want external plugins breaking us
                    fail_info = ("source: %s" % name, sys.exc_info)
                    logging.exception("Error loading external type source, source: %s", source)
                    self.failed_sources.append(fail_info)

            # Only load as many external sources as we need to resolve this type_name
            if self.is_known_type(type_name) or (is_complex and base_type in self.type_factories):
                break

        self._lazy_type_sources = self._lazy_type_sources[i:]

        # If we've loaded everything and we still can't find it then there's a configuration error somewhere
        if not (self.is_known_type(type_name) or (is_complex and base_type in self.type_factories)):
            raise ArgumentError("get_type called on unknown type", type=type_name, failed_external_sources=[x[0] for x in self.failed_sources])

        return self.get_type(type_name)

Return the type object corresponding to a type name .


def is_known_format(self, type, format):
        """
        Check if format is known for given type.

        Returns boolean indicating if format is valid for the specified type.
        """

        typeobj = self.get_type(type)

        formatter = "format_%s" % str(format)
        if not hasattr(typeobj, formatter):
            return False

        return True

def is_known_format ( self , type , format ) : typeobj = self . get_type ( type ) formatter = "format_%s" % str ( format ) if not hasattr ( typeobj , formatter ) : return False return True

Check if format is known for given type .


def inject_type(self, name, typeobj):
        """
        Given a module-like object that defines a type, add it to our type system so that
        it can be used with the iotile tool and with other annotated API functions.
        """

        name = self._canonicalize_type(name)
        _, is_complex, _ = self.split_type(name)

        if self.is_known_type(name):
            raise ArgumentError("attempting to inject a type that is already defined", type=name)

        if (not is_complex) and self._is_factory(typeobj):
            if name in self.type_factories:
                raise ArgumentError("attempted to inject a complex type factory that is already defined", type=name)
            self.type_factories[name] = typeobj
        else:
            self._validate_type(typeobj)
            self.known_types[name] = typeobj

        if not hasattr(typeobj, "default_formatter"):
            raise ArgumentError("type is invalid, does not have default_formatter function", type=typeobj, methods=dir(typeobj))

Given a module - like object that defines a type add it to our type system so that it can be used with the iotile tool and with other annotated API functions .


def load_type_module(self, module):
        """
        Given a module that contains a list of some types find all symbols in the module that
        do not start with _ and attempt to import them as types.
        """

        for name in (x for x in dir(module) if not x.startswith('_')):
            typeobj = getattr(module, name)

            try:
                self.inject_type(name, typeobj)
            except ArgumentError:
                pass

def load_type_module ( self , module ) : for name in ( x for x in dir ( module ) if not x . startswith ( '_' ) ) : typeobj = getattr ( module , name ) try : self . inject_type ( name , typeobj ) except ArgumentError : pass

Given a module that contains a list of some types find all symbols in the module that do not start with _ and attempt to import them as types .


def spec_filled(self, pos_args, kw_args):
        """Check if we have enough arguments to call this function.

        Args:
            pos_args (list): A list of all the positional values we have.
            kw_args (dict): A dict of all of the keyword args we have.

        Returns:
            bool: True if we have a filled spec, False otherwise.
        """

        req_names = self.arg_names
        if len(self.arg_defaults) > 0:
            req_names = req_names[:-len(self.arg_defaults)]

        req = [x for x in req_names if x not in kw_args]
        return len(req) <= len(pos_args)

def spec_filled ( self , pos_args , kw_args ) : req_names = self . arg_names if len ( self . arg_defaults ) > 0 : req_names = req_names [ : - len ( self . arg_defaults ) ] req = [ x for x in req_names if x not in kw_args ] return len ( req ) <= len ( pos_args )

Check if we have enough arguments to call this function .


def add_param(self, name, type_name, validators, desc=None):
        """Add type information for a parameter by name.

        Args:
            name (str): The name of the parameter we wish to annotate
            type_name (str): The name of the parameter's type
            validators (list): A list of either strings or n tuples that each
                specify a validator defined for type_name.  If a string is passed,
                the validator is invoked with no extra arguments.  If a tuple is
                passed, the validator will be invoked with the extra arguments.
            desc (str): Optional parameter description.
        """

        if name in self.annotated_params:
            raise TypeSystemError("Annotation specified multiple times for the same parameter", param=name)

        if name not in self.arg_names and name != self.varargs and name != self.kwargs:
            raise TypeSystemError("Annotation specified for unknown parameter", param=name)

        info = ParameterInfo(type_name, validators, desc)
        self.annotated_params[name] = info

Add type information for a parameter by name .


def typed_returnvalue(self, type_name, formatter=None):
        """Add type information to the return value of this function.

        Args:
            type_name (str): The name of the type of the return value.
            formatter (str): An optional name of a formatting function specified
                for the type given in type_name.
        """
        self.return_info = ReturnInfo(type_name, formatter, True, None)

def typed_returnvalue ( self , type_name , formatter = None ) : self . return_info = ReturnInfo ( type_name , formatter , True , None )

Add type information to the return value of this function .


def custom_returnvalue(self, printer, desc=None):
        """Use a custom function to print the return value.

        Args:
            printer (callable): A function that should take in the return
                value and convert it to a string.
            desc (str): An optional description of the return value.
        """
        self.return_info = ReturnInfo(None, printer, True, desc)

def custom_returnvalue ( self , printer , desc = None ) : self . return_info = ReturnInfo ( None , printer , True , desc )

Use a custom function to print the return value .


def match_shortname(self, name, filled_args=None):
        """Try to convert a prefix into a parameter name.

        If the result could be ambiguous or there is no matching
        parameter, throw an ArgumentError

        Args:
            name (str): A prefix for a parameter name
            filled_args (list): A list of filled positional arguments that will be
                removed from consideration.

        Returns:
            str: The full matching parameter name
        """

        filled_count = 0
        if filled_args is not None:
            filled_count = len(filled_args)

        possible = [x for x in self.arg_names[filled_count:] if x.startswith(name)]
        if len(possible) == 0:
            raise ArgumentError("Could not convert short-name full parameter name, none could be found", short_name=name, parameters=self.arg_names)
        elif len(possible) > 1:
            raise ArgumentError("Short-name is ambiguous, could match multiple keyword parameters", short_name=name, possible_matches=possible)

        return possible[0]

Try to convert a prefix into a parameter name .


def param_type(self, name):
        """Get the parameter type information by name.

        Args:
            name (str): The full name of a parameter.

        Returns:
            str: The type name or None if no type information is given.
        """

        self._ensure_loaded()

        if name not in self.annotated_params:
            return None

        return self.annotated_params[name].type_name

def param_type ( self , name ) : self . _ensure_loaded ( ) if name not in self . annotated_params : return None return self . annotated_params [ name ] . type_name

Get the parameter type information by name .


def signature(self, name=None):
        """Return our function signature as a string.

        By default this function uses the annotated name of the function
        however if you need to override that with a custom name you can
        pass name=<custom name>

        Args:
            name (str): Optional name to override the default name given
                in the function signature.

        Returns:
            str: The formatted function signature
        """

        self._ensure_loaded()

        if name is None:
            name = self.name

        num_args = len(self.arg_names)

        num_def = 0
        if self.arg_defaults is not None:
            num_def = len(self.arg_defaults)

        num_no_def = num_args - num_def

        args = []
        for i in range(0, len(self.arg_names)):
            typestr = ""

            if self.arg_names[i] in self.annotated_params:
                typestr = "{} ".format(self.annotated_params[self.arg_names[i]].type_name)

            if i >= num_no_def:
                default = str(self.arg_defaults[i-num_no_def])
                if len(default) == 0:
                    default = "''"

                args.append("{}{}={}".format(typestr, str(self.arg_names[i]), default))
            else:
                args.append(typestr + str(self.arg_names[i]))

        return "{}({})".format(name, ", ".join(args))

def
signature
(
self
,
name
=
)
:
self
.
_ensure_loaded
(
)
if
name
is
:
name
=
self
.
name
num_args
=
len
(
self
.
arg_names
)
num_def
=
0
if
self
.
arg_defaults
is
not
:
num_def
=
len
(
self
.
arg_defaults
)
num_no_def
=
num_args
num_def
args
=
[
]
for
i
in
range
(
0
,
len
(
self
.
arg_names
)
)
:
typestr
=
""
if
self
.
arg_names
[
i
]
in
self
.
annotated_params
:
typestr
=
"{} "
.
format
(
self
.
annotated_params
[
self
.
arg_names
[
i
]
]
.
type_name
)
if
i
>=
num_no_def
:
default
=
str
(
self
.
arg_defaults
[
i
num_no_def
]
)
if
len
(
default
)
==
0
:
default
=
"''"
args
.
append
(
"{}{}={}"
.
format
(
typestr
,
str
(
self
.
arg_names
[
i
]
)
,
default
)
)
else
:
args
.
append
(
typestr
+
str
(
self
.
arg_names
[
i
]
)
)
return
"{}({})"
.
format
(
name
,
", "
.
join
(
args
)
)

Return our function signature as a string .


def format_returnvalue(self, value):
        """Format the return value of this function as a string.

        Args:
            value (object): The return value that we are supposed to format.

        Returns:
            str: The formatted return value, or None if this function indicates
                that it does not return data
        """

        self._ensure_loaded()

        if not self.return_info.is_data:
            return None

        # If the return value is typed, use the type_system to format it
        if self.return_info.type_name is not None:
            return typeinfo.type_system.format_value(value, self.return_info.type_name, self.return_info.formatter)

        # Otherwise we expect a callable function to convert this value to a string
        return self.return_info.formatter(value)

Format the return value of this function as a string .


def convert_positional_argument(self, index, arg_value):
        """Convert and validate a positional argument.

        Args:
            index (int): The positional index of the argument
            arg_value (object): The value to convert and validate

        Returns:
            object: The converted value.
        """

        # For bound methods, skip self
        if self._has_self:
            if index == 0:
                return arg_value

            index -= 1

        arg_name = self.arg_names[index]
        return self.convert_argument(arg_name, arg_value)

def
convert_positional_argument
(
self
,
index
,
arg_value
)
:
# For bound methods, skip self
if
self
.
_has_self
:
if
index
==
0
:
return
arg_value
index
-=
1
arg_name
=
self
.
arg_names
[
index
]
return
self
.
convert_argument
(
arg_name
,
arg_value
)

Convert and validate a positional argument .


def check_spec(self, pos_args, kwargs=None):
        """Check if there are any missing or duplicate arguments.

        Args:
            pos_args (list): A list of arguments that will be passed as positional
                arguments.
            kwargs (dict): A dictionary of the keyword arguments that will be passed.

        Returns:
            dict: A dictionary of argument name to argument value, pulled from either
                the value passed or the default value if no argument is passed.

        Raises:
            ArgumentError: If a positional or keyword argument does not fit in the spec.
            ValidationError: If an argument is passed twice.
        """

        if kwargs is None:
            kwargs = {}

        if self.varargs is not None or self.kwargs is not None:
            raise InternalError("check_spec cannot be called on a function that takes *args or **kwargs")

        missing = object()

        arg_vals = [missing]*len(self.arg_names)
        kw_indices = {name: i for i, name in enumerate(self.arg_names)}

        for i, arg in enumerate(pos_args):
            if i >= len(arg_vals):
                raise ArgumentError("Too many positional arguments, first excessive argument=%s" % str(arg))

            arg_vals[i] = arg

        for arg, val in kwargs.items():
            index = kw_indices.get(arg)
            if index is None:
                raise ArgumentError("Cannot find argument by name: %s" % arg)

            if arg_vals[index] is not missing:
                raise ValidationError("Argument %s passed twice" % arg)

            arg_vals[index] = val

        # Fill in any default variables if their args are missing
        if len(self.arg_defaults) > 0:
            for i in range(0, len(self.arg_defaults)):
                neg_index = -len(self.arg_defaults) + i
                if arg_vals[neg_index] is missing:
                    arg_vals[neg_index] = self.arg_defaults[i]

        # Now make sure there isn't a missing gap
        if missing in arg_vals:
            index = arg_vals.index(missing)
            raise ArgumentError("Missing a required argument (position: %d, name: %s)" % (index, self.arg_names[index]))

        return {name: val for name, val in zip(self.arg_names, arg_vals)}

Check if there are any missing or duplicate arguments .


def convert_argument(self, arg_name, arg_value):
        """Given a parameter with type information, convert and validate it.

        Args:
            arg_name (str): The name of the argument to convert and validate
            arg_value (object): The value to convert and validate

        Returns:
            object: The converted value.
        """

        self._ensure_loaded()

        type_name = self.param_type(arg_name)
        if type_name is None:
            return arg_value

        val = typeinfo.type_system.convert_to_type(arg_value, type_name)

        validators = self.annotated_params[arg_name].validators
        if len(validators) == 0:
            return val

        type_obj = typeinfo.type_system.get_type(type_name)

        # Run all of the validators that were defined for this argument.
        # If the validation fails, they will raise an exception that we convert to
        # an instance of ValidationError
        try:
            for validator_name, extra_args in validators:
                if not hasattr(type_obj, validator_name):
                    raise ValidationError("Could not find validator specified for argument", argument=arg_name, validator_name=validator_name, type=str(type_obj), method=dir(type_obj))

                validator = getattr(type_obj, validator_name)
                validator(val, *extra_args)
        except (ValueError, TypeError) as exc:
            raise ValidationError(exc.args[0], argument=arg_name, arg_value=val)

        return val

Given a parameter with type information convert and validate it .


def format(self, exclude_class=False):
        """Format this exception as a string including class name.

        Args:
            exclude_class (bool): Whether to exclude the exception class
                name when formatting this exception

        Returns:
            string: a multiline string with the message, class name and
                key value parameters passed to create the exception.
        """

        if exclude_class:
            msg = self.msg
        else:
            msg = "%s: %s" % (self.__class__.__name__, self.msg)

        if len(self.params) != 0:
            paramstring = "\n".join([str(key) + ": " + str(val) for key, val in self.params.items()])
            msg += "\nAdditional Information:\n" + paramstring

        return msg

def
format
(
self
,
exclude_class
=
False
)
:
if
exclude_class
:
msg
=
self
.
msg
else
:
msg
=
"%s: %s"
%
(
self
.
__class__
.
__name__
,
self
.
msg
)
if
len
(
self
.
params
)
!=
0
:
paramstring
=
"\n"
.
join
(
[
str
(
key
)
+
": "
+
str
(
val
)
for
key
,
val
in
self
.
params
.
items
(
)
]
)
msg
+=
"\nAdditional Information:\n"
+
paramstring
return
msg

Format this exception as a string including class name .


def to_dict(self):
        """Convert this exception to a dictionary.

        Returns:
            dist: A dictionary of information about this exception,
                Has a 'reason' key, a 'type' key  and a dictionary of params
        """

        out = {}
        out['reason'] = self.msg
        out['type'] = self.__class__.__name__
        out['params'] = self.params

        return out

def to_dict ( self ) : out = { } out [ 'reason' ] = self . msg out [ 'type' ] = self . __class__ . __name__ out [ 'params' ] = self . params return out

Convert this exception to a dictionary .


def _check_and_execute(func, *args, **kwargs):
    """
    Check the type of all parameters with type information, converting
    as appropriate and then execute the function.
    """

    convargs = []

    #Convert and validate all arguments
    for i, arg in enumerate(args):
        val = func.metadata.convert_positional_argument(i, arg)
        convargs.append(val)

    convkw = {}
    for key, val in kwargs:
        convkw[key] = func.metadata.convert_argument(key, val)

    if not func.metadata.spec_filled(convargs, convkw):
        raise ValidationError("Not enough parameters specified to call function", function=func.metadata.name, signature=func.metadata.signature())

    retval = func(*convargs, **convkw)
    return retval

Check the type of all parameters with type information converting as appropriate and then execute the function .


def _parse_validators(valids):
    """Parse a list of validator names or n-tuples, checking for errors.

    Returns:
        list((func_name, [args...])): A list of validator function names and a
            potentially empty list of optional parameters for each function.
    """

    outvals = []

    for val in valids:
        if isinstance(val, str):
            args = []
        elif len(val) > 1:
            args = val[1:]
            val = val[0]
        else:
            raise ValidationError("You must pass either an n-tuple or a string to define a validator", validator=val)

        name = "validate_%s" % str(val)
        outvals.append((name, args))

    return outvals

Parse a list of validator names or n - tuples checking for errors .


def find_all(container):
    """Find all annotated function inside of a container.

    Annotated functions are identified as those that:
    - do not start with a _ character
    - are either annotated with metadata
    - or strings that point to lazily loaded modules

    Args:
        container (object): The container to search for annotated functions.

    Returns:
        dict: A dict with all of the found functions in it.
    """

    if isinstance(container, dict):
        names = container.keys()
    else:
        names = dir(container)

    built_context = BasicContext()

    for name in names:
        # Ignore _ and __ names
        if name.startswith('_'):
            continue

        if isinstance(container, dict):
            obj = container[name]
        else:
            obj = getattr(container, name)

        # Check if this is an annotated object that should be included.  Check the type of
        # annotated to avoid issues with module imports where someone did from annotate import *
        # into the module causing an annotated symbol to be defined as a decorator

        # If we are in a dict context then strings point to lazily loaded modules so include them too.
        if isinstance(container, dict) and isinstance(obj, str):
            built_context[name] = obj
        elif hasattr(obj, 'metadata') and isinstance(getattr(obj, 'metadata'), AnnotatedMetadata):
            built_context[name] = obj

    return built_context

Find all annotated function inside of a container .


def context_from_module(module):
    """
    Given a module, create a context from all of the top level annotated
    symbols in that module.
    """

    con = find_all(module)

    if hasattr(module, "__doc__"):
        setattr(con, "__doc__", module.__doc__)

    name = module.__name__
    if hasattr(module, "_name_"):
        name = module._name_  # pylint: disable=W0212

    con = annotated(con, name)
    setattr(con, 'context', True)

    return name, con

def
context_from_module
(
module
)
:
con
=
find_all
(
module
)
if
hasattr
(
module
,
"__doc__"
)
:
setattr
(
con
,
"__doc__"
,
module
.
__doc__
)
name
=
module
.
__name__
if
hasattr
(
module
,
"_name_"
)
:
name
=
module
.
_name_
# pylint: disable=W0212
con
=
annotated
(
con
,
name
)
setattr
(
con
,
'context'
,
True
)
return
name
,
con

Given a module create a context from all of the top level annotated symbols in that module .


def get_help(func):
    """Return usage information about a context or function.

    For contexts, just return the context name and its docstring
    For functions, return the function signature as well as its
    argument types.

    Args:
        func (callable): An annotated callable function

    Returns:
        str: The formatted help text
    """

    help_text = ""
    if isinstance(func, dict):
        name = context_name(func)

        help_text = "\n" + name + "\n\n"
        doc = inspect.getdoc(func)
        if doc is not None:
            doc = inspect.cleandoc(doc)
            help_text += doc + '\n'

        return help_text

    sig = func.metadata.signature()
    doc = inspect.getdoc(func)
    if doc is not None:
        doc = inspect.cleandoc(doc)

    help_text += "\n" + sig + "\n\n"
    if doc is not None:
        help_text += doc + '\n'

    if inspect.isclass(func):
        func = func.__init__

    # If we derived the parameter annotations from a docstring,
    # don't insert a custom arguments section since it already
    # exists.
    if func.metadata.load_from_doc:
        return help_text

    help_text += "\nArguments:\n"
    for key, info in func.metadata.annotated_params.items():
        type_name = info.type_name
        desc = ""
        if info.desc is not None:
            desc = info.desc

        help_text += "  - %s (%s): %s\n" % (key, type_name, desc)

    return help_text

Return usage information about a context or function .


def param(name, type_name, *validators, **kwargs):
    """Decorate a function to give type information about its parameters.

    This function stores a type name, optional description and optional list
    of validation functions along with the decorated function it is called
    on in order to allow run time type conversions and validation.

    Args:
        name (string): name of the parameter
        type_name (string): The name of a type that will be known to the type
            system by the time this function is called for the first time.  Types
            are lazily loaded so it is not required that the type resolve correctly
            at the point in the module where this function is defined.
        validators (list(string or tuple)): A list of validators.  Each validator
            can be defined either using a string name or as an n-tuple of the form
            [name, \\*extra_args].  The name is used to look up a validator function
            of the form validate_name, which is called on the parameters value to
            determine if it is valid.  If extra_args are given, they are passed
            as extra arguments to the validator function, which is called as:

            validator(value, \\*extra_args)
        desc (string): An optional descriptioon for this parameter that must be
            passed as a keyword argument.

    Returns:
        callable: A decorated function with additional type metadata
    """

    def _param(func):
        func = annotated(func)

        valids = _parse_validators(validators)
        func.metadata.add_param(name, type_name, valids, **kwargs)

        # Only decorate the function once even if we have multiple param decorators
        if func.decorated:
            return func

        func.decorated = True
        return decorate(func, _check_and_execute)

    return _param

Decorate a function to give type information about its parameters .


def returns(desc=None, printer=None, data=True):
    """Specify how the return value of this function should be handled.

    Args:
        desc (str): A deprecated description of the return value
        printer (callable): A callable function that can format this return value
        data (bool): A deprecated parameter for specifying that this function
            returns data.
    """

    if data is False:
        raise ArgumentError("Specifying non data return type in returns is no longer supported")

    def _returns(func):
        annotated(func)
        func.custom_returnvalue(printer, desc)
        return func

    return _returns

Specify how the return value of this function should be handled .


def return_type(type_name, formatter=None):
    """Specify that this function returns a typed value.

    Args:
        type_name (str): A type name known to the global typedargs type system
        formatter (str): An optional name of a formatting function specified
            for the type given in type_name.
    """

    def _returns(func):
        annotated(func)
        func.metadata.typed_returnvalue(type_name, formatter)
        return func

    return _returns

def return_type ( type_name , formatter = None ) : def _returns ( func ) : annotated ( func ) func . metadata . typed_returnvalue ( type_name , formatter ) return func return _returns

Specify that this function returns a typed value .


def context(name=None):
    """Declare that a class defines a context.

    Contexts are for use with HierarchicalShell for discovering
    and using functionality from the command line.

    Args:
        name (str): Optional name for this context if you don't want
            to just use the class name.
    """

    def _context(cls):
        annotated(cls, name)
        cls.context = True

        return cls

    return _context

def context ( name = None ) : def _context ( cls ) : annotated ( cls , name ) cls . context = True return cls return _context

Declare that a class defines a context .


def docannotate(func):
    """Annotate a function using information from its docstring.

    The annotation actually happens at the time the function is first called
    to improve startup time.  For this function to work, the docstring must be
    formatted correctly.  You should use the typedargs pylint plugin to make
    sure there are no errors in the docstring.
    """

    func = annotated(func)
    func.metadata.load_from_doc = True

    if func.decorated:
        return func

    func.decorated = True
    return decorate(func, _check_and_execute)

def docannotate ( func ) : func = annotated ( func ) func . metadata . load_from_doc = True if func . decorated : return func func . decorated = True return decorate ( func , _check_and_execute )

Annotate a function using information from its docstring .


def annotated(func, name=None):
    """Mark a function as callable from the command line.

    This function is meant to be called as decorator.  This function
    also initializes metadata about the function's arguments that is
    built up by the param decorator.

    Args:
        func (callable): The function that we wish to mark as callable
            from the command line.
        name (str): Optional string that will override the function's
            built-in name.
    """

    if hasattr(func, 'metadata'):
        if name is not None:
            func.metadata = AnnotatedMetadata(func, name)
        return func

    func.metadata = AnnotatedMetadata(func, name)

    func.finalizer = False
    func.takes_cmdline = False
    func.decorated = False
    func.context = False

    return func

def annotated ( func , name = None ) : if hasattr ( func , 'metadata' ) : if name is not None : func . metadata = AnnotatedMetadata ( func , name ) return func func . metadata = AnnotatedMetadata ( func , name ) func . finalizer = False func . takes_cmdline = False func . decorated = False func . context = False return func

Mark a function as callable from the command line .


def short_description(func):
    """
    Given an object with a docstring, return the first line of the docstring
    """

    doc = inspect.getdoc(func)
    if doc is not None:
        doc = inspect.cleandoc(doc)
        lines = doc.splitlines()
        return lines[0]

    return ""

def short_description ( func ) : doc = inspect . getdoc ( func ) if doc is not None : doc = inspect . cleandoc ( doc ) lines = doc . splitlines ( ) return lines [ 0 ] return ""

Given an object with a docstring return the first line of the docstring


def load():
    """
    Load ``cron`` modules for applications listed in ``INSTALLED_APPS``.
    """
    autodiscover_modules('cron')

    if PROJECT_MODULE:
        if '.' in PROJECT_MODULE.__name__:
            try:
                import_module('%s.cron' % '.'.join(
                    PROJECT_MODULE.__name__.split('.')[0:-1]))
            except ImportError as e:
                if 'No module named' not in str(e):
                    print(e)

    # load django tasks
    for cmd, app in get_commands().items():
        try:
            load_command_class(app, cmd)
        except django.core.exceptions.ImproperlyConfigured:
            pass

def
load
(
)
:
autodiscover_modules
(
'cron'
)
if
PROJECT_MODULE
:
if
'.'
in
PROJECT_MODULE
.
__name__
:
try
:
import_module
(
'%s.cron'
%
'.'
.
join
(
PROJECT_MODULE
.
__name__
.
split
(
'.'
)
[
0
:
1
]
)
)
except
ImportError
as
e
:
if
'No module named'
not
in
str
(
e
)
:
print
(
e
)
# load django tasks
for
cmd
,
app
in
get_commands
(
)
.
items
(
)
:
try
:
load_command_class
(
app
,
cmd
)
except
django
.
core
.
exceptions
.
ImproperlyConfigured
:
pass

Load cron modules for applications listed in INSTALLED_APPS .


def install():
    """
    Register tasks with cron.
    """
    load()
    tab = crontab.CronTab(user=True)
    for task in registry:
        tab.new(task.command, KRONOS_BREADCRUMB).setall(task.schedule)
    tab.write()
    return len(registry)

def install ( ) : load ( ) tab = crontab . CronTab ( user = True ) for task in registry : tab . new ( task . command , KRONOS_BREADCRUMB ) . setall ( task . schedule ) tab . write ( ) return len ( registry )


def printtasks():
    """
    Print the tasks that would be installed in the
    crontab, for debugging purposes.
    """
    load()

    tab = crontab.CronTab('')
    for task in registry:
        tab.new(task.command, KRONOS_BREADCRUMB).setall(task.schedule)
    print(tab.render())

def printtasks ( ) : load ( ) tab = crontab . CronTab ( '' ) for task in registry : tab . new ( task . command , KRONOS_BREADCRUMB ) . setall ( task . schedule ) print ( tab . render ( ) )

Print the tasks that would be installed in the crontab for debugging purposes .


def uninstall():
    """
    Uninstall tasks from cron.
    """
    tab = crontab.CronTab(user=True)
    count = len(list(tab.find_comment(KRONOS_BREADCRUMB)))
    tab.remove_all(comment=KRONOS_BREADCRUMB)
    tab.write()
    return count

def uninstall ( ) : tab = crontab . CronTab ( user = True ) count = len ( list ( tab . find_comment ( KRONOS_BREADCRUMB ) ) ) tab . remove_all ( comment = KRONOS_BREADCRUMB ) tab . write ( ) return count


def create(self, uri, local_path):
        """Create a project handler

        Args:
            uri (str): schema://something formatted uri
            local_path (str): the project configs directory

        Return:
            ProjectHandler derived class instance
        """
        matches = self.schema_pattern.search(uri)

        if not matches:
            logger.error("Unknown uri schema: '%s'. Added schemas: %s", uri, list(self.handlers.keys()))
            return None

        schema = matches.group(1)
        url = matches.group(2)

        return self.handlers[schema](url, local_path)


def load(self):
        """Load the projects config data from local path

        Returns:
            Dict: project_name -> project_data
        """
        projects = {}

        path = os.path.expanduser(self.path)

        if not os.path.isdir(path):
            return projects

        logger.debug("Load project configs from %s", path)

        for filename in os.listdir(path):
            filename_parts = os.path.splitext(filename)

            if filename_parts[1][1:] != PROJECT_CONFIG_EXTENSION:
                continue
            name = filename_parts[0]

            try:
                project_file_path = os.path.join(path, filename)
                with open(project_file_path) as f:
                    data = yaml.load(f)
                projects[name] = data
            except ValueError:
                continue

            logger.debug("Project '{}' config readed from {}".format(name, project_file_path))

        return projects

def
load
(
self
)
:
projects
=
{
}
path
=
os
.
path
.
expanduser
(
self
.
path
)
if
not
os
.
path
.
isdir
(
path
)
:
return
projects
logger
.
debug
(
"Load project configs from %s"
,
path
)
for
filename
in
os
.
listdir
(
path
)
:
filename_parts
=
os
.
path
.
splitext
(
filename
)
if
filename_parts
[
1
]
[
1
:
]
!=
PROJECT_CONFIG_EXTENSION
:
continue
name
=
filename_parts
[
0
]
try
:
project_file_path
=
os
.
path
.
join
(
path
,
filename
)
with
open
(
project_file_path
)
as
f
:
data
=
yaml
.
load
(
f
)
projects
[
name
]
=
data
except
ValueError
:
continue
logger
.
debug
(
"Project '{}' config readed from {}"
.
format
(
name
,
project_file_path
)
)
return
projects


def save(self, projects):
        """Save the projects configs to local path

        Args:
            projects (dict): project_name -> project_data
        """

        base_path = os.path.expanduser(self.path)

        if not os.path.isdir(base_path):
            return

        logger.debug("Save projects config to %s", base_path)

        for name, data in list(projects.items()):
            project_file_path = self.get_project_config_path(name)
            with open(project_file_path, "w") as f:
                yaml.dump(data, stream = f, default_flow_style = False)
                logger.debug("Project '%s' config has been writed to '%s'", name, project_file_path)


def define_singleton(carrier, name, cls, cls_args = {}):
    """Creates a property with the given name, but the cls will created only with the first call

    Args:
        carrier: an instance of the class where want to reach the cls instance
        name (str): the variable name of the cls instance
        cls (type): the singleton object type
        cls_args (dict): optional dict for createing cls

    """
    instance_name = "__{}".format(name)
    setattr(carrier, instance_name, None)

    def getter(self):
        instance = getattr(carrier, instance_name)

        if instance is None:
            instance = cls(**cls_args)
            setattr(carrier, instance_name, instance)

        return instance

    setattr(type(carrier), name, property(getter))

def define_singleton ( carrier , name , cls , cls_args = { } ) : instance_name = "__{}" . format ( name ) setattr ( carrier , instance_name , None ) def getter ( self ) : instance = getattr ( carrier , instance_name ) if instance is None : instance = cls ( * * cls_args ) setattr ( carrier , instance_name , instance ) return instance setattr ( type ( carrier ) , name , property ( getter ) )

Creates a property with the given name but the cls will created only with the first call


def get_dependent_projects(self, recursive = True):
        """Get the dependencies of the Project

        Args:
            recursive (bool): add the dependant project's dependencies too

        Returns:
            dict of project name and project instances
        """
        projects = {}
        for name, ref in list(self.dependencies.items()):
            try:
                prj = self.vcp.projects[name]
            except KeyError:
                logger.error("Unknown project '%s' in project '%s' dependencies!", name, self.name)
                continue
            projects[name] = prj
            if recursive:
                projects.update(prj.get_dependent_projects())
        return projects


def post_process(func):
    """Calls the project handler same named function

    Note: the project handler may add some extra arguments to the command,
          so when use this decorator, add **kwargs to the end of the arguments

    """
    @wraps(func)
    def wrapper(*args, **kwargs):
        res = func(*args, **kwargs)
        project_command = args[0]
        project_handler = project_command.vcp.project_handler
        if not project_handler:
            return res
        kwargs['command_result'] = res
        getattr(project_handler, func.__name__)(**kwargs)
        return res

    return wrapper

def post_process ( func ) : @ wraps ( func ) def wrapper ( * args , * * kwargs ) : res = func ( * args , * * kwargs ) project_command = args [ 0 ] project_handler = project_command . vcp . project_handler if not project_handler : return res kwargs [ 'command_result' ] = res getattr ( project_handler , func . __name__ ) ( * * kwargs ) return res return wrapper


def __init(self, project, path, force, init_languages):
        status = {}
        """
        REFACTOR status to project init result ENUM
        jelenleg ha a project init False, akkor torlunk minden adatot a projectrol
        de van egy atmenet, mikor csak a lang init nem sikerult
        erre valo jelenleg a status. ez rossz
        """

        project.init(path, status, force, init_languages = init_languages)

        failed = []
        for name, val in list(status.items()):
            if val is False and name not in failed:
                failed.append(name)

        return failed

def __init ( self , project , path , force , init_languages ) : status = { } project . init ( path , status , force , init_languages = init_languages ) failed = [ ] for name , val in list ( status . items ( ) ) : if val is False and name not in failed : failed . append ( name ) return failed

REFACTOR status to project init result ENUM jelenleg ha a project init False akkor torlunk minden adatot a projectrol de van egy atmenet mikor csak a lang init nem sikerult erre valo jelenleg a status . ez rossz


def setitem(self, key, value):
    # type: (Any, Any, Any) -> Any
    '''Takes an object, a key, and a value and produces a new object
    that is a copy of the original but with ``value`` as the new value of
    ``key``.

    The following equality should hold for your definition:

    .. code-block:: python

        setitem(obj, key, obj[key]) == obj

    This function is used by many lenses (particularly GetitemLens) to
    set items on states even when those states do not ordinarily support
    ``setitem``. This function is designed to have a similar signature
    as python's built-in ``setitem`` except that it returns a new object
    that has the item set rather than mutating the object in place.

    It's what enables the ``lens[some_key]`` functionality.

    The corresponding method call for this hook is
    ``obj._lens_setitem(key, value)``.

    The default implementation makes a copy of the object using
    ``copy.copy`` and then mutates the new object by setting the item
    on it in the conventional way.
    '''
    try:
        self._lens_setitem
    except AttributeError:
        selfcopy = copy.copy(self)
        selfcopy[key] = value
        return selfcopy
    else:
        return self._lens_setitem(key, value)

def
setitem
(
self
,
key
,
value
)
:
# type: (Any, Any, Any) -> Any
try
:
self
.
_lens_setitem
except
AttributeError
:
selfcopy
=
copy
.
copy
(
self
)
selfcopy
[
key
]
=
value
return
selfcopy
else
:
return
self
.
_lens_setitem
(
key
,
value
)

Takes an object a key and a value and produces a new object that is a copy of the original but with value as the new value of key .


def setattr(self, name, value):
    # type: (Any, Any, Any) -> Any
    '''Takes an object, a string, and a value and produces a new object
    that is a copy of the original but with the attribute called ``name``
    set to ``value``.

    The following equality should hold for your definition:

    .. code-block:: python

        setattr(obj, 'attr', obj.attr) == obj

    This function is used by many lenses (particularly GetattrLens) to set
    attributes on states even when those states do not ordinarily support
    ``setattr``. This function is designed to have a similar signature
    as python's built-in ``setattr`` except that it returns a new object
    that has the attribute set rather than mutating the object in place.

    It's what enables the ``lens.some_attribute`` functionality.

    The corresponding method call for this hook is
    ``obj._lens_setattr(name, value)``.

    The default implementation makes a copy of the object using
    ``copy.copy`` and then mutates the new object by calling python's
    built in ``setattr`` on it.
    '''
    try:
        self._lens_setattr
    except AttributeError:
        selfcopy = copy.copy(self)
        builtin_setattr(selfcopy, name, value)
        return selfcopy
    else:
        return self._lens_setattr(name, value)

def
setattr
(
self
,
name
,
value
)
:
# type: (Any, Any, Any) -> Any
try
:
self
.
_lens_setattr
except
AttributeError
:
selfcopy
=
copy
.
copy
(
self
)
builtin_setattr
(
selfcopy
,
name
,
value
)
return
selfcopy
else
:
return
self
.
_lens_setattr
(
name
,
value
)

Takes an object a string and a value and produces a new object that is a copy of the original but with the attribute called name set to value .


def from_iter(self, iterable):
    # type: (Any, Any) -> Any
    '''Takes an object and an iterable and produces a new object that is
    a copy of the original with data from ``iterable`` reincorporated. It
    is intended as the inverse of the ``to_iter`` function. Any state in
    ``self`` that is not modelled by the iterable should remain unchanged.

    The following equality should hold for your definition:

    .. code-block:: python

        from_iter(self, to_iter(self)) == self

    This function is used by EachLens to synthesise states from iterables,
    allowing it to focus every element of an iterable state.

    The corresponding method call for this hook is
    ``obj._lens_from_iter(iterable)``.

    There is no default implementation.
    '''
    try:
        self._lens_from_iter
    except AttributeError:
        message = 'Don\'t know how to create instance of {} from iterable'
        raise NotImplementedError(message.format(type(self)))
    else:
        return self._lens_from_iter(iterable)

Takes an object and an iterable and produces a new object that is a copy of the original with data from iterable reincorporated . It is intended as the inverse of the to_iter function . Any state in self that is not modelled by the iterable should remain unchanged .


def set(self, newvalue):
        # type: (B) -> Callable[[S], T]
        '''Set the focus to `newvalue`.

            >>> from lenses import lens
            >>> set_item_one_to_four = lens[1].set(4)
            >>> set_item_one_to_four([1, 2, 3])
            [1, 4, 3]
        '''

        def setter(state):
            return self._optic.set(state, newvalue)

        return setter

def
set
(
self
,
newvalue
)
:
# type: (B) -> Callable[[S], T]
def
setter
(
state
)
:
return
self
.
_optic
.
set
(
state
,
newvalue
)
return
setter


def set_many(self, new_values):
        # type: (Iterable[B]) -> Callable[[S], T]
        '''Set many foci to values taken by iterating over `new_values`.

            >>> from lenses import lens
            >>> lens.Each().set_many(range(4, 7))([0, 1, 2])
            [4, 5, 6]
        '''

        def setter_many(state):
            return self._optic.iterate(state, new_values)

        return setter_many

Set many foci to values taken by iterating over new_values .


def modify(self, func):
        # type: (Callable[[A], B]) -> Callable[[S], T]
        '''Apply a function to the focus.

            >>> from lenses import lens
            >>> convert_item_one_to_string = lens[1].modify(str)
            >>> convert_item_one_to_string([1, 2, 3])
            [1, '2', 3]
            >>> add_ten_to_item_one = lens[1].modify(lambda n: n + 10)
            >>> add_ten_to_item_one([1, 2, 3])
            [1, 12, 3]
        '''

        def modifier(state):
            return self._optic.over(state, func)

        return modifier


def collect_args(n):
    '''Returns a function that can be called `n` times with a single
    argument before returning all the args that have been passed to it
    in a tuple. Useful as a substitute for functions that can't easily be
    curried.

        >>> collect_args(3)(1)(2)(3)
        (1, 2, 3)
    '''
    args = []

    def arg_collector(arg):
        args.append(arg)
        if len(args) == n:
            return tuple(args)
        else:
            return arg_collector

    return arg_collector

def collect_args ( n ) : args = [ ] def arg_collector ( arg ) : args . append ( arg ) if len ( args ) == n : return tuple ( args ) else : return arg_collector return arg_collector

Returns a function that can be called n times with a single argument before returning all the args that have been passed to it in a tuple . Useful as a substitute for functions that can t easily be curried .


def func(self, f, state):
        '''Intended to be overridden by subclasses. Raises
        NotImplementedError.'''
        message = 'Tried to use unimplemented lens {}.'
        raise NotImplementedError(message.format(type(self)))

def
func
(
self
,
f
,
state
)
:
message
=
'Tried to use unimplemented lens {}.'
raise
NotImplementedError
(
message
.
format
(
type
(
self
)
)
)

Intended to be overridden by subclasses . Raises NotImplementedError .


def apply(self, f, pure, state):
        '''Runs the lens over the `state` applying `f` to all the foci
        collecting the results together using the applicative functor
        functions defined in `lenses.typeclass`. `f` must return an
        applicative functor. For the case when no focus exists you must
        also provide a `pure` which should take a focus and return the
        pure form of the functor returned by `f`.
        '''
        return self.func(Functorisor(pure, f), state)

def apply ( self , f , pure , state ) : return self . func ( Functorisor ( pure , f ) , state )

Runs the lens over the state applying f to all the foci collecting the results together using the applicative functor functions defined in lenses . typeclass . f must return an applicative functor . For the case when no focus exists you must also provide a pure which should take a focus and return the pure form of the functor returned by f .


def view(self, state):
        # type: (S) -> B
        '''Returns the focus within `state`. If multiple items are
        focused then it will attempt to join them together as a monoid.
        See `lenses.typeclass.mappend`.

        Requires kind Fold. This method will raise TypeError if the
        optic has no way to get any foci.

        For technical reasons, this method requires there to be at least
        one foci at the end of the view. It will raise ValueError when
        there is none.
        '''
        if not self._is_kind(Fold):
            raise TypeError('Must be an instance of Fold to .view()')

        guard = object()
        result = self.preview(state).maybe(guard)
        if result is guard:
            raise ValueError('No focus to view')
        return cast(B, result)

Returns the focus within state . If multiple items are focused then it will attempt to join them together as a monoid . See lenses . typeclass . mappend .


def to_list_of(self, state):
        # type: (S) -> List[B]
        '''Returns a list of all the foci within `state`.

        Requires kind Fold. This method will raise TypeError if the
        optic has no way to get any foci.
        '''
        if not self._is_kind(Fold):
            raise TypeError('Must be an instance of Fold to .to_list_of()')

        pure = lambda a: Const([])
        func = lambda a: Const([a])
        return self.apply(func, pure, state).unwrap()

Returns a list of all the foci within state .


def over(self, state, fn):
        # type: (S, Callable[[A], B]) -> T
        '''Applies a function `fn` to all the foci within `state`.

        Requires kind Setter. This method will raise TypeError when the
        optic has no way to set foci.
        '''
        if not self._is_kind(Setter):
            raise TypeError('Must be an instance of Setter to .over()')

        pure = lambda a: Identity(a)
        func = lambda a: Identity(fn(a))
        return self.apply(func, pure, state).unwrap()

Applies a function fn to all the foci within state .


def set(self, state, value):
        # type: (S, B) -> T
        '''Sets all the foci within `state` to `value`.

        Requires kind Setter. This method will raise TypeError when the
        optic has no way to set foci.
        '''
        if not self._is_kind(Setter):
            raise TypeError('Must be an instance of Setter to .set()')

        pure = lambda a: Identity(a)
        func = lambda a: Identity(value)
        return self.apply(func, pure, state).unwrap()

Sets all the foci within state to value .


def iterate(self, state, iterable):
        # type: (S, Iterable[B]) -> T
        '''Sets all the foci within `state` to values taken from `iterable`.

        Requires kind Setter. This method will raise TypeError when the
        optic has no way to set foci.
        '''
        if not self._is_kind(Setter):
            raise TypeError('Must be an instance of Setter to .iterate()')

        i = iter(iterable)
        pure = lambda a: Identity(a)
        func = lambda a: Identity(next(i))
        return self.apply(func, pure, state).unwrap()

Sets all the foci within state to values taken from iterable .


def kind(self):
        '''Returns a class representing the 'kind' of optic.'''
        optics = [
            Equality,
            Isomorphism,
            Prism,
            Review,
            Lens,
            Traversal,
            Getter,
            Setter,
            Fold,
        ]
        for optic in optics:
            if self._is_kind(optic):
                return optic

def kind ( self ) : optics = [ Equality , Isomorphism , Prism , Review , Lens , Traversal , Getter , Setter , Fold , ] for optic in optics : if self . _is_kind ( optic ) : return optic

Returns a class representing the kind of optic .


def main():
    '''The main function. Instantiates a GameState object and then
    enters a REPL-like main loop, waiting for input, updating the state
    based on the input, then outputting the new state.'''

    state = GameState()
    print(state)
    while state.running:
        input = get_single_char()

        state, should_advance = state.handle_input(input)
        if should_advance:
            state = state.advance_robots()
            state = state.check_game_end()

        print(state)

    print(state.message)

def main ( ) : state = GameState ( ) print ( state ) while state . running : input = get_single_char ( ) state , should_advance = state . handle_input ( input ) if should_advance : state = state . advance_robots ( ) state = state . check_game_end ( ) print ( state ) print ( state . message )

The main function . Instantiates a GameState object and then enters a REPL - like main loop waiting for input updating the state based on the input then outputting the new state .


def step_towards(self, other):
        '''returns the vector moved one step in the direction of the
        other, potentially diagonally.'''

        return self + Vector(
            (
                (self[0] < other[0]) - (self[0] > other[0]),
                (self[1] < other[1]) - (self[1] > other[1]),
            )
        )

def step_towards ( self , other ) : return self + Vector ( ( ( self [ 0 ] < other [ 0 ] ) - ( self [ 0 ] > other [ 0 ] ) , ( self [ 1 ] < other [ 1 ] ) - ( self [ 1 ] > other [ 1 ] ) , ) )

returns the vector moved one step in the direction of the other potentially diagonally .


def handle_input(self, input):
        '''Takes a single character string as input and alters the game
        state according to that input. Mostly, this means moving the
        player around. Returns a new game state and boolean indicating
        whether the input had an effect on the state.'''

        dirs = {
            'h': (-1, 0),
            'j': (0, 1),
            'k': (0, -1),
            'l': (1, 0),
            'y': (-1, -1),
            'u': (1, -1),
            'n': (1, 1),
            'b': (-1, 1),
        }

        if input in dirs:
            new_self = (lens.player + dirs[input])(self)
            if not new_self.player.inside():
                return self, False
            return new_self, True
        elif input == '.':
            return self, True
        elif input == 'q':
            return self.end_game(), False
        elif input == 't':
            self = lens.player.set(Vector.random())(self)
            return self, True
        else:
            return self, False

def handle_input ( self , input ) : dirs = { 'h' : ( - 1 , 0 ) , 'j' : ( 0 , 1 ) , 'k' : ( 0 , - 1 ) , 'l' : ( 1 , 0 ) , 'y' : ( - 1 , - 1 ) , 'u' : ( 1 , - 1 ) , 'n' : ( 1 , 1 ) , 'b' : ( - 1 , 1 ) , } if input in dirs : new_self = ( lens . player + dirs [ input ] ) ( self ) if not new_self . player . inside ( ) : return self , False return new_self , True elif input == '.' : return self , True elif input == 'q' : return self . end_game ( ) , False elif input == 't' : self = lens . player . set ( Vector . random ( ) ) ( self ) return self , True else : return self , False

Takes a single character string as input and alters the game state according to that input . Mostly this means moving the player around . Returns a new game state and boolean indicating whether the input had an effect on the state .