[taurus] 02/04: New upstream version 4.0.3+dfsg

Frédéric-Emmanuel Picca picca at moszumanska.debian.org
Mon Jan 23 19:12:50 UTC 2017


This is an automated email from the git hooks/post-receive script.

picca pushed a commit to branch master
in repository taurus.

commit cfb3ec16e6b54dea7f5b6b18ede9b71092bd5184
Author: Picca Frédéric-Emmanuel <picca at debian.org>
Date:   Mon Jan 23 18:31:56 2017 +0100

    New upstream version 4.0.3+dfsg
---
 lib/taurus/external/argparse/LICENSE.txt           |   20 -
 lib/taurus/external/argparse/argparse_local.py     | 2362 --------------------
 lib/taurus/external/enum/enum/__init__.py          |  809 -------
 lib/taurus/external/ordereddict/ordereddict.py     |  153 --
 lib/taurus/external/pint/pint_local/AUTHORS        |   41 -
 lib/taurus/external/pint/pint_local/LICENSE        |   33 -
 lib/taurus/external/pint/pint_local/__init__.py    |  126 --
 .../external/pint/pint_local/compat/__init__.py    |  129 --
 .../external/pint/pint_local/compat/chainmap.py    |  153 --
 .../external/pint/pint_local/compat/lrucache.py    |  177 --
 .../external/pint/pint_local/compat/nullhandler.py |   32 -
 .../external/pint/pint_local/compat/tokenize.py    |  640 ------
 .../external/pint/pint_local/constants_en.txt      |   51 -
 lib/taurus/external/pint/pint_local/context.py     |  239 --
 lib/taurus/external/pint/pint_local/converters.py  |   82 -
 lib/taurus/external/pint/pint_local/default_en.txt |  377 ----
 lib/taurus/external/pint/pint_local/definitions.py |  157 --
 lib/taurus/external/pint/pint_local/errors.py      |  113 -
 lib/taurus/external/pint/pint_local/formatting.py  |  200 --
 lib/taurus/external/pint/pint_local/measurement.py |   99 -
 lib/taurus/external/pint/pint_local/pint_eval.py   |  258 ---
 lib/taurus/external/pint/pint_local/quantity.py    | 1337 -----------
 lib/taurus/external/pint/pint_local/systems.py     |  423 ----
 lib/taurus/external/pint/pint_local/unit.py        | 1375 ------------
 lib/taurus/external/pint/pint_local/util.py        |  643 ------
 setup.cfg                                          |    1 +
 26 files changed, 1 insertion(+), 10029 deletions(-)

diff --git a/lib/taurus/external/argparse/LICENSE.txt b/lib/taurus/external/argparse/LICENSE.txt
deleted file mode 100644
index 640bc78..0000000
--- a/lib/taurus/external/argparse/LICENSE.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-argparse is (c) 2006-2009 Steven J. Bethard <steven.bethard at gmail.com>.
-
-The argparse module was contributed to Python as of Python 2.7 and thus
-was licensed under the Python license. Same license applies to all files in
-the argparse package project.
-
-For details about the Python License, please see doc/Python-License.txt.
-
-History
--------
-
-Before (and including) argparse 1.1, the argparse package was licensed under
-Apache License v2.0.
-
-After argparse 1.1, all project files from the argparse project were deleted
-due to license compatibility issues between Apache License 2.0 and GNU GPL v2.
-
-The project repository then had a clean start with some files taken from
-Python 2.7.1, so definitely all files are under Python License now.
-
diff --git a/lib/taurus/external/argparse/argparse_local.py b/lib/taurus/external/argparse/argparse_local.py
deleted file mode 100644
index 32d948c..0000000
--- a/lib/taurus/external/argparse/argparse_local.py
+++ /dev/null
@@ -1,2362 +0,0 @@
-# Author: Steven J. Bethard <steven.bethard at gmail.com>.
-
-"""Command-line parsing library
-
-This module is an optparse-inspired command-line parsing library that:
-
-    - handles both optional and positional arguments
-    - produces highly informative usage messages
-    - supports parsers that dispatch to sub-parsers
-
-The following is a simple usage example that sums integers from the
-command-line and writes the result to a file::
-
-    parser = argparse.ArgumentParser(
-        description='sum the integers at the command line')
-    parser.add_argument(
-        'integers', metavar='int', nargs='+', type=int,
-        help='an integer to be summed')
-    parser.add_argument(
-        '--log', default=sys.stdout, type=argparse.FileType('w'),
-        help='the file where the sum should be written')
-    args = parser.parse_args()
-    args.log.write('%s' % sum(args.integers))
-    args.log.close()
-
-The module contains the following public classes:
-
-    - ArgumentParser -- The main entry point for command-line parsing. As the
-        example above shows, the add_argument() method is used to populate
-        the parser with actions for optional and positional arguments. Then
-        the parse_args() method is invoked to convert the args at the
-        command-line into an object with attributes.
-
-    - ArgumentError -- The exception raised by ArgumentParser objects when
-        there are errors with the parser's actions. Errors raised while
-        parsing the command-line are caught by ArgumentParser and emitted
-        as command-line messages.
-
-    - FileType -- A factory for defining types of files to be created. As the
-        example above shows, instances of FileType are typically passed as
-        the type= argument of add_argument() calls.
-
-    - Action -- The base class for parser actions. Typically actions are
-        selected by passing strings like 'store_true' or 'append_const' to
-        the action= argument of add_argument(). However, for greater
-        customization of ArgumentParser actions, subclasses of Action may
-        be defined and passed as the action= argument.
-
-    - HelpFormatter, RawDescriptionHelpFormatter, RawTextHelpFormatter,
-        ArgumentDefaultsHelpFormatter -- Formatter classes which
-        may be passed as the formatter_class= argument to the
-        ArgumentParser constructor. HelpFormatter is the default,
-        RawDescriptionHelpFormatter and RawTextHelpFormatter tell the parser
-        not to change the formatting for help text, and
-        ArgumentDefaultsHelpFormatter adds information about argument defaults
-        to the help.
-
-All other classes in this module are considered implementation details.
-(Also note that HelpFormatter and RawDescriptionHelpFormatter are only
-considered public as object names -- the API of the formatter objects is
-still considered an implementation detail.)
-"""
-
-__version__ = '1.2.1'
-__all__ = [
-    'ArgumentParser',
-    'ArgumentError',
-    'ArgumentTypeError',
-    'FileType',
-    'HelpFormatter',
-    'ArgumentDefaultsHelpFormatter',
-    'RawDescriptionHelpFormatter',
-    'RawTextHelpFormatter',
-    'Namespace',
-    'Action',
-    'ONE_OR_MORE',
-    'OPTIONAL',
-    'PARSER',
-    'REMAINDER',
-    'SUPPRESS',
-    'ZERO_OR_MORE',
-]
-
-
-import copy as _copy
-import os as _os
-import re as _re
-import sys as _sys
-import textwrap as _textwrap
-
-from gettext import gettext as _
-
-try:
-    set
-except NameError:
-    # for python < 2.4 compatibility (sets module is there since 2.3):
-    from sets import Set as set
-
-try:
-    basestring
-except NameError:
-    basestring = str
-
-try:
-    sorted
-except NameError:
-    # for python < 2.4 compatibility:
-    def sorted(iterable, reverse=False):
-        result = list(iterable)
-        result.sort()
-        if reverse:
-            result.reverse()
-        return result
-
-
-def _callable(obj):
-    return hasattr(obj, '__call__') or hasattr(obj, '__bases__')
-
-
-SUPPRESS = '==SUPPRESS=='
-
-OPTIONAL = '?'
-ZERO_OR_MORE = '*'
-ONE_OR_MORE = '+'
-PARSER = 'A...'
-REMAINDER = '...'
-_UNRECOGNIZED_ARGS_ATTR = '_unrecognized_args'
-
-# =============================
-# Utility functions and classes
-# =============================
-
-class _AttributeHolder(object):
-    """Abstract base class that provides __repr__.
-
-    The __repr__ method returns a string in the format::
-        ClassName(attr=name, attr=name, ...)
-    The attributes are determined either by a class-level attribute,
-    '_kwarg_names', or by inspecting the instance __dict__.
-    """
-
-    def __repr__(self):
-        type_name = type(self).__name__
-        arg_strings = []
-        for arg in self._get_args():
-            arg_strings.append(repr(arg))
-        for name, value in self._get_kwargs():
-            arg_strings.append('%s=%r' % (name, value))
-        return '%s(%s)' % (type_name, ', '.join(arg_strings))
-
-    def _get_kwargs(self):
-        return sorted(self.__dict__.items())
-
-    def _get_args(self):
-        return []
-
-
-def _ensure_value(namespace, name, value):
-    if getattr(namespace, name, None) is None:
-        setattr(namespace, name, value)
-    return getattr(namespace, name)
-
-
-# ===============
-# Formatting Help
-# ===============
-
-class HelpFormatter(object):
-    """Formatter for generating usage messages and argument help strings.
-
-    Only the name of this class is considered a public API. All the methods
-    provided by the class are considered an implementation detail.
-    """
-
-    def __init__(self,
-                 prog,
-                 indent_increment=2,
-                 max_help_position=24,
-                 width=None):
-
-        # default setting for width
-        if width is None:
-            try:
-                width = int(_os.environ['COLUMNS'])
-            except (KeyError, ValueError):
-                width = 80
-            width -= 2
-
-        self._prog = prog
-        self._indent_increment = indent_increment
-        self._max_help_position = max_help_position
-        self._width = width
-
-        self._current_indent = 0
-        self._level = 0
-        self._action_max_length = 0
-
-        self._root_section = self._Section(self, None)
-        self._current_section = self._root_section
-
-        self._whitespace_matcher = _re.compile(r'\s+')
-        self._long_break_matcher = _re.compile(r'\n\n\n+')
-
-    # ===============================
-    # Section and indentation methods
-    # ===============================
-    def _indent(self):
-        self._current_indent += self._indent_increment
-        self._level += 1
-
-    def _dedent(self):
-        self._current_indent -= self._indent_increment
-        assert self._current_indent >= 0, 'Indent decreased below 0.'
-        self._level -= 1
-
-    class _Section(object):
-
-        def __init__(self, formatter, parent, heading=None):
-            self.formatter = formatter
-            self.parent = parent
-            self.heading = heading
-            self.items = []
-
-        def format_help(self):
-            # format the indented section
-            if self.parent is not None:
-                self.formatter._indent()
-            join = self.formatter._join_parts
-            for func, args in self.items:
-                func(*args)
-            item_help = join([func(*args) for func, args in self.items])
-            if self.parent is not None:
-                self.formatter._dedent()
-
-            # return nothing if the section was empty
-            if not item_help:
-                return ''
-
-            # add the heading if the section was non-empty
-            if self.heading is not SUPPRESS and self.heading is not None:
-                current_indent = self.formatter._current_indent
-                heading = '%*s%s:\n' % (current_indent, '', self.heading)
-            else:
-                heading = ''
-
-            # join the section-initial newline, the heading and the help
-            return join(['\n', heading, item_help, '\n'])
-
-    def _add_item(self, func, args):
-        self._current_section.items.append((func, args))
-
-    # ========================
-    # Message building methods
-    # ========================
-    def start_section(self, heading):
-        self._indent()
-        section = self._Section(self, self._current_section, heading)
-        self._add_item(section.format_help, [])
-        self._current_section = section
-
-    def end_section(self):
-        self._current_section = self._current_section.parent
-        self._dedent()
-
-    def add_text(self, text):
-        if text is not SUPPRESS and text is not None:
-            self._add_item(self._format_text, [text])
-
-    def add_usage(self, usage, actions, groups, prefix=None):
-        if usage is not SUPPRESS:
-            args = usage, actions, groups, prefix
-            self._add_item(self._format_usage, args)
-
-    def add_argument(self, action):
-        if action.help is not SUPPRESS:
-
-            # find all invocations
-            get_invocation = self._format_action_invocation
-            invocations = [get_invocation(action)]
-            for subaction in self._iter_indented_subactions(action):
-                invocations.append(get_invocation(subaction))
-
-            # update the maximum item length
-            invocation_length = max([len(s) for s in invocations])
-            action_length = invocation_length + self._current_indent
-            self._action_max_length = max(self._action_max_length,
-                                          action_length)
-
-            # add the item to the list
-            self._add_item(self._format_action, [action])
-
-    def add_arguments(self, actions):
-        for action in actions:
-            self.add_argument(action)
-
-    # =======================
-    # Help-formatting methods
-    # =======================
-    def format_help(self):
-        help = self._root_section.format_help()
-        if help:
-            help = self._long_break_matcher.sub('\n\n', help)
-            help = help.strip('\n') + '\n'
-        return help
-
-    def _join_parts(self, part_strings):
-        return ''.join([part
-                        for part in part_strings
-                        if part and part is not SUPPRESS])
-
-    def _format_usage(self, usage, actions, groups, prefix):
-        if prefix is None:
-            prefix = _('usage: ')
-
-        # if usage is specified, use that
-        if usage is not None:
-            usage = usage % dict(prog=self._prog)
-
-        # if no optionals or positionals are available, usage is just prog
-        elif usage is None and not actions:
-            usage = '%(prog)s' % dict(prog=self._prog)
-
-        # if optionals and positionals are available, calculate usage
-        elif usage is None:
-            prog = '%(prog)s' % dict(prog=self._prog)
-
-            # split optionals from positionals
-            optionals = []
-            positionals = []
-            for action in actions:
-                if action.option_strings:
-                    optionals.append(action)
-                else:
-                    positionals.append(action)
-
-            # build full usage string
-            format = self._format_actions_usage
-            action_usage = format(optionals + positionals, groups)
-            usage = ' '.join([s for s in [prog, action_usage] if s])
-
-            # wrap the usage parts if it's too long
-            text_width = self._width - self._current_indent
-            if len(prefix) + len(usage) > text_width:
-
-                # break usage into wrappable parts
-                part_regexp = r'\(.*?\)+|\[.*?\]+|\S+'
-                opt_usage = format(optionals, groups)
-                pos_usage = format(positionals, groups)
-                opt_parts = _re.findall(part_regexp, opt_usage)
-                pos_parts = _re.findall(part_regexp, pos_usage)
-                assert ' '.join(opt_parts) == opt_usage
-                assert ' '.join(pos_parts) == pos_usage
-
-                # helper for wrapping lines
-                def get_lines(parts, indent, prefix=None):
-                    lines = []
-                    line = []
-                    if prefix is not None:
-                        line_len = len(prefix) - 1
-                    else:
-                        line_len = len(indent) - 1
-                    for part in parts:
-                        if line_len + 1 + len(part) > text_width:
-                            lines.append(indent + ' '.join(line))
-                            line = []
-                            line_len = len(indent) - 1
-                        line.append(part)
-                        line_len += len(part) + 1
-                    if line:
-                        lines.append(indent + ' '.join(line))
-                    if prefix is not None:
-                        lines[0] = lines[0][len(indent):]
-                    return lines
-
-                # if prog is short, follow it with optionals or positionals
-                if len(prefix) + len(prog) <= 0.75 * text_width:
-                    indent = ' ' * (len(prefix) + len(prog) + 1)
-                    if opt_parts:
-                        lines = get_lines([prog] + opt_parts, indent, prefix)
-                        lines.extend(get_lines(pos_parts, indent))
-                    elif pos_parts:
-                        lines = get_lines([prog] + pos_parts, indent, prefix)
-                    else:
-                        lines = [prog]
-
-                # if prog is long, put it on its own line
-                else:
-                    indent = ' ' * len(prefix)
-                    parts = opt_parts + pos_parts
-                    lines = get_lines(parts, indent)
-                    if len(lines) > 1:
-                        lines = []
-                        lines.extend(get_lines(opt_parts, indent))
-                        lines.extend(get_lines(pos_parts, indent))
-                    lines = [prog] + lines
-
-                # join lines into usage
-                usage = '\n'.join(lines)
-
-        # prefix with 'usage:'
-        return '%s%s\n\n' % (prefix, usage)
-
-    def _format_actions_usage(self, actions, groups):
-        # find group indices and identify actions in groups
-        group_actions = set()
-        inserts = {}
-        for group in groups:
-            try:
-                start = actions.index(group._group_actions[0])
-            except ValueError:
-                continue
-            else:
-                end = start + len(group._group_actions)
-                if actions[start:end] == group._group_actions:
-                    for action in group._group_actions:
-                        group_actions.add(action)
-                    if not group.required:
-                        if start in inserts:
-                            inserts[start] += ' ['
-                        else:
-                            inserts[start] = '['
-                        inserts[end] = ']'
-                    else:
-                        if start in inserts:
-                            inserts[start] += ' ('
-                        else:
-                            inserts[start] = '('
-                        inserts[end] = ')'
-                    for i in range(start + 1, end):
-                        inserts[i] = '|'
-
-        # collect all actions format strings
-        parts = []
-        for i, action in enumerate(actions):
-
-            # suppressed arguments are marked with None
-            # remove | separators for suppressed arguments
-            if action.help is SUPPRESS:
-                parts.append(None)
-                if inserts.get(i) == '|':
-                    inserts.pop(i)
-                elif inserts.get(i + 1) == '|':
-                    inserts.pop(i + 1)
-
-            # produce all arg strings
-            elif not action.option_strings:
-                part = self._format_args(action, action.dest)
-
-                # if it's in a group, strip the outer []
-                if action in group_actions:
-                    if part[0] == '[' and part[-1] == ']':
-                        part = part[1:-1]
-
-                # add the action string to the list
-                parts.append(part)
-
-            # produce the first way to invoke the option in brackets
-            else:
-                option_string = action.option_strings[0]
-
-                # if the Optional doesn't take a value, format is:
-                #    -s or --long
-                if action.nargs == 0:
-                    part = '%s' % option_string
-
-                # if the Optional takes a value, format is:
-                #    -s ARGS or --long ARGS
-                else:
-                    default = action.dest.upper()
-                    args_string = self._format_args(action, default)
-                    part = '%s %s' % (option_string, args_string)
-
-                # make it look optional if it's not required or in a group
-                if not action.required and action not in group_actions:
-                    part = '[%s]' % part
-
-                # add the action string to the list
-                parts.append(part)
-
-        # insert things at the necessary indices
-        for i in sorted(inserts, reverse=True):
-            parts[i:i] = [inserts[i]]
-
-        # join all the action items with spaces
-        text = ' '.join([item for item in parts if item is not None])
-
-        # clean up separators for mutually exclusive groups
-        open = r'[\[(]'
-        close = r'[\])]'
-        text = _re.sub(r'(%s) ' % open, r'\1', text)
-        text = _re.sub(r' (%s)' % close, r'\1', text)
-        text = _re.sub(r'%s *%s' % (open, close), r'', text)
-        text = _re.sub(r'\(([^|]*)\)', r'\1', text)
-        text = text.strip()
-
-        # return the text
-        return text
-
-    def _format_text(self, text):
-        if '%(prog)' in text:
-            text = text % dict(prog=self._prog)
-        text_width = self._width - self._current_indent
-        indent = ' ' * self._current_indent
-        return self._fill_text(text, text_width, indent) + '\n\n'
-
-    def _format_action(self, action):
-        # determine the required width and the entry label
-        help_position = min(self._action_max_length + 2,
-                            self._max_help_position)
-        help_width = self._width - help_position
-        action_width = help_position - self._current_indent - 2
-        action_header = self._format_action_invocation(action)
-
-        # ho nelp; start on same line and add a final newline
-        if not action.help:
-            tup = self._current_indent, '', action_header
-            action_header = '%*s%s\n' % tup
-
-        # short action name; start on the same line and pad two spaces
-        elif len(action_header) <= action_width:
-            tup = self._current_indent, '', action_width, action_header
-            action_header = '%*s%-*s  ' % tup
-            indent_first = 0
-
-        # long action name; start on the next line
-        else:
-            tup = self._current_indent, '', action_header
-            action_header = '%*s%s\n' % tup
-            indent_first = help_position
-
-        # collect the pieces of the action help
-        parts = [action_header]
-
-        # if there was help for the action, add lines of help text
-        if action.help:
-            help_text = self._expand_help(action)
-            help_lines = self._split_lines(help_text, help_width)
-            parts.append('%*s%s\n' % (indent_first, '', help_lines[0]))
-            for line in help_lines[1:]:
-                parts.append('%*s%s\n' % (help_position, '', line))
-
-        # or add a newline if the description doesn't end with one
-        elif not action_header.endswith('\n'):
-            parts.append('\n')
-
-        # if there are any sub-actions, add their help as well
-        for subaction in self._iter_indented_subactions(action):
-            parts.append(self._format_action(subaction))
-
-        # return a single string
-        return self._join_parts(parts)
-
-    def _format_action_invocation(self, action):
-        if not action.option_strings:
-            metavar, = self._metavar_formatter(action, action.dest)(1)
-            return metavar
-
-        else:
-            parts = []
-
-            # if the Optional doesn't take a value, format is:
-            #    -s, --long
-            if action.nargs == 0:
-                parts.extend(action.option_strings)
-
-            # if the Optional takes a value, format is:
-            #    -s ARGS, --long ARGS
-            else:
-                default = action.dest.upper()
-                args_string = self._format_args(action, default)
-                for option_string in action.option_strings:
-                    parts.append('%s %s' % (option_string, args_string))
-
-            return ', '.join(parts)
-
-    def _metavar_formatter(self, action, default_metavar):
-        if action.metavar is not None:
-            result = action.metavar
-        elif action.choices is not None:
-            choice_strs = [str(choice) for choice in action.choices]
-            result = '{%s}' % ','.join(choice_strs)
-        else:
-            result = default_metavar
-
-        def format(tuple_size):
-            if isinstance(result, tuple):
-                return result
-            else:
-                return (result, ) * tuple_size
-        return format
-
-    def _format_args(self, action, default_metavar):
-        get_metavar = self._metavar_formatter(action, default_metavar)
-        if action.nargs is None:
-            result = '%s' % get_metavar(1)
-        elif action.nargs == OPTIONAL:
-            result = '[%s]' % get_metavar(1)
-        elif action.nargs == ZERO_OR_MORE:
-            result = '[%s [%s ...]]' % get_metavar(2)
-        elif action.nargs == ONE_OR_MORE:
-            result = '%s [%s ...]' % get_metavar(2)
-        elif action.nargs == REMAINDER:
-            result = '...'
-        elif action.nargs == PARSER:
-            result = '%s ...' % get_metavar(1)
-        else:
-            formats = ['%s' for _ in range(action.nargs)]
-            result = ' '.join(formats) % get_metavar(action.nargs)
-        return result
-
-    def _expand_help(self, action):
-        params = dict(vars(action), prog=self._prog)
-        for name in list(params):
-            if params[name] is SUPPRESS:
-                del params[name]
-        for name in list(params):
-            if hasattr(params[name], '__name__'):
-                params[name] = params[name].__name__
-        if params.get('choices') is not None:
-            choices_str = ', '.join([str(c) for c in params['choices']])
-            params['choices'] = choices_str
-        return self._get_help_string(action) % params
-
-    def _iter_indented_subactions(self, action):
-        try:
-            get_subactions = action._get_subactions
-        except AttributeError:
-            pass
-        else:
-            self._indent()
-            for subaction in get_subactions():
-                yield subaction
-            self._dedent()
-
-    def _split_lines(self, text, width):
-        text = self._whitespace_matcher.sub(' ', text).strip()
-        return _textwrap.wrap(text, width)
-
-    def _fill_text(self, text, width, indent):
-        text = self._whitespace_matcher.sub(' ', text).strip()
-        return _textwrap.fill(text, width, initial_indent=indent,
-                                           subsequent_indent=indent)
-
-    def _get_help_string(self, action):
-        return action.help
-
-
-class RawDescriptionHelpFormatter(HelpFormatter):
-    """Help message formatter which retains any formatting in descriptions.
-
-    Only the name of this class is considered a public API. All the methods
-    provided by the class are considered an implementation detail.
-    """
-
-    def _fill_text(self, text, width, indent):
-        return ''.join([indent + line for line in text.splitlines(True)])
-
-
-class RawTextHelpFormatter(RawDescriptionHelpFormatter):
-    """Help message formatter which retains formatting of all help text.
-
-    Only the name of this class is considered a public API. All the methods
-    provided by the class are considered an implementation detail.
-    """
-
-    def _split_lines(self, text, width):
-        return text.splitlines()
-
-
-class ArgumentDefaultsHelpFormatter(HelpFormatter):
-    """Help message formatter which adds default values to argument help.
-
-    Only the name of this class is considered a public API. All the methods
-    provided by the class are considered an implementation detail.
-    """
-
-    def _get_help_string(self, action):
-        help = action.help
-        if '%(default)' not in action.help:
-            if action.default is not SUPPRESS:
-                defaulting_nargs = [OPTIONAL, ZERO_OR_MORE]
-                if action.option_strings or action.nargs in defaulting_nargs:
-                    help += ' (default: %(default)s)'
-        return help
-
-
-# =====================
-# Options and Arguments
-# =====================
-
-def _get_action_name(argument):
-    if argument is None:
-        return None
-    elif argument.option_strings:
-        return  '/'.join(argument.option_strings)
-    elif argument.metavar not in (None, SUPPRESS):
-        return argument.metavar
-    elif argument.dest not in (None, SUPPRESS):
-        return argument.dest
-    else:
-        return None
-
-
-class ArgumentError(Exception):
-    """An error from creating or using an argument (optional or positional).
-
-    The string value of this exception is the message, augmented with
-    information about the argument that caused it.
-    """
-
-    def __init__(self, argument, message):
-        self.argument_name = _get_action_name(argument)
-        self.message = message
-
-    def __str__(self):
-        if self.argument_name is None:
-            format = '%(message)s'
-        else:
-            format = 'argument %(argument_name)s: %(message)s'
-        return format % dict(message=self.message,
-                             argument_name=self.argument_name)
-
-
-class ArgumentTypeError(Exception):
-    """An error from trying to convert a command line string to a type."""
-    pass
-
-
-# ==============
-# Action classes
-# ==============
-
-class Action(_AttributeHolder):
-    """Information about how to convert command line strings to Python objects.
-
-    Action objects are used by an ArgumentParser to represent the information
-    needed to parse a single argument from one or more strings from the
-    command line. The keyword arguments to the Action constructor are also
-    all attributes of Action instances.
-
-    Keyword Arguments:
-
-        - option_strings -- A list of command-line option strings which
-            should be associated with this action.
-
-        - dest -- The name of the attribute to hold the created object(s)
-
-        - nargs -- The number of command-line arguments that should be
-            consumed. By default, one argument will be consumed and a single
-            value will be produced.  Other values include:
-                - N (an integer) consumes N arguments (and produces a list)
-                - '?' consumes zero or one arguments
-                - '*' consumes zero or more arguments (and produces a list)
-                - '+' consumes one or more arguments (and produces a list)
-            Note that the difference between the default and nargs=1 is that
-            with the default, a single value will be produced, while with
-            nargs=1, a list containing a single value will be produced.
-
-        - const -- The value to be produced if the option is specified and the
-            option uses an action that takes no values.
-
-        - default -- The value to be produced if the option is not specified.
-
-        - type -- The type which the command-line arguments should be converted
-            to, should be one of 'string', 'int', 'float', 'complex' or a
-            callable object that accepts a single string argument. If None,
-            'string' is assumed.
-
-        - choices -- A container of values that should be allowed. If not None,
-            after a command-line argument has been converted to the appropriate
-            type, an exception will be raised if it is not a member of this
-            collection.
-
-        - required -- True if the action must always be specified at the
-            command line. This is only meaningful for optional command-line
-            arguments.
-
-        - help -- The help string describing the argument.
-
-        - metavar -- The name to be used for the option's argument with the
-            help string. If None, the 'dest' value will be used as the name.
-    """
-
-    def __init__(self,
-                 option_strings,
-                 dest,
-                 nargs=None,
-                 const=None,
-                 default=None,
-                 type=None,
-                 choices=None,
-                 required=False,
-                 help=None,
-                 metavar=None):
-        self.option_strings = option_strings
-        self.dest = dest
-        self.nargs = nargs
-        self.const = const
-        self.default = default
-        self.type = type
-        self.choices = choices
-        self.required = required
-        self.help = help
-        self.metavar = metavar
-
-    def _get_kwargs(self):
-        names = [
-            'option_strings',
-            'dest',
-            'nargs',
-            'const',
-            'default',
-            'type',
-            'choices',
-            'help',
-            'metavar',
-        ]
-        return [(name, getattr(self, name)) for name in names]
-
-    def __call__(self, parser, namespace, values, option_string=None):
-        raise NotImplementedError(_('.__call__() not defined'))
-
-
-class _StoreAction(Action):
-
-    def __init__(self,
-                 option_strings,
-                 dest,
-                 nargs=None,
-                 const=None,
-                 default=None,
-                 type=None,
-                 choices=None,
-                 required=False,
-                 help=None,
-                 metavar=None):
-        if nargs == 0:
-            raise ValueError('nargs for store actions must be > 0; if you '
-                             'have nothing to store, actions such as store '
-                             'true or store const may be more appropriate')
-        if const is not None and nargs != OPTIONAL:
-            raise ValueError('nargs must be %r to supply const' % OPTIONAL)
-        super(_StoreAction, self).__init__(
-            option_strings=option_strings,
-            dest=dest,
-            nargs=nargs,
-            const=const,
-            default=default,
-            type=type,
-            choices=choices,
-            required=required,
-            help=help,
-            metavar=metavar)
-
-    def __call__(self, parser, namespace, values, option_string=None):
-        setattr(namespace, self.dest, values)
-
-
-class _StoreConstAction(Action):
-
-    def __init__(self,
-                 option_strings,
-                 dest,
-                 const,
-                 default=None,
-                 required=False,
-                 help=None,
-                 metavar=None):
-        super(_StoreConstAction, self).__init__(
-            option_strings=option_strings,
-            dest=dest,
-            nargs=0,
-            const=const,
-            default=default,
-            required=required,
-            help=help)
-
-    def __call__(self, parser, namespace, values, option_string=None):
-        setattr(namespace, self.dest, self.const)
-
-
-class _StoreTrueAction(_StoreConstAction):
-
-    def __init__(self,
-                 option_strings,
-                 dest,
-                 default=False,
-                 required=False,
-                 help=None):
-        super(_StoreTrueAction, self).__init__(
-            option_strings=option_strings,
-            dest=dest,
-            const=True,
-            default=default,
-            required=required,
-            help=help)
-
-
-class _StoreFalseAction(_StoreConstAction):
-
-    def __init__(self,
-                 option_strings,
-                 dest,
-                 default=True,
-                 required=False,
-                 help=None):
-        super(_StoreFalseAction, self).__init__(
-            option_strings=option_strings,
-            dest=dest,
-            const=False,
-            default=default,
-            required=required,
-            help=help)
-
-
-class _AppendAction(Action):
-
-    def __init__(self,
-                 option_strings,
-                 dest,
-                 nargs=None,
-                 const=None,
-                 default=None,
-                 type=None,
-                 choices=None,
-                 required=False,
-                 help=None,
-                 metavar=None):
-        if nargs == 0:
-            raise ValueError('nargs for append actions must be > 0; if arg '
-                             'strings are not supplying the value to append, '
-                             'the append const action may be more appropriate')
-        if const is not None and nargs != OPTIONAL:
-            raise ValueError('nargs must be %r to supply const' % OPTIONAL)
-        super(_AppendAction, self).__init__(
-            option_strings=option_strings,
-            dest=dest,
-            nargs=nargs,
-            const=const,
-            default=default,
-            type=type,
-            choices=choices,
-            required=required,
-            help=help,
-            metavar=metavar)
-
-    def __call__(self, parser, namespace, values, option_string=None):
-        items = _copy.copy(_ensure_value(namespace, self.dest, []))
-        items.append(values)
-        setattr(namespace, self.dest, items)
-
-
-class _AppendConstAction(Action):
-
-    def __init__(self,
-                 option_strings,
-                 dest,
-                 const,
-                 default=None,
-                 required=False,
-                 help=None,
-                 metavar=None):
-        super(_AppendConstAction, self).__init__(
-            option_strings=option_strings,
-            dest=dest,
-            nargs=0,
-            const=const,
-            default=default,
-            required=required,
-            help=help,
-            metavar=metavar)
-
-    def __call__(self, parser, namespace, values, option_string=None):
-        items = _copy.copy(_ensure_value(namespace, self.dest, []))
-        items.append(self.const)
-        setattr(namespace, self.dest, items)
-
-
-class _CountAction(Action):
-
-    def __init__(self,
-                 option_strings,
-                 dest,
-                 default=None,
-                 required=False,
-                 help=None):
-        super(_CountAction, self).__init__(
-            option_strings=option_strings,
-            dest=dest,
-            nargs=0,
-            default=default,
-            required=required,
-            help=help)
-
-    def __call__(self, parser, namespace, values, option_string=None):
-        new_count = _ensure_value(namespace, self.dest, 0) + 1
-        setattr(namespace, self.dest, new_count)
-
-
-class _HelpAction(Action):
-
-    def __init__(self,
-                 option_strings,
-                 dest=SUPPRESS,
-                 default=SUPPRESS,
-                 help=None):
-        super(_HelpAction, self).__init__(
-            option_strings=option_strings,
-            dest=dest,
-            default=default,
-            nargs=0,
-            help=help)
-
-    def __call__(self, parser, namespace, values, option_string=None):
-        parser.print_help()
-        parser.exit()
-
-
-class _VersionAction(Action):
-
-    def __init__(self,
-                 option_strings,
-                 version=None,
-                 dest=SUPPRESS,
-                 default=SUPPRESS,
-                 help="show program's version number and exit"):
-        super(_VersionAction, self).__init__(
-            option_strings=option_strings,
-            dest=dest,
-            default=default,
-            nargs=0,
-            help=help)
-        self.version = version
-
-    def __call__(self, parser, namespace, values, option_string=None):
-        version = self.version
-        if version is None:
-            version = parser.version
-        formatter = parser._get_formatter()
-        formatter.add_text(version)
-        parser.exit(message=formatter.format_help())
-
-
-class _SubParsersAction(Action):
-
-    class _ChoicesPseudoAction(Action):
-
-        def __init__(self, name, help):
-            sup = super(_SubParsersAction._ChoicesPseudoAction, self)
-            sup.__init__(option_strings=[], dest=name, help=help)
-
-    def __init__(self,
-                 option_strings,
-                 prog,
-                 parser_class,
-                 dest=SUPPRESS,
-                 help=None,
-                 metavar=None):
-
-        self._prog_prefix = prog
-        self._parser_class = parser_class
-        self._name_parser_map = {}
-        self._choices_actions = []
-
-        super(_SubParsersAction, self).__init__(
-            option_strings=option_strings,
-            dest=dest,
-            nargs=PARSER,
-            choices=self._name_parser_map,
-            help=help,
-            metavar=metavar)
-
-    def add_parser(self, name, **kwargs):
-        # set prog from the existing prefix
-        if kwargs.get('prog') is None:
-            kwargs['prog'] = '%s %s' % (self._prog_prefix, name)
-
-        # create a pseudo-action to hold the choice help
-        if 'help' in kwargs:
-            help = kwargs.pop('help')
-            choice_action = self._ChoicesPseudoAction(name, help)
-            self._choices_actions.append(choice_action)
-
-        # create the parser and add it to the map
-        parser = self._parser_class(**kwargs)
-        self._name_parser_map[name] = parser
-        return parser
-
-    def _get_subactions(self):
-        return self._choices_actions
-
-    def __call__(self, parser, namespace, values, option_string=None):
-        parser_name = values[0]
-        arg_strings = values[1:]
-
-        # set the parser name if requested
-        if self.dest is not SUPPRESS:
-            setattr(namespace, self.dest, parser_name)
-
-        # select the parser
-        try:
-            parser = self._name_parser_map[parser_name]
-        except KeyError:
-            tup = parser_name, ', '.join(self._name_parser_map)
-            msg = _('unknown parser %r (choices: %s)' % tup)
-            raise ArgumentError(self, msg)
-
-        # parse all the remaining options into the namespace
-        # store any unrecognized options on the object, so that the top
-        # level parser can decide what to do with them
-        namespace, arg_strings = parser.parse_known_args(arg_strings, namespace)
-        if arg_strings:
-            vars(namespace).setdefault(_UNRECOGNIZED_ARGS_ATTR, [])
-            getattr(namespace, _UNRECOGNIZED_ARGS_ATTR).extend(arg_strings)
-
-
-# ==============
-# Type classes
-# ==============
-
-class FileType(object):
-    """Factory for creating file object types
-
-    Instances of FileType are typically passed as type= arguments to the
-    ArgumentParser add_argument() method.
-
-    Keyword Arguments:
-        - mode -- A string indicating how the file is to be opened. Accepts the
-            same values as the builtin open() function.
-        - bufsize -- The file's desired buffer size. Accepts the same values as
-            the builtin open() function.
-    """
-
-    def __init__(self, mode='r', bufsize=None):
-        self._mode = mode
-        self._bufsize = bufsize
-
-    def __call__(self, string):
-        # the special argument "-" means sys.std{in,out}
-        if string == '-':
-            if 'r' in self._mode:
-                return _sys.stdin
-            elif 'w' in self._mode:
-                return _sys.stdout
-            else:
-                msg = _('argument "-" with mode %r' % self._mode)
-                raise ValueError(msg)
-
-        # all other arguments are used as file names
-        if self._bufsize:
-            return open(string, self._mode, self._bufsize)
-        else:
-            return open(string, self._mode)
-
-    def __repr__(self):
-        args = [self._mode, self._bufsize]
-        args_str = ', '.join([repr(arg) for arg in args if arg is not None])
-        return '%s(%s)' % (type(self).__name__, args_str)
-
-# ===========================
-# Optional and Positional Parsing
-# ===========================
-
-class Namespace(_AttributeHolder):
-    """Simple object for storing attributes.
-
-    Implements equality by attribute names and values, and provides a simple
-    string representation.
-    """
-
-    def __init__(self, **kwargs):
-        for name in kwargs:
-            setattr(self, name, kwargs[name])
-
-    __hash__ = None
-
-    def __eq__(self, other):
-        return vars(self) == vars(other)
-
-    def __ne__(self, other):
-        return not (self == other)
-
-    def __contains__(self, key):
-        return key in self.__dict__
-
-
-class _ActionsContainer(object):
-
-    def __init__(self,
-                 description,
-                 prefix_chars,
-                 argument_default,
-                 conflict_handler):
-        super(_ActionsContainer, self).__init__()
-
-        self.description = description
-        self.argument_default = argument_default
-        self.prefix_chars = prefix_chars
-        self.conflict_handler = conflict_handler
-
-        # set up registries
-        self._registries = {}
-
-        # register actions
-        self.register('action', None, _StoreAction)
-        self.register('action', 'store', _StoreAction)
-        self.register('action', 'store_const', _StoreConstAction)
-        self.register('action', 'store_true', _StoreTrueAction)
-        self.register('action', 'store_false', _StoreFalseAction)
-        self.register('action', 'append', _AppendAction)
-        self.register('action', 'append_const', _AppendConstAction)
-        self.register('action', 'count', _CountAction)
-        self.register('action', 'help', _HelpAction)
-        self.register('action', 'version', _VersionAction)
-        self.register('action', 'parsers', _SubParsersAction)
-
-        # raise an exception if the conflict handler is invalid
-        self._get_handler()
-
-        # action storage
-        self._actions = []
-        self._option_string_actions = {}
-
-        # groups
-        self._action_groups = []
-        self._mutually_exclusive_groups = []
-
-        # defaults storage
-        self._defaults = {}
-
-        # determines whether an "option" looks like a negative number
-        self._negative_number_matcher = _re.compile(r'^-\d+$|^-\d*\.\d+$')
-
-        # whether or not there are any optionals that look like negative
-        # numbers -- uses a list so it can be shared and edited
-        self._has_negative_number_optionals = []
-
-    # ====================
-    # Registration methods
-    # ====================
-    def register(self, registry_name, value, object):
-        registry = self._registries.setdefault(registry_name, {})
-        registry[value] = object
-
-    def _registry_get(self, registry_name, value, default=None):
-        return self._registries[registry_name].get(value, default)
-
-    # ==================================
-    # Namespace default accessor methods
-    # ==================================
-    def set_defaults(self, **kwargs):
-        self._defaults.update(kwargs)
-
-        # if these defaults match any existing arguments, replace
-        # the previous default on the object with the new one
-        for action in self._actions:
-            if action.dest in kwargs:
-                action.default = kwargs[action.dest]
-
-    def get_default(self, dest):
-        for action in self._actions:
-            if action.dest == dest and action.default is not None:
-                return action.default
-        return self._defaults.get(dest, None)
-
-
-    # =======================
-    # Adding argument actions
-    # =======================
-    def add_argument(self, *args, **kwargs):
-        """
-        add_argument(dest, ..., name=value, ...)
-        add_argument(option_string, option_string, ..., name=value, ...)
-        """
-
-        # if no positional args are supplied or only one is supplied and
-        # it doesn't look like an option string, parse a positional
-        # argument
-        chars = self.prefix_chars
-        if not args or len(args) == 1 and args[0][0] not in chars:
-            if args and 'dest' in kwargs:
-                raise ValueError('dest supplied twice for positional argument')
-            kwargs = self._get_positional_kwargs(*args, **kwargs)
-
-        # otherwise, we're adding an optional argument
-        else:
-            kwargs = self._get_optional_kwargs(*args, **kwargs)
-
-        # if no default was supplied, use the parser-level default
-        if 'default' not in kwargs:
-            dest = kwargs['dest']
-            if dest in self._defaults:
-                kwargs['default'] = self._defaults[dest]
-            elif self.argument_default is not None:
-                kwargs['default'] = self.argument_default
-
-        # create the action object, and add it to the parser
-        action_class = self._pop_action_class(kwargs)
-        if not _callable(action_class):
-            raise ValueError('unknown action "%s"' % action_class)
-        action = action_class(**kwargs)
-
-        # raise an error if the action type is not callable
-        type_func = self._registry_get('type', action.type, action.type)
-        if not _callable(type_func):
-            raise ValueError('%r is not callable' % type_func)
-
-        return self._add_action(action)
-
-    def add_argument_group(self, *args, **kwargs):
-        group = _ArgumentGroup(self, *args, **kwargs)
-        self._action_groups.append(group)
-        return group
-
-    def add_mutually_exclusive_group(self, **kwargs):
-        group = _MutuallyExclusiveGroup(self, **kwargs)
-        self._mutually_exclusive_groups.append(group)
-        return group
-
-    def _add_action(self, action):
-        # resolve any conflicts
-        self._check_conflict(action)
-
-        # add to actions list
-        self._actions.append(action)
-        action.container = self
-
-        # index the action by any option strings it has
-        for option_string in action.option_strings:
-            self._option_string_actions[option_string] = action
-
-        # set the flag if any option strings look like negative numbers
-        for option_string in action.option_strings:
-            if self._negative_number_matcher.match(option_string):
-                if not self._has_negative_number_optionals:
-                    self._has_negative_number_optionals.append(True)
-
-        # return the created action
-        return action
-
-    def _remove_action(self, action):
-        self._actions.remove(action)
-
-    def _add_container_actions(self, container):
-        # collect groups by titles
-        title_group_map = {}
-        for group in self._action_groups:
-            if group.title in title_group_map:
-                msg = _('cannot merge actions - two groups are named %r')
-                raise ValueError(msg % (group.title))
-            title_group_map[group.title] = group
-
-        # map each action to its group
-        group_map = {}
-        for group in container._action_groups:
-
-            # if a group with the title exists, use that, otherwise
-            # create a new group matching the container's group
-            if group.title not in title_group_map:
-                title_group_map[group.title] = self.add_argument_group(
-                    title=group.title,
-                    description=group.description,
-                    conflict_handler=group.conflict_handler)
-
-            # map the actions to their new group
-            for action in group._group_actions:
-                group_map[action] = title_group_map[group.title]
-
-        # add container's mutually exclusive groups
-        # NOTE: if add_mutually_exclusive_group ever gains title= and
-        # description= then this code will need to be expanded as above
-        for group in container._mutually_exclusive_groups:
-            mutex_group = self.add_mutually_exclusive_group(
-                required=group.required)
-
-            # map the actions to their new mutex group
-            for action in group._group_actions:
-                group_map[action] = mutex_group
-
-        # add all actions to this container or their group
-        for action in container._actions:
-            group_map.get(action, self)._add_action(action)
-
-    def _get_positional_kwargs(self, dest, **kwargs):
-        # make sure required is not specified
-        if 'required' in kwargs:
-            msg = _("'required' is an invalid argument for positionals")
-            raise TypeError(msg)
-
-        # mark positional arguments as required if at least one is
-        # always required
-        if kwargs.get('nargs') not in [OPTIONAL, ZERO_OR_MORE]:
-            kwargs['required'] = True
-        if kwargs.get('nargs') == ZERO_OR_MORE and 'default' not in kwargs:
-            kwargs['required'] = True
-
-        # return the keyword arguments with no option strings
-        return dict(kwargs, dest=dest, option_strings=[])
-
-    def _get_optional_kwargs(self, *args, **kwargs):
-        # determine short and long option strings
-        option_strings = []
-        long_option_strings = []
-        for option_string in args:
-            # error on strings that don't start with an appropriate prefix
-            if not option_string[0] in self.prefix_chars:
-                msg = _('invalid option string %r: '
-                        'must start with a character %r')
-                tup = option_string, self.prefix_chars
-                raise ValueError(msg % tup)
-
-            # strings starting with two prefix characters are long options
-            option_strings.append(option_string)
-            if option_string[0] in self.prefix_chars:
-                if len(option_string) > 1:
-                    if option_string[1] in self.prefix_chars:
-                        long_option_strings.append(option_string)
-
-        # infer destination, '--foo-bar' -> 'foo_bar' and '-x' -> 'x'
-        dest = kwargs.pop('dest', None)
-        if dest is None:
-            if long_option_strings:
-                dest_option_string = long_option_strings[0]
-            else:
-                dest_option_string = option_strings[0]
-            dest = dest_option_string.lstrip(self.prefix_chars)
-            if not dest:
-                msg = _('dest= is required for options like %r')
-                raise ValueError(msg % option_string)
-            dest = dest.replace('-', '_')
-
-        # return the updated keyword arguments
-        return dict(kwargs, dest=dest, option_strings=option_strings)
-
-    def _pop_action_class(self, kwargs, default=None):
-        action = kwargs.pop('action', default)
-        return self._registry_get('action', action, action)
-
-    def _get_handler(self):
-        # determine function from conflict handler string
-        handler_func_name = '_handle_conflict_%s' % self.conflict_handler
-        try:
-            return getattr(self, handler_func_name)
-        except AttributeError:
-            msg = _('invalid conflict_resolution value: %r')
-            raise ValueError(msg % self.conflict_handler)
-
-    def _check_conflict(self, action):
-
-        # find all options that conflict with this option
-        confl_optionals = []
-        for option_string in action.option_strings:
-            if option_string in self._option_string_actions:
-                confl_optional = self._option_string_actions[option_string]
-                confl_optionals.append((option_string, confl_optional))
-
-        # resolve any conflicts
-        if confl_optionals:
-            conflict_handler = self._get_handler()
-            conflict_handler(action, confl_optionals)
-
-    def _handle_conflict_error(self, action, conflicting_actions):
-        message = _('conflicting option string(s): %s')
-        conflict_string = ', '.join([option_string
-                                     for option_string, action
-                                     in conflicting_actions])
-        raise ArgumentError(action, message % conflict_string)
-
-    def _handle_conflict_resolve(self, action, conflicting_actions):
-
-        # remove all conflicting options
-        for option_string, action in conflicting_actions:
-
-            # remove the conflicting option
-            action.option_strings.remove(option_string)
-            self._option_string_actions.pop(option_string, None)
-
-            # if the option now has no option string, remove it from the
-            # container holding it
-            if not action.option_strings:
-                action.container._remove_action(action)
-
-
-class _ArgumentGroup(_ActionsContainer):
-
-    def __init__(self, container, title=None, description=None, **kwargs):
-        # add any missing keyword arguments by checking the container
-        update = kwargs.setdefault
-        update('conflict_handler', container.conflict_handler)
-        update('prefix_chars', container.prefix_chars)
-        update('argument_default', container.argument_default)
-        super_init = super(_ArgumentGroup, self).__init__
-        super_init(description=description, **kwargs)
-
-        # group attributes
-        self.title = title
-        self._group_actions = []
-
-        # share most attributes with the container
-        self._registries = container._registries
-        self._actions = container._actions
-        self._option_string_actions = container._option_string_actions
-        self._defaults = container._defaults
-        self._has_negative_number_optionals = \
-            container._has_negative_number_optionals
-
-    def _add_action(self, action):
-        action = super(_ArgumentGroup, self)._add_action(action)
-        self._group_actions.append(action)
-        return action
-
-    def _remove_action(self, action):
-        super(_ArgumentGroup, self)._remove_action(action)
-        self._group_actions.remove(action)
-
-
-class _MutuallyExclusiveGroup(_ArgumentGroup):
-
-    def __init__(self, container, required=False):
-        super(_MutuallyExclusiveGroup, self).__init__(container)
-        self.required = required
-        self._container = container
-
-    def _add_action(self, action):
-        if action.required:
-            msg = _('mutually exclusive arguments must be optional')
-            raise ValueError(msg)
-        action = self._container._add_action(action)
-        self._group_actions.append(action)
-        return action
-
-    def _remove_action(self, action):
-        self._container._remove_action(action)
-        self._group_actions.remove(action)
-
-
-class ArgumentParser(_AttributeHolder, _ActionsContainer):
-    """Object for parsing command line strings into Python objects.
-
-    Keyword Arguments:
-        - prog -- The name of the program (default: sys.argv[0])
-        - usage -- A usage message (default: auto-generated from arguments)
-        - description -- A description of what the program does
-        - epilog -- Text following the argument descriptions
-        - parents -- Parsers whose arguments should be copied into this one
-        - formatter_class -- HelpFormatter class for printing help messages
-        - prefix_chars -- Characters that prefix optional arguments
-        - fromfile_prefix_chars -- Characters that prefix files containing
-            additional arguments
-        - argument_default -- The default value for all arguments
-        - conflict_handler -- String indicating how to handle conflicts
-        - add_help -- Add a -h/-help option
-    """
-
-    def __init__(self,
-                 prog=None,
-                 usage=None,
-                 description=None,
-                 epilog=None,
-                 version=None,
-                 parents=[],
-                 formatter_class=HelpFormatter,
-                 prefix_chars='-',
-                 fromfile_prefix_chars=None,
-                 argument_default=None,
-                 conflict_handler='error',
-                 add_help=True):
-
-        if version is not None:
-            import warnings
-            warnings.warn(
-                """The "version" argument to ArgumentParser is deprecated. """
-                """Please use """
-                """"add_argument(..., action='version', version="N", ...)" """
-                """instead""", DeprecationWarning)
-
-        superinit = super(ArgumentParser, self).__init__
-        superinit(description=description,
-                  prefix_chars=prefix_chars,
-                  argument_default=argument_default,
-                  conflict_handler=conflict_handler)
-
-        # default setting for prog
-        if prog is None:
-            prog = _os.path.basename(_sys.argv[0])
-
-        self.prog = prog
-        self.usage = usage
-        self.epilog = epilog
-        self.version = version
-        self.formatter_class = formatter_class
-        self.fromfile_prefix_chars = fromfile_prefix_chars
-        self.add_help = add_help
-
-        add_group = self.add_argument_group
-        self._positionals = add_group(_('positional arguments'))
-        self._optionals = add_group(_('optional arguments'))
-        self._subparsers = None
-
-        # register types
-        def identity(string):
-            return string
-        self.register('type', None, identity)
-
-        # add help and version arguments if necessary
-        # (using explicit default to override global argument_default)
-        if '-' in prefix_chars:
-            default_prefix = '-'
-        else:
-            default_prefix = prefix_chars[0]
-        if self.add_help:
-            self.add_argument(
-                default_prefix+'h', default_prefix*2+'help',
-                action='help', default=SUPPRESS,
-                help=_('show this help message and exit'))
-        if self.version:
-            self.add_argument(
-                default_prefix+'v', default_prefix*2+'version',
-                action='version', default=SUPPRESS,
-                version=self.version,
-                help=_("show program's version number and exit"))
-
-        # add parent arguments and defaults
-        for parent in parents:
-            self._add_container_actions(parent)
-            try:
-                defaults = parent._defaults
-            except AttributeError:
-                pass
-            else:
-                self._defaults.update(defaults)
-
-    # =======================
-    # Pretty __repr__ methods
-    # =======================
-    def _get_kwargs(self):
-        names = [
-            'prog',
-            'usage',
-            'description',
-            'version',
-            'formatter_class',
-            'conflict_handler',
-            'add_help',
-        ]
-        return [(name, getattr(self, name)) for name in names]
-
-    # ==================================
-    # Optional/Positional adding methods
-    # ==================================
-    def add_subparsers(self, **kwargs):
-        if self._subparsers is not None:
-            self.error(_('cannot have multiple subparser arguments'))
-
-        # add the parser class to the arguments if it's not present
-        kwargs.setdefault('parser_class', type(self))
-
-        if 'title' in kwargs or 'description' in kwargs:
-            title = _(kwargs.pop('title', 'subcommands'))
-            description = _(kwargs.pop('description', None))
-            self._subparsers = self.add_argument_group(title, description)
-        else:
-            self._subparsers = self._positionals
-
-        # prog defaults to the usage message of this parser, skipping
-        # optional arguments and with no "usage:" prefix
-        if kwargs.get('prog') is None:
-            formatter = self._get_formatter()
-            positionals = self._get_positional_actions()
-            groups = self._mutually_exclusive_groups
-            formatter.add_usage(self.usage, positionals, groups, '')
-            kwargs['prog'] = formatter.format_help().strip()
-
-        # create the parsers action and add it to the positionals list
-        parsers_class = self._pop_action_class(kwargs, 'parsers')
-        action = parsers_class(option_strings=[], **kwargs)
-        self._subparsers._add_action(action)
-
-        # return the created parsers action
-        return action
-
-    def _add_action(self, action):
-        if action.option_strings:
-            self._optionals._add_action(action)
-        else:
-            self._positionals._add_action(action)
-        return action
-
-    def _get_optional_actions(self):
-        return [action
-                for action in self._actions
-                if action.option_strings]
-
-    def _get_positional_actions(self):
-        return [action
-                for action in self._actions
-                if not action.option_strings]
-
-    # =====================================
-    # Command line argument parsing methods
-    # =====================================
-    def parse_args(self, args=None, namespace=None):
-        args, argv = self.parse_known_args(args, namespace)
-        if argv:
-            msg = _('unrecognized arguments: %s')
-            self.error(msg % ' '.join(argv))
-        return args
-
-    def parse_known_args(self, args=None, namespace=None):
-        # args default to the system args
-        if args is None:
-            args = _sys.argv[1:]
-
-        # default Namespace built from parser defaults
-        if namespace is None:
-            namespace = Namespace()
-
-        # add any action defaults that aren't present
-        for action in self._actions:
-            if action.dest is not SUPPRESS:
-                if not hasattr(namespace, action.dest):
-                    if action.default is not SUPPRESS:
-                        default = action.default
-                        if isinstance(action.default, basestring):
-                            default = self._get_value(action, default)
-                        setattr(namespace, action.dest, default)
-
-        # add any parser defaults that aren't present
-        for dest in self._defaults:
-            if not hasattr(namespace, dest):
-                setattr(namespace, dest, self._defaults[dest])
-
-        # parse the arguments and exit if there are any errors
-        try:
-            namespace, args = self._parse_known_args(args, namespace)
-            if hasattr(namespace, _UNRECOGNIZED_ARGS_ATTR):
-                args.extend(getattr(namespace, _UNRECOGNIZED_ARGS_ATTR))
-                delattr(namespace, _UNRECOGNIZED_ARGS_ATTR)
-            return namespace, args
-        except ArgumentError:
-            err = _sys.exc_info()[1]
-            self.error(str(err))
-
-    def _parse_known_args(self, arg_strings, namespace):
-        # replace arg strings that are file references
-        if self.fromfile_prefix_chars is not None:
-            arg_strings = self._read_args_from_files(arg_strings)
-
-        # map all mutually exclusive arguments to the other arguments
-        # they can't occur with
-        action_conflicts = {}
-        for mutex_group in self._mutually_exclusive_groups:
-            group_actions = mutex_group._group_actions
-            for i, mutex_action in enumerate(mutex_group._group_actions):
-                conflicts = action_conflicts.setdefault(mutex_action, [])
-                conflicts.extend(group_actions[:i])
-                conflicts.extend(group_actions[i + 1:])
-
-        # find all option indices, and determine the arg_string_pattern
-        # which has an 'O' if there is an option at an index,
-        # an 'A' if there is an argument, or a '-' if there is a '--'
-        option_string_indices = {}
-        arg_string_pattern_parts = []
-        arg_strings_iter = iter(arg_strings)
-        for i, arg_string in enumerate(arg_strings_iter):
-
-            # all args after -- are non-options
-            if arg_string == '--':
-                arg_string_pattern_parts.append('-')
-                for arg_string in arg_strings_iter:
-                    arg_string_pattern_parts.append('A')
-
-            # otherwise, add the arg to the arg strings
-            # and note the index if it was an option
-            else:
-                option_tuple = self._parse_optional(arg_string)
-                if option_tuple is None:
-                    pattern = 'A'
-                else:
-                    option_string_indices[i] = option_tuple
-                    pattern = 'O'
-                arg_string_pattern_parts.append(pattern)
-
-        # join the pieces together to form the pattern
-        arg_strings_pattern = ''.join(arg_string_pattern_parts)
-
-        # converts arg strings to the appropriate and then takes the action
-        seen_actions = set()
-        seen_non_default_actions = set()
-
-        def take_action(action, argument_strings, option_string=None):
-            seen_actions.add(action)
-            argument_values = self._get_values(action, argument_strings)
-
-            # error if this argument is not allowed with other previously
-            # seen arguments, assuming that actions that use the default
-            # value don't really count as "present"
-            if argument_values is not action.default:
-                seen_non_default_actions.add(action)
-                for conflict_action in action_conflicts.get(action, []):
-                    if conflict_action in seen_non_default_actions:
-                        msg = _('not allowed with argument %s')
-                        action_name = _get_action_name(conflict_action)
-                        raise ArgumentError(action, msg % action_name)
-
-            # take the action if we didn't receive a SUPPRESS value
-            # (e.g. from a default)
-            if argument_values is not SUPPRESS:
-                action(self, namespace, argument_values, option_string)
-
-        # function to convert arg_strings into an optional action
-        def consume_optional(start_index):
-
-            # get the optional identified at this index
-            option_tuple = option_string_indices[start_index]
-            action, option_string, explicit_arg = option_tuple
-
-            # identify additional optionals in the same arg string
-            # (e.g. -xyz is the same as -x -y -z if no args are required)
-            match_argument = self._match_argument
-            action_tuples = []
-            while True:
-
-                # if we found no optional action, skip it
-                if action is None:
-                    extras.append(arg_strings[start_index])
-                    return start_index + 1
-
-                # if there is an explicit argument, try to match the
-                # optional's string arguments to only this
-                if explicit_arg is not None:
-                    arg_count = match_argument(action, 'A')
-
-                    # if the action is a single-dash option and takes no
-                    # arguments, try to parse more single-dash options out
-                    # of the tail of the option string
-                    chars = self.prefix_chars
-                    if arg_count == 0 and option_string[1] not in chars:
-                        action_tuples.append((action, [], option_string))
-                        char = option_string[0]
-                        option_string = char + explicit_arg[0]
-                        new_explicit_arg = explicit_arg[1:] or None
-                        optionals_map = self._option_string_actions
-                        if option_string in optionals_map:
-                            action = optionals_map[option_string]
-                            explicit_arg = new_explicit_arg
-                        else:
-                            msg = _('ignored explicit argument %r')
-                            raise ArgumentError(action, msg % explicit_arg)
-
-                    # if the action expect exactly one argument, we've
-                    # successfully matched the option; exit the loop
-                    elif arg_count == 1:
-                        stop = start_index + 1
-                        args = [explicit_arg]
-                        action_tuples.append((action, args, option_string))
-                        break
-
-                    # error if a double-dash option did not use the
-                    # explicit argument
-                    else:
-                        msg = _('ignored explicit argument %r')
-                        raise ArgumentError(action, msg % explicit_arg)
-
-                # if there is no explicit argument, try to match the
-                # optional's string arguments with the following strings
-                # if successful, exit the loop
-                else:
-                    start = start_index + 1
-                    selected_patterns = arg_strings_pattern[start:]
-                    arg_count = match_argument(action, selected_patterns)
-                    stop = start + arg_count
-                    args = arg_strings[start:stop]
-                    action_tuples.append((action, args, option_string))
-                    break
-
-            # add the Optional to the list and return the index at which
-            # the Optional's string args stopped
-            assert action_tuples
-            for action, args, option_string in action_tuples:
-                take_action(action, args, option_string)
-            return stop
-
-        # the list of Positionals left to be parsed; this is modified
-        # by consume_positionals()
-        positionals = self._get_positional_actions()
-
-        # function to convert arg_strings into positional actions
-        def consume_positionals(start_index):
-            # match as many Positionals as possible
-            match_partial = self._match_arguments_partial
-            selected_pattern = arg_strings_pattern[start_index:]
-            arg_counts = match_partial(positionals, selected_pattern)
-
-            # slice off the appropriate arg strings for each Positional
-            # and add the Positional and its args to the list
-            for action, arg_count in zip(positionals, arg_counts):
-                args = arg_strings[start_index: start_index + arg_count]
-                start_index += arg_count
-                take_action(action, args)
-
-            # slice off the Positionals that we just parsed and return the
-            # index at which the Positionals' string args stopped
-            positionals[:] = positionals[len(arg_counts):]
-            return start_index
-
-        # consume Positionals and Optionals alternately, until we have
-        # passed the last option string
-        extras = []
-        start_index = 0
-        if option_string_indices:
-            max_option_string_index = max(option_string_indices)
-        else:
-            max_option_string_index = -1
-        while start_index <= max_option_string_index:
-
-            # consume any Positionals preceding the next option
-            next_option_string_index = min([
-                index
-                for index in option_string_indices
-                if index >= start_index])
-            if start_index != next_option_string_index:
-                positionals_end_index = consume_positionals(start_index)
-
-                # only try to parse the next optional if we didn't consume
-                # the option string during the positionals parsing
-                if positionals_end_index > start_index:
-                    start_index = positionals_end_index
-                    continue
-                else:
-                    start_index = positionals_end_index
-
-            # if we consumed all the positionals we could and we're not
-            # at the index of an option string, there were extra arguments
-            if start_index not in option_string_indices:
-                strings = arg_strings[start_index:next_option_string_index]
-                extras.extend(strings)
-                start_index = next_option_string_index
-
-            # consume the next optional and any arguments for it
-            start_index = consume_optional(start_index)
-
-        # consume any positionals following the last Optional
-        stop_index = consume_positionals(start_index)
-
-        # if we didn't consume all the argument strings, there were extras
-        extras.extend(arg_strings[stop_index:])
-
-        # if we didn't use all the Positional objects, there were too few
-        # arg strings supplied.
-        if positionals:
-            self.error(_('too few arguments'))
-
-        # make sure all required actions were present
-        for action in self._actions:
-            if action.required:
-                if action not in seen_actions:
-                    name = _get_action_name(action)
-                    self.error(_('argument %s is required') % name)
-
-        # make sure all required groups had one option present
-        for group in self._mutually_exclusive_groups:
-            if group.required:
-                for action in group._group_actions:
-                    if action in seen_non_default_actions:
-                        break
-
-                # if no actions were used, report the error
-                else:
-                    names = [_get_action_name(action)
-                             for action in group._group_actions
-                             if action.help is not SUPPRESS]
-                    msg = _('one of the arguments %s is required')
-                    self.error(msg % ' '.join(names))
-
-        # return the updated namespace and the extra arguments
-        return namespace, extras
-
-    def _read_args_from_files(self, arg_strings):
-        # expand arguments referencing files
-        new_arg_strings = []
-        for arg_string in arg_strings:
-
-            # for regular arguments, just add them back into the list
-            if arg_string[0] not in self.fromfile_prefix_chars:
-                new_arg_strings.append(arg_string)
-
-            # replace arguments referencing files with the file content
-            else:
-                try:
-                    args_file = open(arg_string[1:])
-                    try:
-                        arg_strings = []
-                        for arg_line in args_file.read().splitlines():
-                            for arg in self.convert_arg_line_to_args(arg_line):
-                                arg_strings.append(arg)
-                        arg_strings = self._read_args_from_files(arg_strings)
-                        new_arg_strings.extend(arg_strings)
-                    finally:
-                        args_file.close()
-                except IOError:
-                    err = _sys.exc_info()[1]
-                    self.error(str(err))
-
-        # return the modified argument list
-        return new_arg_strings
-
-    def convert_arg_line_to_args(self, arg_line):
-        return [arg_line]
-
-    def _match_argument(self, action, arg_strings_pattern):
-        # match the pattern for this action to the arg strings
-        nargs_pattern = self._get_nargs_pattern(action)
-        match = _re.match(nargs_pattern, arg_strings_pattern)
-
-        # raise an exception if we weren't able to find a match
-        if match is None:
-            nargs_errors = {
-                None: _('expected one argument'),
-                OPTIONAL: _('expected at most one argument'),
-                ONE_OR_MORE: _('expected at least one argument'),
-            }
-            default = _('expected %s argument(s)') % action.nargs
-            msg = nargs_errors.get(action.nargs, default)
-            raise ArgumentError(action, msg)
-
-        # return the number of arguments matched
-        return len(match.group(1))
-
-    def _match_arguments_partial(self, actions, arg_strings_pattern):
-        # progressively shorten the actions list by slicing off the
-        # final actions until we find a match
-        result = []
-        for i in range(len(actions), 0, -1):
-            actions_slice = actions[:i]
-            pattern = ''.join([self._get_nargs_pattern(action)
-                               for action in actions_slice])
-            match = _re.match(pattern, arg_strings_pattern)
-            if match is not None:
-                result.extend([len(string) for string in match.groups()])
-                break
-
-        # return the list of arg string counts
-        return result
-
-    def _parse_optional(self, arg_string):
-        # if it's an empty string, it was meant to be a positional
-        if not arg_string:
-            return None
-
-        # if it doesn't start with a prefix, it was meant to be positional
-        if not arg_string[0] in self.prefix_chars:
-            return None
-
-        # if the option string is present in the parser, return the action
-        if arg_string in self._option_string_actions:
-            action = self._option_string_actions[arg_string]
-            return action, arg_string, None
-
-        # if it's just a single character, it was meant to be positional
-        if len(arg_string) == 1:
-            return None
-
-        # if the option string before the "=" is present, return the action
-        if '=' in arg_string:
-            option_string, explicit_arg = arg_string.split('=', 1)
-            if option_string in self._option_string_actions:
-                action = self._option_string_actions[option_string]
-                return action, option_string, explicit_arg
-
-        # search through all possible prefixes of the option string
-        # and all actions in the parser for possible interpretations
-        option_tuples = self._get_option_tuples(arg_string)
-
-        # if multiple actions match, the option string was ambiguous
-        if len(option_tuples) > 1:
-            options = ', '.join([option_string
-                for action, option_string, explicit_arg in option_tuples])
-            tup = arg_string, options
-            self.error(_('ambiguous option: %s could match %s') % tup)
-
-        # if exactly one action matched, this segmentation is good,
-        # so return the parsed action
-        elif len(option_tuples) == 1:
-            option_tuple, = option_tuples
-            return option_tuple
-
-        # if it was not found as an option, but it looks like a negative
-        # number, it was meant to be positional
-        # unless there are negative-number-like options
-        if self._negative_number_matcher.match(arg_string):
-            if not self._has_negative_number_optionals:
-                return None
-
-        # if it contains a space, it was meant to be a positional
-        if ' ' in arg_string:
-            return None
-
-        # it was meant to be an optional but there is no such option
-        # in this parser (though it might be a valid option in a subparser)
-        return None, arg_string, None
-
-    def _get_option_tuples(self, option_string):
-        result = []
-
-        # option strings starting with two prefix characters are only
-        # split at the '='
-        chars = self.prefix_chars
-        if option_string[0] in chars and option_string[1] in chars:
-            if '=' in option_string:
-                option_prefix, explicit_arg = option_string.split('=', 1)
-            else:
-                option_prefix = option_string
-                explicit_arg = None
-            for option_string in self._option_string_actions:
-                if option_string.startswith(option_prefix):
-                    action = self._option_string_actions[option_string]
-                    tup = action, option_string, explicit_arg
-                    result.append(tup)
-
-        # single character options can be concatenated with their arguments
-        # but multiple character options always have to have their argument
-        # separate
-        elif option_string[0] in chars and option_string[1] not in chars:
-            option_prefix = option_string
-            explicit_arg = None
-            short_option_prefix = option_string[:2]
-            short_explicit_arg = option_string[2:]
-
-            for option_string in self._option_string_actions:
-                if option_string == short_option_prefix:
-                    action = self._option_string_actions[option_string]
-                    tup = action, option_string, short_explicit_arg
-                    result.append(tup)
-                elif option_string.startswith(option_prefix):
-                    action = self._option_string_actions[option_string]
-                    tup = action, option_string, explicit_arg
-                    result.append(tup)
-
-        # shouldn't ever get here
-        else:
-            self.error(_('unexpected option string: %s') % option_string)
-
-        # return the collected option tuples
-        return result
-
-    def _get_nargs_pattern(self, action):
-        # in all examples below, we have to allow for '--' args
-        # which are represented as '-' in the pattern
-        nargs = action.nargs
-
-        # the default (None) is assumed to be a single argument
-        if nargs is None:
-            nargs_pattern = '(-*A-*)'
-
-        # allow zero or one arguments
-        elif nargs == OPTIONAL:
-            nargs_pattern = '(-*A?-*)'
-
-        # allow zero or more arguments
-        elif nargs == ZERO_OR_MORE:
-            nargs_pattern = '(-*[A-]*)'
-
-        # allow one or more arguments
-        elif nargs == ONE_OR_MORE:
-            nargs_pattern = '(-*A[A-]*)'
-
-        # allow any number of options or arguments
-        elif nargs == REMAINDER:
-            nargs_pattern = '([-AO]*)'
-
-        # allow one argument followed by any number of options or arguments
-        elif nargs == PARSER:
-            nargs_pattern = '(-*A[-AO]*)'
-
-        # all others should be integers
-        else:
-            nargs_pattern = '(-*%s-*)' % '-*'.join('A' * nargs)
-
-        # if this is an optional action, -- is not allowed
-        if action.option_strings:
-            nargs_pattern = nargs_pattern.replace('-*', '')
-            nargs_pattern = nargs_pattern.replace('-', '')
-
-        # return the pattern
-        return nargs_pattern
-
-    # ========================
-    # Value conversion methods
-    # ========================
-    def _get_values(self, action, arg_strings):
-        # for everything but PARSER args, strip out '--'
-        if action.nargs not in [PARSER, REMAINDER]:
-            arg_strings = [s for s in arg_strings if s != '--']
-
-        # optional argument produces a default when not present
-        if not arg_strings and action.nargs == OPTIONAL:
-            if action.option_strings:
-                value = action.const
-            else:
-                value = action.default
-            if isinstance(value, basestring):
-                value = self._get_value(action, value)
-                self._check_value(action, value)
-
-        # when nargs='*' on a positional, if there were no command-line
-        # args, use the default if it is anything other than None
-        elif (not arg_strings and action.nargs == ZERO_OR_MORE and
-              not action.option_strings):
-            if action.default is not None:
-                value = action.default
-            else:
-                value = arg_strings
-            self._check_value(action, value)
-
-        # single argument or optional argument produces a single value
-        elif len(arg_strings) == 1 and action.nargs in [None, OPTIONAL]:
-            arg_string, = arg_strings
-            value = self._get_value(action, arg_string)
-            self._check_value(action, value)
-
-        # REMAINDER arguments convert all values, checking none
-        elif action.nargs == REMAINDER:
-            value = [self._get_value(action, v) for v in arg_strings]
-
-        # PARSER arguments convert all values, but check only the first
-        elif action.nargs == PARSER:
-            value = [self._get_value(action, v) for v in arg_strings]
-            self._check_value(action, value[0])
-
-        # all other types of nargs produce a list
-        else:
-            value = [self._get_value(action, v) for v in arg_strings]
-            for v in value:
-                self._check_value(action, v)
-
-        # return the converted value
-        return value
-
-    def _get_value(self, action, arg_string):
-        type_func = self._registry_get('type', action.type, action.type)
-        if not _callable(type_func):
-            msg = _('%r is not callable')
-            raise ArgumentError(action, msg % type_func)
-
-        # convert the value to the appropriate type
-        try:
-            result = type_func(arg_string)
-
-        # ArgumentTypeErrors indicate errors
-        except ArgumentTypeError:
-            name = getattr(action.type, '__name__', repr(action.type))
-            msg = str(_sys.exc_info()[1])
-            raise ArgumentError(action, msg)
-
-        # TypeErrors or ValueErrors also indicate errors
-        except (TypeError, ValueError):
-            name = getattr(action.type, '__name__', repr(action.type))
-            msg = _('invalid %s value: %r')
-            raise ArgumentError(action, msg % (name, arg_string))
-
-        # return the converted value
-        return result
-
-    def _check_value(self, action, value):
-        # converted value must be one of the choices (if specified)
-        if action.choices is not None and value not in action.choices:
-            tup = value, ', '.join(map(repr, action.choices))
-            msg = _('invalid choice: %r (choose from %s)') % tup
-            raise ArgumentError(action, msg)
-
-    # =======================
-    # Help-formatting methods
-    # =======================
-    def format_usage(self):
-        formatter = self._get_formatter()
-        formatter.add_usage(self.usage, self._actions,
-                            self._mutually_exclusive_groups)
-        return formatter.format_help()
-
-    def format_help(self):
-        formatter = self._get_formatter()
-
-        # usage
-        formatter.add_usage(self.usage, self._actions,
-                            self._mutually_exclusive_groups)
-
-        # description
-        formatter.add_text(self.description)
-
-        # positionals, optionals and user-defined groups
-        for action_group in self._action_groups:
-            formatter.start_section(action_group.title)
-            formatter.add_text(action_group.description)
-            formatter.add_arguments(action_group._group_actions)
-            formatter.end_section()
-
-        # epilog
-        formatter.add_text(self.epilog)
-
-        # determine help from format above
-        return formatter.format_help()
-
-    def format_version(self):
-        import warnings
-        warnings.warn(
-            'The format_version method is deprecated -- the "version" '
-            'argument to ArgumentParser is no longer supported.',
-            DeprecationWarning)
-        formatter = self._get_formatter()
-        formatter.add_text(self.version)
-        return formatter.format_help()
-
-    def _get_formatter(self):
-        return self.formatter_class(prog=self.prog)
-
-    # =====================
-    # Help-printing methods
-    # =====================
-    def print_usage(self, file=None):
-        if file is None:
-            file = _sys.stdout
-        self._print_message(self.format_usage(), file)
-
-    def print_help(self, file=None):
-        if file is None:
-            file = _sys.stdout
-        self._print_message(self.format_help(), file)
-
-    def print_version(self, file=None):
-        import warnings
-        warnings.warn(
-            'The print_version method is deprecated -- the "version" '
-            'argument to ArgumentParser is no longer supported.',
-            DeprecationWarning)
-        self._print_message(self.format_version(), file)
-
-    def _print_message(self, message, file=None):
-        if message:
-            if file is None:
-                file = _sys.stderr
-            file.write(message)
-
-    # ===============
-    # Exiting methods
-    # ===============
-    def exit(self, status=0, message=None):
-        if message:
-            self._print_message(message, _sys.stderr)
-        _sys.exit(status)
-
-    def error(self, message):
-        """error(message: string)
-
-        Prints a usage message incorporating the message to stderr and
-        exits.
-
-        If you override this in a subclass, it should not return -- it
-        should either exit or raise an exception.
-        """
-        self.print_usage(_sys.stderr)
-        self.exit(2, _('%s: error: %s\n') % (self.prog, message))
diff --git a/lib/taurus/external/enum/enum/__init__.py b/lib/taurus/external/enum/enum/__init__.py
deleted file mode 100644
index cbc3fba..0000000
--- a/lib/taurus/external/enum/enum/__init__.py
+++ /dev/null
@@ -1,809 +0,0 @@
-# Copyright (c) 2013, Ethan Furman.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-#    Redistributions of source code must retain the above
-#    copyright notice, this list of conditions and the
-#    following disclaimer.
-#
-#    Redistributions in binary form must reproduce the above
-#    copyright notice, this list of conditions and the following
-#    disclaimer in the documentation and/or other materials
-#    provided with the distribution.
-#
-#    Neither the name Ethan Furman nor the names of any
-#    contributors may be used to endorse or promote products
-#    derived from this software without specific prior written
-#    permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-
-"""Python Enumerations"""
-
-import sys as _sys
-
-__all__ = ['Enum', 'IntEnum', 'unique']
-
-pyver = float('%s.%s' % _sys.version_info[:2])
-
-try:
-    any
-except NameError:
-    def any(iterable):
-        for element in iterable:
-            if element:
-                return True
-        return False
-
-try:
-    from collections import OrderedDict
-except ImportError:
-    OrderedDict = None
-
-try:
-    basestring
-except NameError:
-    # In Python 2 basestring is the ancestor of both str and unicode
-    # in Python 3 it's just str, but was missing in 3.1
-    basestring = str
-
-class _RouteClassAttributeToGetattr(object):
-    """Route attribute access on a class to __getattr__.
-
-    This is a descriptor, used to define attributes that act differently when
-    accessed through an instance and through a class.  Instance access remains
-    normal, but access to an attribute through a class will be routed to the
-    class's __getattr__ method; this is done by raising AttributeError.
-
-    """
-    def __init__(self, fget=None):
-        self.fget = fget
-
-    def __get__(self, instance, ownerclass=None):
-        if instance is None:
-            raise AttributeError()
-        return self.fget(instance)
-
-    def __set__(self, instance, value):
-        raise AttributeError("can't set attribute")
-
-    def __delete__(self, instance):
-        raise AttributeError("can't delete attribute")
-
-
-def _is_descriptor(obj):
-    """Returns True if obj is a descriptor, False otherwise."""
-    return (
-            hasattr(obj, '__get__') or
-            hasattr(obj, '__set__') or
-            hasattr(obj, '__delete__'))
-
-
-def _is_dunder(name):
-    """Returns True if a __dunder__ name, False otherwise."""
-    return (name[:2] == name[-2:] == '__' and
-            name[2:3] != '_' and
-            name[-3:-2] != '_' and
-            len(name) > 4)
-
-
-def _is_sunder(name):
-    """Returns True if a _sunder_ name, False otherwise."""
-    return (name[0] == name[-1] == '_' and
-            name[1:2] != '_' and
-            name[-2:-1] != '_' and
-            len(name) > 2)
-
-
-def _make_class_unpicklable(cls):
-    """Make the given class un-picklable."""
-    def _break_on_call_reduce(self, protocol=None):
-        raise TypeError('%r cannot be pickled' % self)
-    cls.__reduce_ex__ = _break_on_call_reduce
-    #cls.__reduce__ = _break_on_call_reduce
-    cls.__module__ = '<unknown>'
-
-
-class _EnumDict(dict):
-    """Track enum member order and ensure member names are not reused.
-
-    EnumMeta will use the names found in self._member_names as the
-    enumeration member names.
-
-    """
-    def __init__(self):
-        super(_EnumDict, self).__init__()
-        self._member_names = []
-
-    def __setitem__(self, key, value):
-        """Changes anything not dundered or not a descriptor.
-
-        If a descriptor is added with the same name as an enum member, the name
-        is removed from _member_names (this may leave a hole in the numerical
-        sequence of values).
-
-        If an enum member name is used twice, an error is raised; duplicate
-        values are not checked for.
-
-        Single underscore (sunder) names are reserved.
-
-        Note:   in 3.x __order__ is simply discarded as a not necessary piece
-                leftover from 2.x
-
-        """
-        if pyver >= 3.0 and key == '__order__':
-            return
-        if _is_sunder(key):
-            raise ValueError('_names_ are reserved for future Enum use')
-        elif _is_dunder(key):
-            pass
-        elif key in self._member_names:
-            # descriptor overwriting an enum?
-            raise TypeError('Attempted to reuse key: %r' % key)
-        elif not _is_descriptor(value):
-            if key in self:
-                # enum overwriting a descriptor?
-                raise TypeError('Key already defined as: %r' % self[key])
-            self._member_names.append(key)
-        super(_EnumDict, self).__setitem__(key, value)
-
-
-# Dummy value for Enum as EnumMeta explicity checks for it, but of course until
-# EnumMeta finishes running the first time the Enum class doesn't exist.  This
-# is also why there are checks in EnumMeta like `if Enum is not None`
-Enum = None
-
-
-class EnumMeta(type):
-    """Metaclass for Enum"""
-    @classmethod
-    def __prepare__(metacls, cls, bases):
-        return _EnumDict()
-
-    def __new__(metacls, cls, bases, classdict):
-        # an Enum class is final once enumeration items have been defined; it
-        # cannot be mixed with other types (int, float, etc.) if it has an
-        # inherited __new__ unless a new __new__ is defined (or the resulting
-        # class will fail).
-        if type(classdict) is dict:
-            original_dict = classdict
-            classdict = _EnumDict()
-            for k, v in original_dict.items():
-                classdict[k] = v
-
-        member_type, first_enum = metacls._get_mixins_(bases)
-        #if member_type is object:
-        #    use_args = False
-        #else:
-        #    use_args = True
-        __new__, save_new, use_args = metacls._find_new_(classdict, member_type,
-                                                        first_enum)
-        # save enum items into separate mapping so they don't get baked into
-        # the new class
-        members = dict((k, classdict[k]) for k in classdict._member_names)
-        for name in classdict._member_names:
-            del classdict[name]
-
-        # py2 support for definition order
-        __order__ = classdict.get('__order__')
-        if __order__ is None:
-            __order__ = classdict._member_names
-            if pyver < 3.0:
-                order_specified = False
-            else:
-                order_specified = True
-        else:
-            del classdict['__order__']
-            order_specified = True
-            if pyver < 3.0:
-                __order__ = __order__.replace(',', ' ').split()
-                aliases = [name for name in members if name not in __order__]
-                __order__ += aliases
-
-        # check for illegal enum names (any others?)
-        invalid_names = set(members) & set(['mro'])
-        if invalid_names:
-            raise ValueError('Invalid enum member name(s): %s' % (
-                ', '.join(invalid_names), ))
-
-        # create our new Enum type
-        enum_class = super(EnumMeta, metacls).__new__(metacls, cls, bases, classdict)
-        enum_class._member_names_ = []               # names in random order
-        if order_specified and OrderedDict is not None:
-            enum_class._member_map_ = OrderedDict()
-        else:
-            enum_class._member_map_ = {}             # name->value map
-        enum_class._member_type_ = member_type
-
-        # Reverse value->name map for hashable values.
-        enum_class._value2member_map_ = {}
-
-        # instantiate them, checking for duplicates as we go
-        # we instantiate first instead of checking for duplicates first in case
-        # a custom __new__ is doing something funky with the values -- such as
-        # auto-numbering ;)
-        if __new__ is None:
-            __new__ = enum_class.__new__
-        for member_name in __order__:
-            value = members[member_name]
-            if not isinstance(value, tuple):
-                args = (value, )
-            else:
-                args = value
-            if member_type is tuple:   # special case for tuple enums
-                args = (args, )     # wrap it one more time
-            if not use_args or not args:
-                enum_member = __new__(enum_class)
-                if not hasattr(enum_member, '_value_'):
-                    enum_member._value_ = value
-            else:
-                enum_member = __new__(enum_class, *args)
-                if not hasattr(enum_member, '_value_'):
-                    enum_member._value_ = member_type(*args)
-            value = enum_member._value_
-            enum_member._name_ = member_name
-            enum_member.__objclass__ = enum_class
-            enum_member.__init__(*args)
-            # If another member with the same value was already defined, the
-            # new member becomes an alias to the existing one.
-            for name, canonical_member in enum_class._member_map_.items():
-                if canonical_member.value == enum_member._value_:
-                    enum_member = canonical_member
-                    break
-            else:
-                # Aliases don't appear in member names (only in __members__).
-                enum_class._member_names_.append(member_name)
-            enum_class._member_map_[member_name] = enum_member
-            try:
-                # This may fail if value is not hashable. We can't add the value
-                # to the map, and by-value lookups for this value will be
-                # linear.
-                enum_class._value2member_map_[value] = enum_member
-            except TypeError:
-                pass
-
-        # in Python2.x we cannot know definition order, so go with value order
-        # unless __order__ was specified in the class definition
-        if not order_specified:
-            enum_class._member_names_ = [
-                e[0] for e in sorted(
-                [(name, enum_class._member_map_[name]) for name in enum_class._member_names_],
-                 key=lambda t: t[1]._value_
-                        )]
-
-        # double check that repr and friends are not the mixin's or various
-        # things break (such as pickle)
-        if Enum is not None:
-            setattr(enum_class, '__getnewargs__', Enum.__getnewargs__)
-            setattr(enum_class, '__reduce_ex__', Enum.__reduce_ex__)
-        for name in ('__repr__', '__str__', '__format__', ):
-            class_method = getattr(enum_class, name)
-            obj_method = getattr(member_type, name, None)
-            enum_method = getattr(first_enum, name, None)
-            if obj_method is not None and obj_method is class_method:
-                setattr(enum_class, name, enum_method)
-
-        # check for a __getnewargs__, and if not present sabotage
-        # pickling, since it won't work anyway
-        if member_type is not object:
-            methods = ('__getnewargs_ex__', '__getnewargs__',
-                    '__reduce_ex__', '__reduce__')
-            if not any(map(member_type.__dict__.get, methods)):
-                _make_class_unpicklable(enum_class)
-
-        # method resolution and int's are not playing nice
-        # Python's less than 2.6 use __cmp__
-
-        if pyver < 2.6:
-
-            if issubclass(enum_class, int):
-                setattr(enum_class, '__cmp__', getattr(int, '__cmp__'))
-
-        elif pyver < 3.0:
-
-            if issubclass(enum_class, int):
-                for method in (
-                        '__le__',
-                        '__lt__',
-                        '__gt__',
-                        '__ge__',
-                        '__eq__',
-                        '__ne__',
-                        '__hash__',
-                        ):
-                    setattr(enum_class, method, getattr(int, method))
-
-        # replace any other __new__ with our own (as long as Enum is not None,
-        # anyway) -- again, this is to support pickle
-        if Enum is not None:
-            # if the user defined their own __new__, save it before it gets
-            # clobbered in case they subclass later
-            if save_new:
-                setattr(enum_class, '__member_new__', enum_class.__dict__['__new__'])
-            setattr(enum_class, '__new__', Enum.__dict__['__new__'])
-        return enum_class
-
-    def __call__(cls, value, names=None, module=None, type=None):
-        """Either returns an existing member, or creates a new enum class.
-
-        This method is used both when an enum class is given a value to match
-        to an enumeration member (i.e. Color(3)) and for the functional API
-        (i.e. Color = Enum('Color', names='red green blue')).
-
-        When used for the functional API: `module`, if set, will be stored in
-        the new class' __module__ attribute; `type`, if set, will be mixed in
-        as the first base class.
-
-        Note: if `module` is not set this routine will attempt to discover the
-        calling module by walking the frame stack; if this is unsuccessful
-        the resulting class will not be pickleable.
-
-        """
-        if names is None:  # simple value lookup
-            return cls.__new__(cls, value)
-        # otherwise, functional API: we're creating a new Enum type
-        return cls._create_(value, names, module=module, type=type)
-
-    def __contains__(cls, member):
-        return isinstance(member, cls) and member.name in cls._member_map_
-
-    def __delattr__(cls, attr):
-        # nicer error message when someone tries to delete an attribute
-        # (see issue19025).
-        if attr in cls._member_map_:
-            raise AttributeError(
-                    "%s: cannot delete Enum member." % cls.__name__)
-        super(EnumMeta, cls).__delattr__(attr)
-
-    def __dir__(self):
-        return (['__class__', '__doc__', '__members__', '__module__'] +
-                self._member_names_)
-
-    @property
-    def __members__(cls):
-        """Returns a mapping of member name->value.
-
-        This mapping lists all enum members, including aliases. Note that this
-        is a copy of the internal mapping.
-
-        """
-        return cls._member_map_.copy()
-
-    def __getattr__(cls, name):
-        """Return the enum member matching `name`
-
-        We use __getattr__ instead of descriptors or inserting into the enum
-        class' __dict__ in order to support `name` and `value` being both
-        properties for enum members (which live in the class' __dict__) and
-        enum members themselves.
-
-        """
-        if _is_dunder(name):
-            raise AttributeError(name)
-        try:
-            return cls._member_map_[name]
-        except KeyError:
-            raise AttributeError(name)
-
-    def __getitem__(cls, name):
-        return cls._member_map_[name]
-
-    def __iter__(cls):
-        return (cls._member_map_[name] for name in cls._member_names_)
-
-    def __reversed__(cls):
-        return (cls._member_map_[name] for name in reversed(cls._member_names_))
-
-    def __len__(cls):
-        return len(cls._member_names_)
-
-    def __repr__(cls):
-        return "<enum %r>" % cls.__name__
-
-    def __setattr__(cls, name, value):
-        """Block attempts to reassign Enum members.
-
-        A simple assignment to the class namespace only changes one of the
-        several possible ways to get an Enum member from the Enum class,
-        resulting in an inconsistent Enumeration.
-
-        """
-        member_map = cls.__dict__.get('_member_map_', {})
-        if name in member_map:
-            raise AttributeError('Cannot reassign members.')
-        super(EnumMeta, cls).__setattr__(name, value)
-
-    def _create_(cls, class_name, names=None, module=None, type=None):
-        """Convenience method to create a new Enum class.
-
-        `names` can be:
-
-        * A string containing member names, separated either with spaces or
-          commas.  Values are auto-numbered from 1.
-        * An iterable of member names.  Values are auto-numbered from 1.
-        * An iterable of (member name, value) pairs.
-        * A mapping of member name -> value.
-
-        """
-        metacls = cls.__class__
-        if type is None:
-            bases = (cls, )
-        else:
-            bases = (type, cls)
-        classdict = metacls.__prepare__(class_name, bases)
-        __order__ = []
-
-        # special processing needed for names?
-        if isinstance(names, basestring):
-            names = names.replace(',', ' ').split()
-        if isinstance(names, (tuple, list)) and isinstance(names[0], basestring):
-            names = [(e, i+1) for (i, e) in enumerate(names)]
-
-        # Here, names is either an iterable of (name, value) or a mapping.
-        for item in names:
-            if isinstance(item, basestring):
-                member_name, member_value = item, names[item]
-            else:
-                member_name, member_value = item
-            classdict[member_name] = member_value
-            __order__.append(member_name)
-        # only set __order__ in classdict if name/value was not from a mapping
-        if not isinstance(item, basestring):
-            classdict['__order__'] = ' '.join(__order__)
-        enum_class = metacls.__new__(metacls, class_name, bases, classdict)
-
-        # TODO: replace the frame hack if a blessed way to know the calling
-        # module is ever developed
-        if module is None:
-            try:
-                module = _sys._getframe(2).f_globals['__name__']
-            except (AttributeError, ValueError):
-                pass
-        if module is None:
-            _make_class_unpicklable(enum_class)
-        else:
-            enum_class.__module__ = module
-
-        return enum_class
-
-    @staticmethod
-    def _get_mixins_(bases):
-        """Returns the type for creating enum members, and the first inherited
-        enum class.
-
-        bases: the tuple of bases that was given to __new__
-
-        """
-        if not bases or Enum is None:
-            return object, Enum
-
-
-        # double check that we are not subclassing a class with existing
-        # enumeration members; while we're at it, see if any other data
-        # type has been mixed in so we can use the correct __new__
-        member_type = first_enum = None
-        for base in bases:
-            if  (base is not Enum and
-                    issubclass(base, Enum) and
-                    base._member_names_):
-                raise TypeError("Cannot extend enumerations")
-        # base is now the last base in bases
-        if not issubclass(base, Enum):
-            raise TypeError("new enumerations must be created as "
-                    "`ClassName([mixin_type,] enum_type)`")
-
-        # get correct mix-in type (either mix-in type of Enum subclass, or
-        # first base if last base is Enum)
-        if not issubclass(bases[0], Enum):
-            member_type = bases[0]     # first data type
-            first_enum = bases[-1]  # enum type
-        else:
-            for base in bases[0].__mro__:
-                # most common: (IntEnum, int, Enum, object)
-                # possible:    (<Enum 'AutoIntEnum'>, <Enum 'IntEnum'>,
-                #               <class 'int'>, <Enum 'Enum'>,
-                #               <class 'object'>)
-                if issubclass(base, Enum):
-                    if first_enum is None:
-                        first_enum = base
-                else:
-                    if member_type is None:
-                        member_type = base
-
-        return member_type, first_enum
-
-    if pyver < 3.0:
-        @staticmethod
-        def _find_new_(classdict, member_type, first_enum):
-            """Returns the __new__ to be used for creating the enum members.
-
-            classdict: the class dictionary given to __new__
-            member_type: the data type whose __new__ will be used by default
-            first_enum: enumeration to check for an overriding __new__
-
-            """
-            # now find the correct __new__, checking to see of one was defined
-            # by the user; also check earlier enum classes in case a __new__ was
-            # saved as __member_new__
-            __new__ = classdict.get('__new__', None)
-            if __new__:
-                return None, True, True      # __new__, save_new, use_args
-
-            N__new__ = getattr(None, '__new__')
-            O__new__ = getattr(object, '__new__')
-            if Enum is None:
-                E__new__ = N__new__
-            else:
-                E__new__ = Enum.__dict__['__new__']
-            # check all possibles for __member_new__ before falling back to
-            # __new__
-            for method in ('__member_new__', '__new__'):
-                for possible in (member_type, first_enum):
-                    try:
-                        target = possible.__dict__[method]
-                    except (AttributeError, KeyError):
-                        target = getattr(possible, method, None)
-                    if target not in [
-                            None,
-                            N__new__,
-                            O__new__,
-                            E__new__,
-                            ]:
-                        if method == '__member_new__':
-                            classdict['__new__'] = target
-                            return None, False, True
-                        if isinstance(target, staticmethod):
-                            target = target.__get__(member_type)
-                        __new__ = target
-                        break
-                if __new__ is not None:
-                    break
-            else:
-                __new__ = object.__new__
-
-            # if a non-object.__new__ is used then whatever value/tuple was
-            # assigned to the enum member name will be passed to __new__ and to the
-            # new enum member's __init__
-            if __new__ is object.__new__:
-                use_args = False
-            else:
-                use_args = True
-
-            return __new__, False, use_args
-    else:
-        @staticmethod
-        def _find_new_(classdict, member_type, first_enum):
-            """Returns the __new__ to be used for creating the enum members.
-
-            classdict: the class dictionary given to __new__
-            member_type: the data type whose __new__ will be used by default
-            first_enum: enumeration to check for an overriding __new__
-
-            """
-            # now find the correct __new__, checking to see of one was defined
-            # by the user; also check earlier enum classes in case a __new__ was
-            # saved as __member_new__
-            __new__ = classdict.get('__new__', None)
-
-            # should __new__ be saved as __member_new__ later?
-            save_new = __new__ is not None
-
-            if __new__ is None:
-                # check all possibles for __member_new__ before falling back to
-                # __new__
-                for method in ('__member_new__', '__new__'):
-                    for possible in (member_type, first_enum):
-                        target = getattr(possible, method, None)
-                        if target not in (
-                                None,
-                                None.__new__,
-                                object.__new__,
-                                Enum.__new__,
-                                ):
-                            __new__ = target
-                            break
-                    if __new__ is not None:
-                        break
-                else:
-                    __new__ = object.__new__
-
-            # if a non-object.__new__ is used then whatever value/tuple was
-            # assigned to the enum member name will be passed to __new__ and to the
-            # new enum member's __init__
-            if __new__ is object.__new__:
-                use_args = False
-            else:
-                use_args = True
-
-            return __new__, save_new, use_args
-
-
-########################################################
-# In order to support Python 2 and 3 with a single
-# codebase we have to create the Enum methods separately
-# and then use the `type(name, bases, dict)` method to
-# create the class.
-########################################################
-temp_enum_dict = {}
-temp_enum_dict['__doc__'] = "Generic enumeration.\n\n    Derive from this class to define new enumerations.\n\n"
-
-def __new__(cls, value):
-    # all enum instances are actually created during class construction
-    # without calling this method; this method is called by the metaclass'
-    # __call__ (i.e. Color(3) ), and by pickle
-    if type(value) is cls:
-        # For lookups like Color(Color.red)
-        value = value.value
-        #return value
-    # by-value search for a matching enum member
-    # see if it's in the reverse mapping (for hashable values)
-    try:
-        if value in cls._value2member_map_:
-            return cls._value2member_map_[value]
-    except TypeError:
-        # not there, now do long search -- O(n) behavior
-        for member in cls._member_map_.values():
-            if member.value == value:
-                return member
-    raise ValueError("%s is not a valid %s" % (value, cls.__name__))
-temp_enum_dict['__new__'] = __new__
-del __new__
-
-def __repr__(self):
-    return "<%s.%s: %r>" % (
-            self.__class__.__name__, self._name_, self._value_)
-temp_enum_dict['__repr__'] = __repr__
-del __repr__
-
-def __str__(self):
-    return "%s.%s" % (self.__class__.__name__, self._name_)
-temp_enum_dict['__str__'] = __str__
-del __str__
-
-def __dir__(self):
-    added_behavior = [m for m in self.__class__.__dict__ if m[0] != '_']
-    return (['__class__', '__doc__', '__module__', 'name', 'value'] + added_behavior)
-temp_enum_dict['__dir__'] = __dir__
-del __dir__
-
-def __format__(self, format_spec):
-    # mixed-in Enums should use the mixed-in type's __format__, otherwise
-    # we can get strange results with the Enum name showing up instead of
-    # the value
-
-    # pure Enum branch
-    if self._member_type_ is object:
-        cls = str
-        val = str(self)
-    # mix-in branch
-    else:
-        cls = self._member_type_
-        val = self.value
-    return cls.__format__(val, format_spec)
-temp_enum_dict['__format__'] = __format__
-del __format__
-
-
-####################################
-# Python's less than 2.6 use __cmp__
-
-if pyver < 2.6:
-
-    def __cmp__(self, other):
-        if type(other) is self.__class__:
-            if self is other:
-                return 0
-            return -1
-        return NotImplemented
-        raise TypeError("unorderable types: %s() and %s()" % (self.__class__.__name__, other.__class__.__name__))
-    temp_enum_dict['__cmp__'] = __cmp__
-    del __cmp__
-
-else:
-
-    def __le__(self, other):
-        raise TypeError("unorderable types: %s() <= %s()" % (self.__class__.__name__, other.__class__.__name__))
-    temp_enum_dict['__le__'] = __le__
-    del __le__
-
-    def __lt__(self, other):
-        raise TypeError("unorderable types: %s() < %s()" % (self.__class__.__name__, other.__class__.__name__))
-    temp_enum_dict['__lt__'] = __lt__
-    del __lt__
-
-    def __ge__(self, other):
-        raise TypeError("unorderable types: %s() >= %s()" % (self.__class__.__name__, other.__class__.__name__))
-    temp_enum_dict['__ge__'] = __ge__
-    del __ge__
-
-    def __gt__(self, other):
-        raise TypeError("unorderable types: %s() > %s()" % (self.__class__.__name__, other.__class__.__name__))
-    temp_enum_dict['__gt__'] = __gt__
-    del __gt__
-
-
-def __eq__(self, other):
-    if type(other) is self.__class__:
-        return self is other
-    return NotImplemented
-temp_enum_dict['__eq__'] = __eq__
-del __eq__
-
-def __ne__(self, other):
-    if type(other) is self.__class__:
-        return self is not other
-    return NotImplemented
-temp_enum_dict['__ne__'] = __ne__
-del __ne__
-
-def __getnewargs__(self):
-    return (self._value_, )
-temp_enum_dict['__getnewargs__'] = __getnewargs__
-del __getnewargs__
-
-def __hash__(self):
-    return hash(self._name_)
-temp_enum_dict['__hash__'] = __hash__
-del __hash__
-
-def __reduce_ex__(self, proto):
-    return self.__class__, self.__getnewargs__()
-temp_enum_dict['__reduce_ex__'] = __reduce_ex__
-del __reduce_ex__
-
-# _RouteClassAttributeToGetattr is used to provide access to the `name`
-# and `value` properties of enum members while keeping some measure of
-# protection from modification, while still allowing for an enumeration
-# to have members named `name` and `value`.  This works because enumeration
-# members are not set directly on the enum class -- __getattr__ is
-# used to look them up.
-
- at _RouteClassAttributeToGetattr
-def name(self):
-    return self._name_
-temp_enum_dict['name'] = name
-del name
-
- at _RouteClassAttributeToGetattr
-def value(self):
-    return self._value_
-temp_enum_dict['value'] = value
-del value
-
-Enum = EnumMeta('Enum', (object, ), temp_enum_dict)
-del temp_enum_dict
-
-# Enum has now been created
-###########################
-
-class IntEnum(int, Enum):
-    """Enum where members are also (and must be) ints"""
-
-
-def unique(enumeration):
-    """Class decorator that ensures only unique members exist in an enumeration."""
-    duplicates = []
-    for name, member in enumeration.__members__.items():
-        if name != member.name:
-            duplicates.append((name, member.name))
-    if duplicates:
-        duplicate_names = ', '.join(
-                ["%s -> %s" % (alias, name) for (alias, name) in duplicates]
-                )
-        raise ValueError('duplicate names found in %r: %s' %
-                (enumeration, duplicate_names)
-                )
-    return enumeration
diff --git a/lib/taurus/external/ordereddict/ordereddict.py b/lib/taurus/external/ordereddict/ordereddict.py
deleted file mode 100644
index f09d261..0000000
--- a/lib/taurus/external/ordereddict/ordereddict.py
+++ /dev/null
@@ -1,153 +0,0 @@
-# -*- coding: utf-8 -*-
-
-##############################################################################
-##
-## This file is part of Taurus
-##
-## http://taurus-scada.org
-##
-## Copyright 2011 CELLS / ALBA Synchrotron, Bellaterra, Spain
-##
-## Taurus is free software: you can redistribute it and/or modify
-## it under the terms of the GNU Lesser General Public License as published by
-## the Free Software Foundation, either version 3 of the License, or
-## (at your option) any later version.
-##
-## Taurus is distributed in the hope that it will be useful,
-## but WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-## GNU Lesser General Public License for more details.
-##
-## You should have received a copy of the GNU Lesser General Public License
-## along with Taurus.  If not, see <http://www.gnu.org/licenses/>.
-##
-##############################################################################
-
-# Copyright (c) 2009 Raymond Hettinger
-#
-# Permission is hereby granted, free of charge, to any person
-# obtaining a copy of this software and associated documentation files
-# (the "Software"), to deal in the Software without restriction,
-# including without limitation the rights to use, copy, modify, merge,
-# publish, distribute, sublicense, and/or sell copies of the Software,
-# and to permit persons to whom the Software is furnished to do so,
-# subject to the following conditions:
-#
-#     The above copyright notice and this permission notice shall be
-#     included in all copies or substantial portions of the Software.
-#
-#     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-#     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-#     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-#     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-#     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-#     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-#     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-#     OTHER DEALINGS IN THE SOFTWARE.
-
-from UserDict import DictMixin
-
-
-class OrderedDict(dict, DictMixin):
-
-    def __init__(self, *args, **kwds):
-        if len(args) > 1:
-            raise TypeError('expected at most 1 arguments, got %d' % len(args))
-        try:
-            self.__end
-        except AttributeError:
-            self.clear()
-        self.update(*args, **kwds)
-
-    def clear(self):
-        self.__end = end = []
-        end += [None, end, end]  # sentinel node for doubly linked list
-        self.__map = {}  # key --> [key, prev, next]
-        dict.clear(self)
-
-    def __setitem__(self, key, value):
-        if key not in self:
-            end = self.__end
-            curr = end[1]
-            curr[2] = end[1] = self.__map[key] = [key, curr, end]
-        dict.__setitem__(self, key, value)
-
-    def __delitem__(self, key):
-        dict.__delitem__(self, key)
-        key, prev_, next_ = self.__map.pop(key)
-        prev_[2] = next_
-        next_[1] = prev_
-
-    def __iter__(self):
-        end = self.__end
-        curr = end[2]
-        while curr is not end:
-            yield curr[0]
-            curr = curr[2]
-
-    def __reversed__(self):
-        end = self.__end
-        curr = end[1]
-        while curr is not end:
-            yield curr[0]
-            curr = curr[1]
-
-    def popitem(self, last=True):
-        if not self:
-            raise KeyError('dictionary is empty')
-        if last:
-            key = reversed(self).next()
-        else:
-            key = iter(self).next()
-        value = self.pop(key)
-        return key, value
-
-    def __reduce__(self):
-        items = [[k, self[k]] for k in self]
-        tmp = self.__map, self.__end
-        del self.__map, self.__end
-        inst_dict = vars(self).copy()
-        self.__map, self.__end = tmp
-        if inst_dict:
-            return (self.__class__, (items,), inst_dict)
-        return self.__class__, (items,)
-
-    def keys(self):
-        return list(self)
-
-    setdefault = DictMixin.setdefault
-    update = DictMixin.update
-    pop = DictMixin.pop
-    values = DictMixin.values
-    items = DictMixin.items
-    iterkeys = DictMixin.iterkeys
-    itervalues = DictMixin.itervalues
-    iteritems = DictMixin.iteritems
-
-    def __repr__(self):
-        if not self:
-            return '%s()' % (self.__class__.__name__,)
-        return '%s(%r)' % (self.__class__.__name__, self.items())
-
-    def copy(self):
-        return self.__class__(self)
-
-    @classmethod
-    def fromkeys(cls, iterable, value=None):
-        d = cls()
-        for key in iterable:
-            d[key] = value
-        return d
-
-    def __eq__(self, other):
-        if isinstance(other, OrderedDict):
-            if len(self) != len(other):
-                return False
-            for p, q in  zip(self.items(), other.items()):
-                if p != q:
-                    return False
-            return True
-        return dict.__eq__(self, other)
-
-    def __ne__(self, other):
-        return not self == other
diff --git a/lib/taurus/external/pint/pint_local/AUTHORS b/lib/taurus/external/pint/pint_local/AUTHORS
deleted file mode 100644
index 6c7f068..0000000
--- a/lib/taurus/external/pint/pint_local/AUTHORS
+++ /dev/null
@@ -1,41 +0,0 @@
-Pint is written and maintained by Hernan E. Grecco <hernan.grecco at gmail.com>.
-
-Other contributors, listed alphabetically, are:
-
-* Aaron Coleman
-* Alexander Böhn <fish2000 at gmail.com>
-* Ana Krivokapic <akrivokapic1 at gmail.com>
-* Andrea Zonca <code at andreazonca.com>
-* Brend Wanders <b.wanders at utwente.nl>
-* choloepus
-* coutinho <coutinho at esrf.fr>
-* Daniel Sokolowski <daniel.sokolowski at danols.com>
-* Dave Brooks <dave at bcs.co.nz>
-* David Linke
-* Ed Schofield <ed at pythoncharmers.com>
-* Eduard Bopp <eduard.bopp at aepsil0n.de>
-* Eli <elifab at gmail.com>
-* Felix Hummel <felix at felixhummel.de>
-* Giel van Schijndel <me at mortis.eu>
-* James Rowe <jnrowe at gmail.com>
-* Jim Turner <jturner314 at gmail.com>
-* Joel B. Mohler <joel at kiwistrawberry.us>
-* John David Reaver <jdreaver at adlerhorst.com>
-* Jonas Olson <jolson at kth.se>
-* Kaido Kert <kaidokert at gmail.com>
-* Kenneth D. Mankoff <mankoff at gmail.com>
-* Kevin Davies <kdavies4 at gmail.com>
-* Luke Campbell <luke.s.campbell at gmail.com>
-* Matthieu Dartiailh <marul at laposte.net>
-* Nate Bogdanowicz <natezb at gmail.com>
-* Peter Grayson <jpgrayson at gmail.com>
-* Richard Barnes <rbarnes at umn.edu>
-* Ryan Dwyer <ryanpdwyer at gmail.com>
-* Ryan Kingsbury <RyanSKingsbury at alumni.unc.edu>
-* Sundar Raman <cybertoast at gmail.com>
-* Tiago Coutinho <coutinho at esrf.fr>
-* Thomas Kluyver <takowl at gmail.com>
-* Tom Ritchford <tom at swirly.com>
-* Virgil Dupras <virgil.dupras at savoirfairelinux.com>
-
-(If you think that your name belongs here, please let the maintainer know)
diff --git a/lib/taurus/external/pint/pint_local/LICENSE b/lib/taurus/external/pint/pint_local/LICENSE
deleted file mode 100644
index 49aec52..0000000
--- a/lib/taurus/external/pint/pint_local/LICENSE
+++ /dev/null
@@ -1,33 +0,0 @@
-Copyright (c) 2012 by Hernan E. Grecco and contributors.  See AUTHORS
-for more details.
-
-Some rights reserved.
-
-Redistribution and use in source and binary forms of the software as well
-as documentation, with or without modification, are permitted provided
-that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright
-  notice, this list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the following
-  disclaimer in the documentation and/or other materials provided
-  with the distribution.
-
-* The names of the contributors may not be used to endorse or
-  promote products derived from this software without specific
-  prior written permission.
-
-THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND
-CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
-NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
-OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE AND DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGE.
diff --git a/lib/taurus/external/pint/pint_local/__init__.py b/lib/taurus/external/pint/pint_local/__init__.py
deleted file mode 100644
index ba4e847..0000000
--- a/lib/taurus/external/pint/pint_local/__init__.py
+++ /dev/null
@@ -1,126 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    pint
-    ~~~~
-
-    Pint is Python module/package to define, operate and manipulate
-    **physical quantities**: the product of a numerical value and a
-    unit of measurement. It allows arithmetic operations between them
-    and conversions from and to different units.
-
-    :copyright: (c) 2012 by Hernan E. Grecco.
-    :license: BSD, see LICENSE for more details.
-"""
-from __future__ import with_statement
-import os
-import subprocess
-import pkg_resources
-from .formatting import formatter
-from .unit import (UnitRegistry, LazyRegistry)
-from .errors import (DimensionalityError, OffsetUnitCalculusError,
-                   UndefinedUnitError)
-from .util import pi_theorem, logger
-
-from .context import Context
-
-
-try:                # pragma: no cover
-    __version__ = pkg_resources.get_distribution('pint').version
-except:             # pragma: no cover
-    # we seem to have a local copy not installed without setuptools
-    # so the reported version will be unknown
-    __version__ = "unknown"
-
-
-#: A Registry with the default units and constants.
-_DEFAULT_REGISTRY = LazyRegistry()
-
-#: Registry used for unpickling operations.
-_APP_REGISTRY = _DEFAULT_REGISTRY
-
-
-def _build_quantity(value, units):
-    """Build Quantity using the Application registry.
-    Used only for unpickling operations.
-    """
-    global _APP_REGISTRY
-    return _APP_REGISTRY.Quantity(value, units)
-
-
-def set_application_registry(registry):
-    """Set the application registry which is used for unpickling operations.
-
-    :param registry: a UnitRegistry instance.
-    """
-    assert isinstance(registry, UnitRegistry)
-    global _APP_REGISTRY
-    logger.debug('Changing app registry from %r to %r.', _APP_REGISTRY, registry)
-    _APP_REGISTRY = registry
-
-
-def _run_pyroma(data):   # pragma: no cover
-    """Run pyroma (used to perform checks before releasing a new version).
-    """
-    import sys
-    from zest.releaser.utils import ask
-    if not ask("Run pyroma on the package before uploading?"):
-        return
-    try:
-        from pyroma import run
-        result = run(data['tagdir'])
-        if result != 10:
-            if not ask("Continue?"):
-                sys.exit(1)
-    except ImportError:
-        if not ask("pyroma not available. Continue?"):
-            sys.exit(1)
-
-
-def _check_travis(data):   # pragma: no cover
-    """Check if Travis reports that everything is ok.
-    (used to perform checks before releasing a new version).
-    """
-    import json
-    import sys
-
-    from zest.releaser.utils import system, ask
-    if not ask('Check with Travis before releasing?'):
-        return
-
-    try:
-        # Python 3
-        from urllib.request import urlopen
-        def get(url):
-            return urlopen(url).read().decode('utf-8')
-
-    except ImportError:
-        # Python 2
-        from urllib2 import urlopen
-        def get(url):
-            return urlopen(url).read()
-
-    url = 'https://api.github.com/repos/%s/%s/status/%s'
-
-    username = 'hgrecco'
-    repo = 'pint'
-    commit = system('git rev-parse HEAD')
-
-    try:
-        result = json.loads(get(url % (username, repo, commit)))['state']
-        print('Travis says: %s' % result)
-        if result != 'success':
-            if not ask('Do you want to continue anyway?', default=False):
-                sys.exit(1)
-    except Exception:
-        print('Could not determine the commit state with Travis.')
-        if ask('Do you want to continue anyway?', default=False):
-            sys.exit(1)
-
-
-def test():
-    """Run all tests.
-
-    :return: a :class:`unittest.TestResult` object
-    """
-    from .testsuite import run
-    return run()
diff --git a/lib/taurus/external/pint/pint_local/compat/__init__.py b/lib/taurus/external/pint/pint_local/compat/__init__.py
deleted file mode 100644
index 7442967..0000000
--- a/lib/taurus/external/pint/pint_local/compat/__init__.py
+++ /dev/null
@@ -1,129 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    pint.compat
-    ~~~~~~~~~~~
-
-    Compatibility layer.
-
-    :copyright: 2013 by Pint Authors, see AUTHORS for more details.
-    :license: BSD, see LICENSE for more details.
-"""
-
-from __future__ import division, unicode_literals, print_function, absolute_import
-
-import sys
-
-from io import BytesIO
-from numbers import Number
-from decimal import Decimal
-
-from . import tokenize
-
-ENCODING_TOKEN = tokenize.ENCODING
-
-PYTHON3 = sys.version >= '3'
-
-def tokenizer(input_string):
-    for tokinfo in tokenize.tokenize(BytesIO(input_string.encode('utf-8')).readline):
-        if tokinfo.type == ENCODING_TOKEN:
-            continue
-        yield tokinfo
-
-
-if PYTHON3:
-    string_types = str
-
-    def u(x):
-        return x
-
-    maketrans = str.maketrans
-
-    long_type = int
-else:
-    string_types = basestring
-
-    import codecs
-
-    def u(x):
-        return codecs.unicode_escape_decode(x)[0]
-
-    maketrans = lambda f, t: dict((ord(a), b) for a, b in zip(f, t))
-
-    long_type = long
-
-if sys.version_info < (2, 7):
-    try:
-        import unittest2 as unittest
-    except ImportError:
-        raise Exception("Testing Pint in Python 2.6 requires package 'unittest2'")
-else:
-    import unittest
-
-
-try:
-    from collections import Chainmap
-except ImportError:
-    from .chainmap import ChainMap
-
-try:
-    from functools import lru_cache
-except ImportError:
-    from .lrucache import lru_cache
-
-try:
-    from logging import NullHandler
-except ImportError:
-    from .nullhandler import NullHandler
-
-try:
-    from itertools import zip_longest
-except ImportError:
-    from itertools import izip_longest as zip_longest
-
-try:
-    import numpy as np
-    from numpy import ndarray
-
-    HAS_NUMPY = True
-    NUMPY_VER = np.__version__
-    NUMERIC_TYPES = (Number, Decimal, ndarray, np.number)
-
-    def _to_magnitude(value, force_ndarray=False):
-        if isinstance(value, (dict, bool)) or value is None:
-            raise TypeError('Invalid magnitude for Quantity: {0!r}'.format(value))
-        elif isinstance(value, string_types) and value == '':
-            raise ValueError('Quantity magnitude cannot be an empty string.')
-        elif isinstance(value, (list, tuple)):
-            return np.asarray(value)
-        if force_ndarray:
-            return np.asarray(value)
-        return value
-
-except ImportError:
-
-    np = None
-
-    class ndarray(object):
-        pass
-
-    HAS_NUMPY = False
-    NUMPY_VER = '0'
-    NUMERIC_TYPES = (Number, Decimal)
-
-    def _to_magnitude(value, force_ndarray=False):
-        if isinstance(value, (dict, bool)) or value is None:
-            raise TypeError('Invalid magnitude for Quantity: {0!r}'.format(value))
-        elif isinstance(value, string_types) and value == '':
-            raise ValueError('Quantity magnitude cannot be an empty string.')
-        elif isinstance(value, (list, tuple)):
-            raise TypeError('lists and tuples are valid magnitudes for '
-                             'Quantity only when NumPy is present.')
-        return value
-
-try:
-    from uncertainties import ufloat
-    HAS_UNCERTAINTIES = True
-except ImportError:
-    ufloat = None
-    HAS_UNCERTAINTIES = False
-
diff --git a/lib/taurus/external/pint/pint_local/compat/chainmap.py b/lib/taurus/external/pint/pint_local/compat/chainmap.py
deleted file mode 100644
index f4c9a4e..0000000
--- a/lib/taurus/external/pint/pint_local/compat/chainmap.py
+++ /dev/null
@@ -1,153 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    pint.compat.chainmap
-    ~~~~~~~~~~~~~~~~~~~~
-
-    Taken from the Python 3.3 source code.
-
-    :copyright: 2013, PSF
-    :license: PSF License
-"""
-
-from __future__ import division, unicode_literals, print_function, absolute_import
-
-import sys
-
-from collections import MutableMapping
-if sys.version_info < (3, 0):
-    from thread import get_ident
-elif sys.version_info < (3, 3):
-    from _thread import get_ident
-else:
-    from threading import get_ident
-
-
-def _recursive_repr(fillvalue='...'):
-    'Decorator to make a repr function return fillvalue for a recursive call'
-
-    def decorating_function(user_function):
-        repr_running = set()
-
-        def wrapper(self):
-            key = id(self), get_ident()
-            if key in repr_running:
-                return fillvalue
-            repr_running.add(key)
-            try:
-                result = user_function(self)
-            finally:
-                repr_running.discard(key)
-            return result
-
-        # Can't use functools.wraps() here because of bootstrap issues
-        wrapper.__module__ = getattr(user_function, '__module__')
-        wrapper.__doc__ = getattr(user_function, '__doc__')
-        wrapper.__name__ = getattr(user_function, '__name__')
-        wrapper.__annotations__ = getattr(user_function, '__annotations__', {})
-        return wrapper
-
-    return decorating_function
-
-
-class ChainMap(MutableMapping):
-    ''' A ChainMap groups multiple dicts (or other mappings) together
-    to create a single, updateable view.
-
-    The underlying mappings are stored in a list.  That list is public and can
-    accessed or updated using the *maps* attribute.  There is no other state.
-
-    Lookups search the underlying mappings successively until a key is found.
-    In contrast, writes, updates, and deletions only operate on the first
-    mapping.
-
-    '''
-
-    def __init__(self, *maps):
-        '''Initialize a ChainMap by setting *maps* to the given mappings.
-        If no mappings are provided, a single empty dictionary is used.
-
-        '''
-        self.maps = list(maps) or [{}]          # always at least one map
-
-    def __missing__(self, key):
-        raise KeyError(key)
-
-    def __getitem__(self, key):
-        for mapping in self.maps:
-            try:
-                return mapping[key]             # can't use 'key in mapping' with defaultdict
-            except KeyError:
-                pass
-        return self.__missing__(key)            # support subclasses that define __missing__
-
-    def get(self, key, default=None):
-        return self[key] if key in self else default
-
-    def __len__(self):
-        return len(set().union(*self.maps))     # reuses stored hash values if possible
-
-    def __iter__(self):
-        return iter(set().union(*self.maps))
-
-    def __contains__(self, key):
-        return any(key in m for m in self.maps)
-
-    def __bool__(self):
-        return any(self.maps)
-
-    @_recursive_repr()
-    def __repr__(self):
-        return '{0.__class__.__name__}({1})'.format(
-            self, ', '.join(map(repr, self.maps)))
-
-    @classmethod
-    def fromkeys(cls, iterable, *args):
-        'Create a ChainMap with a single dict created from the iterable.'
-        return cls(dict.fromkeys(iterable, *args))
-
-    def copy(self):
-        'New ChainMap or subclass with a new copy of maps[0] and refs to maps[1:]'
-        return self.__class__(self.maps[0].copy(), *self.maps[1:])
-
-    __copy__ = copy
-
-    def new_child(self, m=None):                # like Django's _Context.push()
-        '''
-        New ChainMap with a new map followed by all previous maps. If no
-        map is provided, an empty dict is used.
-        '''
-        if m is None:
-            m = {}
-        return self.__class__(m, *self.maps)
-
-    @property
-    def parents(self):                          # like Django's _Context.pop()
-        'New ChainMap from maps[1:].'
-        return self.__class__(*self.maps[1:])
-
-    def __setitem__(self, key, value):
-        self.maps[0][key] = value
-
-    def __delitem__(self, key):
-        try:
-            del self.maps[0][key]
-        except KeyError:
-            raise KeyError('Key not found in the first mapping: {!r}'.format(key))
-
-    def popitem(self):
-        'Remove and return an item pair from maps[0]. Raise KeyError is maps[0] is empty.'
-        try:
-            return self.maps[0].popitem()
-        except KeyError:
-            raise KeyError('No keys found in the first mapping.')
-
-    def pop(self, key, *args):
-        'Remove *key* from maps[0] and return its value. Raise KeyError if *key* not in maps[0].'
-        try:
-            return self.maps[0].pop(key, *args)
-        except KeyError:
-            raise KeyError('Key not found in the first mapping: {!r}'.format(key))
-
-    def clear(self):
-        'Clear maps[0], leaving maps[1:] intact.'
-        self.maps[0].clear()
diff --git a/lib/taurus/external/pint/pint_local/compat/lrucache.py b/lib/taurus/external/pint/pint_local/compat/lrucache.py
deleted file mode 100644
index 868b598..0000000
--- a/lib/taurus/external/pint/pint_local/compat/lrucache.py
+++ /dev/null
@@ -1,177 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    pint.compat.lrucache
-    ~~~~~~~~~~~~~~~~~~~~
-
-    LRU (least recently used) cache backport.
-
-    From https://code.activestate.com/recipes/578078-py26-and-py30-backport-of-python-33s-lru-cache/
-
-    :copyright: 2004, Raymond Hettinger,
-    :license: MIT License
-"""
-
-from collections import namedtuple
-from functools import update_wrapper
-from threading import RLock
-
-_CacheInfo = namedtuple("CacheInfo", ["hits", "misses", "maxsize", "currsize"])
-
-class _HashedSeq(list):
-    __slots__ = 'hashvalue'
-
-    def __init__(self, tup, hash=hash):
-        self[:] = tup
-        self.hashvalue = hash(tup)
-
-    def __hash__(self):
-        return self.hashvalue
-
-def _make_key(args, kwds, typed,
-             kwd_mark = (object(),),
-             fasttypes = set((int, str, frozenset, type(None))),
-             sorted=sorted, tuple=tuple, type=type, len=len):
-    'Make a cache key from optionally typed positional and keyword arguments'
-    key = args
-    if kwds:
-        sorted_items = sorted(kwds.items())
-        key += kwd_mark
-        for item in sorted_items:
-            key += item
-    if typed:
-        key += tuple(type(v) for v in args)
-        if kwds:
-            key += tuple(type(v) for k, v in sorted_items)
-    elif len(key) == 1 and type(key[0]) in fasttypes:
-        return key[0]
-    return _HashedSeq(key)
-
-def lru_cache(maxsize=100, typed=False):
-    """Least-recently-used cache decorator.
-
-    If *maxsize* is set to None, the LRU features are disabled and the cache
-    can grow without bound.
-
-    If *typed* is True, arguments of different types will be cached separately.
-    For example, f(3.0) and f(3) will be treated as distinct calls with
-    distinct results.
-
-    Arguments to the cached function must be hashable.
-
-    View the cache statistics named tuple (hits, misses, maxsize, currsize) with
-    f.cache_info().  Clear the cache and statistics with f.cache_clear().
-    Access the underlying function with f.__wrapped__.
-
-    See:  http://en.wikipedia.org/wiki/Cache_algorithms#Least_Recently_Used
-
-    """
-
-    # Users should only access the lru_cache through its public API:
-    #       cache_info, cache_clear, and f.__wrapped__
-    # The internals of the lru_cache are encapsulated for thread safety and
-    # to allow the implementation to change (including a possible C version).
-
-    def decorating_function(user_function):
-
-        cache = dict()
-        stats = [0, 0]                  # make statistics updateable non-locally
-        HITS, MISSES = 0, 1             # names for the stats fields
-        make_key = _make_key
-        cache_get = cache.get           # bound method to lookup key or return None
-        _len = len                      # localize the global len() function
-        lock = RLock()                  # because linkedlist updates aren't threadsafe
-        root = []                       # root of the circular doubly linked list
-        root[:] = [root, root, None, None]      # initialize by pointing to self
-        nonlocal_root = [root]                  # make updateable non-locally
-        PREV, NEXT, KEY, RESULT = 0, 1, 2, 3    # names for the link fields
-
-        if maxsize == 0:
-
-            def wrapper(*args, **kwds):
-                # no caching, just do a statistics update after a successful call
-                result = user_function(*args, **kwds)
-                stats[MISSES] += 1
-                return result
-
-        elif maxsize is None:
-
-            def wrapper(*args, **kwds):
-                # simple caching without ordering or size limit
-                key = make_key(args, kwds, typed)
-                result = cache_get(key, root)   # root used here as a unique not-found sentinel
-                if result is not root:
-                    stats[HITS] += 1
-                    return result
-                result = user_function(*args, **kwds)
-                cache[key] = result
-                stats[MISSES] += 1
-                return result
-
-        else:
-
-            def wrapper(*args, **kwds):
-                # size limited caching that tracks accesses by recency
-                key = make_key(args, kwds, typed) if kwds or typed else args
-                with lock:
-                    link = cache_get(key)
-                    if link is not None:
-                        # record recent use of the key by moving it to the front of the list
-                        root, = nonlocal_root
-                        link_prev, link_next, key, result = link
-                        link_prev[NEXT] = link_next
-                        link_next[PREV] = link_prev
-                        last = root[PREV]
-                        last[NEXT] = root[PREV] = link
-                        link[PREV] = last
-                        link[NEXT] = root
-                        stats[HITS] += 1
-                        return result
-                result = user_function(*args, **kwds)
-                with lock:
-                    root, = nonlocal_root
-                    if key in cache:
-                        # getting here means that this same key was added to the
-                        # cache while the lock was released.  since the link
-                        # update is already done, we need only return the
-                        # computed result and update the count of misses.
-                        pass
-                    elif _len(cache) >= maxsize:
-                        # use the old root to store the new key and result
-                        oldroot = root
-                        oldroot[KEY] = key
-                        oldroot[RESULT] = result
-                        # empty the oldest link and make it the new root
-                        root = nonlocal_root[0] = oldroot[NEXT]
-                        oldkey = root[KEY]
-                        oldvalue = root[RESULT]
-                        root[KEY] = root[RESULT] = None
-                        # now update the cache dictionary for the new links
-                        del cache[oldkey]
-                        cache[key] = oldroot
-                    else:
-                        # put result in a new link at the front of the list
-                        last = root[PREV]
-                        link = [last, root, key, result]
-                        last[NEXT] = root[PREV] = cache[key] = link
-                    stats[MISSES] += 1
-                return result
-
-        def cache_info():
-            """Report cache statistics"""
-            with lock:
-                return _CacheInfo(stats[HITS], stats[MISSES], maxsize, len(cache))
-
-        def cache_clear():
-            """Clear the cache and cache statistics"""
-            with lock:
-                cache.clear()
-                root = nonlocal_root[0]
-                root[:] = [root, root, None, None]
-                stats[:] = [0, 0]
-
-        wrapper.__wrapped__ = user_function
-        wrapper.cache_info = cache_info
-        wrapper.cache_clear = cache_clear
-        return update_wrapper(wrapper, user_function)
-
-    return decorating_function
diff --git a/lib/taurus/external/pint/pint_local/compat/nullhandler.py b/lib/taurus/external/pint/pint_local/compat/nullhandler.py
deleted file mode 100644
index 288cbb3..0000000
--- a/lib/taurus/external/pint/pint_local/compat/nullhandler.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    pint.compat.nullhandler
-    ~~~~~~~~~~~~~~~~~~~~~~~
-
-    Taken from the Python 2.7 source code.
-
-    :copyright: 2013, PSF
-    :license: PSF License
-"""
-
-
-import logging
-
-class NullHandler(logging.Handler):
-    """
-    This handler does nothing. It's intended to be used to avoid the
-    "No handlers could be found for logger XXX" one-off warning. This is
-    important for library code, which may contain code to log events. If a user
-    of the library does not configure logging, the one-off warning might be
-    produced; to avoid this, the library developer simply needs to instantiate
-    a NullHandler and add it to the top-level logger of the library module or
-    package.
-    """
-    def handle(self, record):
-        pass
-
-    def emit(self, record):
-        pass
-
-    def createLock(self):
-        self.lock = None
diff --git a/lib/taurus/external/pint/pint_local/compat/tokenize.py b/lib/taurus/external/pint/pint_local/compat/tokenize.py
deleted file mode 100644
index 3166224..0000000
--- a/lib/taurus/external/pint/pint_local/compat/tokenize.py
+++ /dev/null
@@ -1,640 +0,0 @@
-"""Tokenization help for Python programs.
-
-tokenize(readline) is a generator that breaks a stream of bytes into
-Python tokens.  It decodes the bytes according to PEP-0263 for
-determining source file encoding.
-
-It accepts a readline-like method which is called repeatedly to get the
-next line of input (or b"" for EOF).  It generates 5-tuples with these
-members:
-
-    the token type (see token.py)
-    the token (a string)
-    the starting (row, column) indices of the token (a 2-tuple of ints)
-    the ending (row, column) indices of the token (a 2-tuple of ints)
-    the original line (string)
-
-It is designed to match the working of the Python tokenizer exactly, except
-that it produces COMMENT tokens for comments and gives type OP for all
-operators.  Additionally, all token lists start with an ENCODING token
-which tells you which encoding was used to decode the bytes stream.
-"""
-
-__author__ = 'Ka-Ping Yee <ping at lfw.org>'
-__credits__ = ('GvR, ESR, Tim Peters, Thomas Wouters, Fred Drake, '
-               'Skip Montanaro, Raymond Hettinger, Trent Nelson, '
-               'Michael Foord')
-
-from codecs import lookup, BOM_UTF8
-import collections
-import io
-from io import TextIOWrapper
-from itertools import chain
-import re
-import sys
-from token import *
-
-try:
-    reASCII = re.ASCII
-except:
-    reASCII = 0
-
-
-try:
-    unicode
-    _name_re = re.compile(r"\w*$", re.UNICODE)
-    def isidentifier(s):
-        if s[0] in '0123456789':
-            return False
-        return bool(_name_re.match(s))
-except NameError:
-    def isidentifier(s):
-        return s.isidentifier()
-
-
-cookie_re = re.compile(r'^[ \t\f]*#.*coding[:=][ \t]*([-\w.]+)', reASCII)
-blank_re = re.compile(br'^[ \t\f]*(?:[#\r\n]|$)', reASCII)
-
-COMMENT = N_TOKENS
-tok_name[COMMENT] = 'COMMENT'
-NL = N_TOKENS + 1
-tok_name[NL] = 'NL'
-ENCODING = N_TOKENS + 2
-tok_name[ENCODING] = 'ENCODING'
-N_TOKENS += 3
-EXACT_TOKEN_TYPES = {
-    '(':   LPAR,
-    ')':   RPAR,
-    '[':   LSQB,
-    ']':   RSQB,
-    ':':   COLON,
-    ',':   COMMA,
-    ';':   SEMI,
-    '+':   PLUS,
-    '-':   MINUS,
-    '*':   STAR,
-    '/':   SLASH,
-    '|':   VBAR,
-    '&':   AMPER,
-    '<':   LESS,
-    '>':   GREATER,
-    '=':   EQUAL,
-    '.':   DOT,
-    '%':   PERCENT,
-    '{':   LBRACE,
-    '}':   RBRACE,
-    '==':  EQEQUAL,
-    '!=':  NOTEQUAL,
-    '<=':  LESSEQUAL,
-    '>=':  GREATEREQUAL,
-    '~':   TILDE,
-    '^':   CIRCUMFLEX,
-    '<<':  LEFTSHIFT,
-    '>>':  RIGHTSHIFT,
-    '**':  DOUBLESTAR,
-    '+=':  PLUSEQUAL,
-    '-=':  MINEQUAL,
-    '*=':  STAREQUAL,
-    '/=':  SLASHEQUAL,
-    '%=':  PERCENTEQUAL,
-    '&=':  AMPEREQUAL,
-    '|=':  VBAREQUAL,
-    '^=': CIRCUMFLEXEQUAL,
-    '<<=': LEFTSHIFTEQUAL,
-    '>>=': RIGHTSHIFTEQUAL,
-    '**=': DOUBLESTAREQUAL,
-    '//':  DOUBLESLASH,
-    '//=': DOUBLESLASHEQUAL,
-    '@':   AT
-}
-
-class TokenInfo(collections.namedtuple('TokenInfo', 'type string start end line')):
-    def __repr__(self):
-        annotated_type = '%d (%s)' % (self.type, tok_name[self.type])
-        return ('TokenInfo(type=%s, string=%r, start=%r, end=%r, line=%r)' %
-                self._replace(type=annotated_type))
-
-    @property
-    def exact_type(self):
-        if self.type == OP and self.string in EXACT_TOKEN_TYPES:
-            return EXACT_TOKEN_TYPES[self.string]
-        else:
-            return self.type
-
-def group(*choices): return '(' + '|'.join(choices) + ')'
-def any(*choices): return group(*choices) + '*'
-def maybe(*choices): return group(*choices) + '?'
-
-# Note: we use unicode matching for names ("\w") but ascii matching for
-# number literals.
-Whitespace = r'[ \f\t]*'
-Comment = r'#[^\r\n]*'
-Ignore = Whitespace + any(r'\\\r?\n' + Whitespace) + maybe(Comment)
-Name = r'\w+'
-
-Hexnumber = r'0[xX][0-9a-fA-F]+'
-Binnumber = r'0[bB][01]+'
-Octnumber = r'0[oO][0-7]+'
-Decnumber = r'(?:0+|[1-9][0-9]*)'
-Intnumber = group(Hexnumber, Binnumber, Octnumber, Decnumber)
-Exponent = r'[eE][-+]?[0-9]+'
-Pointfloat = group(r'[0-9]+\.[0-9]*', r'\.[0-9]+') + maybe(Exponent)
-Expfloat = r'[0-9]+' + Exponent
-Floatnumber = group(Pointfloat, Expfloat)
-Imagnumber = group(r'[0-9]+[jJ]', Floatnumber + r'[jJ]')
-Number = group(Imagnumber, Floatnumber, Intnumber)
-
-StringPrefix = r'(?:[bB][rR]?|[rR][bB]?|[uU])?'
-
-# Tail end of ' string.
-Single = r"[^'\\]*(?:\\.[^'\\]*)*'"
-# Tail end of " string.
-Double = r'[^"\\]*(?:\\.[^"\\]*)*"'
-# Tail end of ''' string.
-Single3 = r"[^'\\]*(?:(?:\\.|'(?!''))[^'\\]*)*'''"
-# Tail end of """ string.
-Double3 = r'[^"\\]*(?:(?:\\.|"(?!""))[^"\\]*)*"""'
-Triple = group(StringPrefix + "'''", StringPrefix + '"""')
-# Single-line ' or " string.
-String = group(StringPrefix + r"'[^\n'\\]*(?:\\.[^\n'\\]*)*'",
-               StringPrefix + r'"[^\n"\\]*(?:\\.[^\n"\\]*)*"')
-
-# Because of leftmost-then-longest match semantics, be sure to put the
-# longest operators first (e.g., if = came before ==, == would get
-# recognized as two instances of =).
-Operator = group(r"\*\*=?", r">>=?", r"<<=?", r"!=",
-                 r"//=?", r"->",
-                 r"[+\-*/%&|^=<>]=?",
-                 r"~")
-
-Bracket = '[][(){}]'
-Special = group(r'\r?\n', r'\.\.\.', r'[:;.,@]')
-Funny = group(Operator, Bracket, Special)
-
-PlainToken = group(Number, Funny, String, Name)
-Token = Ignore + PlainToken
-
-# First (or only) line of ' or " string.
-ContStr = group(StringPrefix + r"'[^\n'\\]*(?:\\.[^\n'\\]*)*" +
-                group("'", r'\\\r?\n'),
-                StringPrefix + r'"[^\n"\\]*(?:\\.[^\n"\\]*)*' +
-                group('"', r'\\\r?\n'))
-PseudoExtras = group(r'\\\r?\n|\Z', Comment, Triple)
-PseudoToken = Whitespace + group(PseudoExtras, Number, Funny, ContStr, Name)
-
-def _compile(expr):
-    return re.compile(expr, re.UNICODE)
-
-endpats = {"'": Single, '"': Double,
-           "'''": Single3, '"""': Double3,
-           "r'''": Single3, 'r"""': Double3,
-           "b'''": Single3, 'b"""': Double3,
-           "R'''": Single3, 'R"""': Double3,
-           "B'''": Single3, 'B"""': Double3,
-           "br'''": Single3, 'br"""': Double3,
-           "bR'''": Single3, 'bR"""': Double3,
-           "Br'''": Single3, 'Br"""': Double3,
-           "BR'''": Single3, 'BR"""': Double3,
-           "rb'''": Single3, 'rb"""': Double3,
-           "Rb'''": Single3, 'Rb"""': Double3,
-           "rB'''": Single3, 'rB"""': Double3,
-           "RB'''": Single3, 'RB"""': Double3,
-           "u'''": Single3, 'u"""': Double3,
-           "R'''": Single3, 'R"""': Double3,
-           "U'''": Single3, 'U"""': Double3,
-           'r': None, 'R': None, 'b': None, 'B': None,
-           'u': None, 'U': None}
-
-triple_quoted = {}
-for t in ("'''", '"""',
-          "r'''", 'r"""', "R'''", 'R"""',
-          "b'''", 'b"""', "B'''", 'B"""',
-          "br'''", 'br"""', "Br'''", 'Br"""',
-          "bR'''", 'bR"""', "BR'''", 'BR"""',
-          "rb'''", 'rb"""', "rB'''", 'rB"""',
-          "Rb'''", 'Rb"""', "RB'''", 'RB"""',
-          "u'''", 'u"""', "U'''", 'U"""',
-          ):
-    triple_quoted[t] = t
-single_quoted = {}
-for t in ("'", '"',
-          "r'", 'r"', "R'", 'R"',
-          "b'", 'b"', "B'", 'B"',
-          "br'", 'br"', "Br'", 'Br"',
-          "bR'", 'bR"', "BR'", 'BR"' ,
-          "rb'", 'rb"', "rB'", 'rB"',
-          "Rb'", 'Rb"', "RB'", 'RB"' ,
-          "u'", 'u"', "U'", 'U"',
-          ):
-    single_quoted[t] = t
-
-tabsize = 8
-
-class TokenError(Exception): pass
-
-class StopTokenizing(Exception): pass
-
-
-class Untokenizer:
-
-    def __init__(self):
-        self.tokens = []
-        self.prev_row = 1
-        self.prev_col = 0
-        self.encoding = None
-
-    def add_whitespace(self, start):
-        row, col = start
-        if row < self.prev_row or row == self.prev_row and col < self.prev_col:
-            raise ValueError("start ({},{}) precedes previous end ({},{})"
-                             .format(row, col, self.prev_row, self.prev_col))
-        row_offset = row - self.prev_row
-        if row_offset:
-            self.tokens.append("\\\n" * row_offset)
-            self.prev_col = 0
-        col_offset = col - self.prev_col
-        if col_offset:
-            self.tokens.append(" " * col_offset)
-
-    def untokenize(self, iterable):
-        it = iter(iterable)
-        for t in it:
-            if len(t) == 2:
-                self.compat(t, it)
-                break
-            tok_type, token, start, end, line = t
-            if tok_type == ENCODING:
-                self.encoding = token
-                continue
-            if tok_type == ENDMARKER:
-                break
-            self.add_whitespace(start)
-            self.tokens.append(token)
-            self.prev_row, self.prev_col = end
-            if tok_type in (NEWLINE, NL):
-                self.prev_row += 1
-                self.prev_col = 0
-        return "".join(self.tokens)
-
-    def compat(self, token, iterable):
-        indents = []
-        toks_append = self.tokens.append
-        startline = token[0] in (NEWLINE, NL)
-        prevstring = False
-
-        for tok in chain([token], iterable):
-            toknum, tokval = tok[:2]
-            if toknum == ENCODING:
-                self.encoding = tokval
-                continue
-
-            if toknum in (NAME, NUMBER):
-                tokval += ' '
-
-            # Insert a space between two consecutive strings
-            if toknum == STRING:
-                if prevstring:
-                    tokval = ' ' + tokval
-                prevstring = True
-            else:
-                prevstring = False
-
-            if toknum == INDENT:
-                indents.append(tokval)
-                continue
-            elif toknum == DEDENT:
-                indents.pop()
-                continue
-            elif toknum in (NEWLINE, NL):
-                startline = True
-            elif startline and indents:
-                toks_append(indents[-1])
-                startline = False
-            toks_append(tokval)
-
-
-def untokenize(iterable):
-    """Transform tokens back into Python source code.
-    It returns a bytes object, encoded using the ENCODING
-    token, which is the first token sequence output by tokenize.
-
-    Each element returned by the iterable must be a token sequence
-    with at least two elements, a token number and token value.  If
-    only two tokens are passed, the resulting output is poor.
-
-    Round-trip invariant for full input:
-        Untokenized source will match input source exactly
-
-    Round-trip invariant for limited intput:
-        # Output bytes will tokenize the back to the input
-        t1 = [tok[:2] for tok in tokenize(f.readline)]
-        newcode = untokenize(t1)
-        readline = BytesIO(newcode).readline
-        t2 = [tok[:2] for tok in tokenize(readline)]
-        assert t1 == t2
-    """
-    ut = Untokenizer()
-    out = ut.untokenize(iterable)
-    if ut.encoding is not None:
-        out = out.encode(ut.encoding)
-    return out
-
-
-def _get_normal_name(orig_enc):
-    """Imitates get_normal_name in tokenizer.c."""
-    # Only care about the first 12 characters.
-    enc = orig_enc[:12].lower().replace("_", "-")
-    if enc == "utf-8" or enc.startswith("utf-8-"):
-        return "utf-8"
-    if enc in ("latin-1", "iso-8859-1", "iso-latin-1") or \
-       enc.startswith(("latin-1-", "iso-8859-1-", "iso-latin-1-")):
-        return "iso-8859-1"
-    return orig_enc
-
-def detect_encoding(readline):
-    """
-    The detect_encoding() function is used to detect the encoding that should
-    be used to decode a Python source file.  It requires one argument, readline,
-    in the same way as the tokenize() generator.
-
-    It will call readline a maximum of twice, and return the encoding used
-    (as a string) and a list of any lines (left as bytes) it has read in.
-
-    It detects the encoding from the presence of a utf-8 bom or an encoding
-    cookie as specified in pep-0263.  If both a bom and a cookie are present,
-    but disagree, a SyntaxError will be raised.  If the encoding cookie is an
-    invalid charset, raise a SyntaxError.  Note that if a utf-8 bom is found,
-    'utf-8-sig' is returned.
-
-    If no encoding is specified, then the default of 'utf-8' will be returned.
-    """
-    try:
-        filename = readline.__self__.name
-    except AttributeError:
-        filename = None
-    bom_found = False
-    encoding = None
-    default = 'utf-8'
-    def read_or_stop():
-        try:
-            return readline()
-        except StopIteration:
-            return b''
-
-    def find_cookie(line):
-        try:
-            # Decode as UTF-8. Either the line is an encoding declaration,
-            # in which case it should be pure ASCII, or it must be UTF-8
-            # per default encoding.
-            line_string = line.decode('utf-8')
-        except UnicodeDecodeError:
-            msg = "invalid or missing encoding declaration"
-            if filename is not None:
-                msg = '{} for {!r}'.format(msg, filename)
-            raise SyntaxError(msg)
-
-        match = cookie_re.match(line_string)
-        if not match:
-            return None
-        encoding = _get_normal_name(match.group(1))
-        try:
-            codec = lookup(encoding)
-        except LookupError:
-            # This behaviour mimics the Python interpreter
-            if filename is None:
-                msg = "unknown encoding: " + encoding
-            else:
-                msg = "unknown encoding for {!r}: {}".format(filename,
-                        encoding)
-            raise SyntaxError(msg)
-
-        if bom_found:
-            if encoding != 'utf-8':
-                # This behaviour mimics the Python interpreter
-                if filename is None:
-                    msg = 'encoding problem: utf-8'
-                else:
-                    msg = 'encoding problem for {!r}: utf-8'.format(filename)
-                raise SyntaxError(msg)
-            encoding += '-sig'
-        return encoding
-
-    first = read_or_stop()
-    if first.startswith(BOM_UTF8):
-        bom_found = True
-        first = first[3:]
-        default = 'utf-8-sig'
-    if not first:
-        return default, []
-
-    encoding = find_cookie(first)
-    if encoding:
-        return encoding, [first]
-    if not blank_re.match(first):
-        return default, [first]
-
-    second = read_or_stop()
-    if not second:
-        return default, [first]
-
-    encoding = find_cookie(second)
-    if encoding:
-        return encoding, [first, second]
-
-    return default, [first, second]
-
-
-def open(filename):
-    """Open a file in read only mode using the encoding detected by
-    detect_encoding().
-    """
-    buffer = io.open(filename, 'rb')
-    encoding, lines = detect_encoding(buffer.readline)
-    buffer.seek(0)
-    text = TextIOWrapper(buffer, encoding, line_buffering=True)
-    text.mode = 'r'
-    return text
-
-
-def tokenize(readline):
-    """
-    The tokenize() generator requires one argment, readline, which
-    must be a callable object which provides the same interface as the
-    readline() method of built-in file objects.  Each call to the function
-    should return one line of input as bytes.  Alternately, readline
-    can be a callable function terminating with StopIteration:
-        readline = open(myfile, 'rb').__next__  # Example of alternate readline
-
-    The generator produces 5-tuples with these members: the token type; the
-    token string; a 2-tuple (srow, scol) of ints specifying the row and
-    column where the token begins in the source; a 2-tuple (erow, ecol) of
-    ints specifying the row and column where the token ends in the source;
-    and the line on which the token was found.  The line passed is the
-    logical line; continuation lines are included.
-
-    The first token sequence will always be an ENCODING token
-    which tells you which encoding was used to decode the bytes stream.
-    """
-    # This import is here to avoid problems when the itertools module is not
-    # built yet and tokenize is imported.
-    from itertools import chain, repeat
-    encoding, consumed = detect_encoding(readline)
-    rl_gen = iter(readline, b"")
-    empty = repeat(b"")
-
-    try:
-        return _tokenize(chain(consumed, rl_gen, empty).__next__, encoding)
-    except AttributeError:
-        return _tokenize(chain(consumed, rl_gen, empty).next, encoding)
-
-
-def _tokenize(readline, encoding):
-    lnum = parenlev = continued = 0
-    numchars = '0123456789'
-    contstr, needcont = '', 0
-    contline = None
-    indents = [0]
-
-    if encoding is not None:
-        if encoding == "utf-8-sig":
-            # BOM will already have been stripped.
-            encoding = "utf-8"
-        yield TokenInfo(ENCODING, encoding, (0, 0), (0, 0), '')
-    while True:             # loop over lines in stream
-        try:
-            line = readline()
-        except StopIteration:
-            line = b''
-
-        if encoding is not None:
-            line = line.decode(encoding)
-        lnum += 1
-        pos, max = 0, len(line)
-
-        if contstr:                            # continued string
-            if not line:
-                raise TokenError("EOF in multi-line string", strstart)
-            endmatch = endprog.match(line)
-            if endmatch:
-                pos = end = endmatch.end(0)
-                yield TokenInfo(STRING, contstr + line[:end],
-                       strstart, (lnum, end), contline + line)
-                contstr, needcont = '', 0
-                contline = None
-            elif needcont and line[-2:] != '\\\n' and line[-3:] != '\\\r\n':
-                yield TokenInfo(ERRORTOKEN, contstr + line,
-                           strstart, (lnum, len(line)), contline)
-                contstr = ''
-                contline = None
-                continue
-            else:
-                contstr = contstr + line
-                contline = contline + line
-                continue
-
-        elif parenlev == 0 and not continued:  # new statement
-            if not line: break
-            column = 0
-            while pos < max:                   # measure leading whitespace
-                if line[pos] == ' ':
-                    column += 1
-                elif line[pos] == '\t':
-                    column = (column//tabsize + 1)*tabsize
-                elif line[pos] == '\f':
-                    column = 0
-                else:
-                    break
-                pos += 1
-            if pos == max:
-                break
-
-            if line[pos] in '#\r\n':           # skip comments or blank lines
-                if line[pos] == '#':
-                    comment_token = line[pos:].rstrip('\r\n')
-                    nl_pos = pos + len(comment_token)
-                    yield TokenInfo(COMMENT, comment_token,
-                           (lnum, pos), (lnum, pos + len(comment_token)), line)
-                    yield TokenInfo(NL, line[nl_pos:],
-                           (lnum, nl_pos), (lnum, len(line)), line)
-                else:
-                    yield TokenInfo((NL, COMMENT)[line[pos] == '#'], line[pos:],
-                           (lnum, pos), (lnum, len(line)), line)
-                continue
-
-            if column > indents[-1]:           # count indents or dedents
-                indents.append(column)
-                yield TokenInfo(INDENT, line[:pos], (lnum, 0), (lnum, pos), line)
-            while column < indents[-1]:
-                if column not in indents:
-                    raise IndentationError(
-                        "unindent does not match any outer indentation level",
-                        ("<tokenize>", lnum, pos, line))
-                indents = indents[:-1]
-                yield TokenInfo(DEDENT, '', (lnum, pos), (lnum, pos), line)
-
-        else:                                  # continued statement
-            if not line:
-                raise TokenError("EOF in multi-line statement", (lnum, 0))
-            continued = 0
-
-        while pos < max:
-            pseudomatch = _compile(PseudoToken).match(line, pos)
-            if pseudomatch:                                # scan for tokens
-                start, end = pseudomatch.span(1)
-                spos, epos, pos = (lnum, start), (lnum, end), end
-                if start == end:
-                    continue
-                token, initial = line[start:end], line[start]
-
-                if (initial in numchars or                  # ordinary number
-                    (initial == '.' and token != '.' and token != '...')):
-                    yield TokenInfo(NUMBER, token, spos, epos, line)
-                elif initial in '\r\n':
-                    yield TokenInfo(NL if parenlev > 0 else NEWLINE,
-                           token, spos, epos, line)
-                elif initial == '#':
-                    assert not token.endswith("\n")
-                    yield TokenInfo(COMMENT, token, spos, epos, line)
-                elif token in triple_quoted:
-                    endprog = _compile(endpats[token])
-                    endmatch = endprog.match(line, pos)
-                    if endmatch:                           # all on one line
-                        pos = endmatch.end(0)
-                        token = line[start:pos]
-                        yield TokenInfo(STRING, token, spos, (lnum, pos), line)
-                    else:
-                        strstart = (lnum, start)           # multiple lines
-                        contstr = line[start:]
-                        contline = line
-                        break
-                elif initial in single_quoted or \
-                    token[:2] in single_quoted or \
-                    token[:3] in single_quoted:
-                    if token[-1] == '\n':                  # continued string
-                        strstart = (lnum, start)
-                        endprog = _compile(endpats[initial] or
-                                           endpats[token[1]] or
-                                           endpats[token[2]])
-                        contstr, needcont = line[start:], 1
-                        contline = line
-                        break
-                    else:                                  # ordinary string
-                        yield TokenInfo(STRING, token, spos, epos, line)
-                elif isidentifier(initial):               # ordinary name
-                    yield TokenInfo(NAME, token, spos, epos, line)
-                elif initial == '\\':                      # continued stmt
-                    continued = 1
-                else:
-                    if initial in '([{':
-                        parenlev += 1
-                    elif initial in ')]}':
-                        parenlev -= 1
-                    yield TokenInfo(OP, token, spos, epos, line)
-            else:
-                yield TokenInfo(ERRORTOKEN, line[pos],
-                           (lnum, pos), (lnum, pos+1), line)
-                pos += 1
-
-    for indent in indents[1:]:                 # pop remaining indent levels
-        yield TokenInfo(DEDENT, '', (lnum, 0), (lnum, 0), '')
-    yield TokenInfo(ENDMARKER, '', (lnum, 0), (lnum, 0), '')
diff --git a/lib/taurus/external/pint/pint_local/constants_en.txt b/lib/taurus/external/pint/pint_local/constants_en.txt
deleted file mode 100644
index 2b67545..0000000
--- a/lib/taurus/external/pint/pint_local/constants_en.txt
+++ /dev/null
@@ -1,51 +0,0 @@
-# Default Pint constants definition file
-# Based on the International System of Units
-# Language: english
-# Source: http://physics.nist.gov/cuu/Constants/Table/allascii.txt
-# :copyright: 2013 by Pint Authors, see AUTHORS for more details.
-
-speed_of_light = 299792458 * meter / second = c
-standard_gravity = 9.806650 * meter / second ** 2 = g_0 = g_n = gravity
-vacuum_permeability = 4 * pi * 1e-7 * newton / ampere ** 2 = mu_0 = magnetic_constant
-vacuum_permittivity = 1 / (mu_0 * c **2 ) = epsilon_0 = electric_constant
-Z_0 = mu_0 * c = impedance_of_free_space = characteristic_impedance_of_vacuum
-
-# 0.000 000 29 e-34
-planck_constant = 6.62606957e-34 J s = h
-hbar = planck_constant / (2 * pi) = ħ
-
-# 0.000 80 e-11
-newtonian_constant_of_gravitation = 6.67384e-11 m^3 kg^-1 s^-2
-
-# 0.000 000 035 e-19
-# elementary_charge = 1.602176565e-19 C = e
-
-# 0.000 0075
-molar_gas_constant = 8.3144621 J mol^-1 K^-1 = R
-
-# 0.000 000 0024 e-3
-fine_structure_constant = 7.2973525698e-3
-
-# 0.000 000 27 e23
-avogadro_number = 6.02214129e23 mol^-1 =N_A
-
-# 0.000 0013 e-23
-boltzmann_constant = 1.3806488e-23 J K^-1 = k
-
-# 0.000 021 e-8
-stefan_boltzmann_constant = 5.670373e-8 W m^-2 K^-4 = σ
-
-# 0.000 0053 e10
-wien_frequency_displacement_law_constant = 5.8789254e10 Hz K^-1
-
-# 0.000 055
-rydberg_constant = 10973731.568539 m^-1
-
-# 0.000 000 40 e-31
-electron_mass = 9.10938291e-31 kg = m_e
-
-# 0.000 000 074 e-27
-neutron_mass = 1.674927351e-27 kg = m_n
-
-# 0.000 000 074 e-27
-proton_mass = 1.672621777e-27 kg = m_p
diff --git a/lib/taurus/external/pint/pint_local/context.py b/lib/taurus/external/pint/pint_local/context.py
deleted file mode 100644
index 7635ca4..0000000
--- a/lib/taurus/external/pint/pint_local/context.py
+++ /dev/null
@@ -1,239 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    pint.context
-    ~~~~~~~~~~~~
-
-    Functions and classes related to context definitions and application.
-
-    :copyright: 2013 by Pint Authors, see AUTHORS for more details.
-    :license: BSD, see LICENSE for more details.
-"""
-
-from __future__ import division, unicode_literals, print_function, absolute_import
-
-
-import re
-from collections import defaultdict
-import weakref
-
-from .compat import ChainMap
-from .util import (ParserHelper, UnitsContainer, string_types,
-                   to_units_container)
-
-#: Regex to match the header parts of a context.
-_header_re = re.compile('@context\s*(?P<defaults>\(.*\))?\s+(?P<name>\w+)\s*(=(?P<aliases>.*))*')
-
-#: Regex to match variable names in an equation.
-_varname_re = re.compile('[A-Za-z_][A-Za-z0-9_]*')
-
-
-def _expression_to_function(eq):
-    def func(ureg, value, **kwargs):
-        return ureg.parse_expression(eq, value=value, **kwargs)
-    return func
-
-
-class Context(object):
-    """A specialized container that defines transformation functions from one
-    dimension to another. Each Dimension are specified using a UnitsContainer.
-    Simple transformation are given with a function taking a single parameter.
-
-        >>> timedim = UnitsContainer({'[time]': 1})
-        >>> spacedim = UnitsContainer({'[length]': 1})
-        >>> def f(time):
-        ...     'Time to length converter'
-        ...     return 3. * time
-        >>> c = Context()
-        >>> c.add_transformation(timedim, spacedim, f)
-        >>> c.transform(timedim, spacedim, 2)
-        6
-
-    Conversion functions may take optional keyword arguments and the context
-    can have default values for these arguments.
-
-        >>> def f(time, n):
-        ...     'Time to length converter, n is the index of refraction of the material'
-        ...     return 3. * time / n
-        >>> c = Context(n=3)
-        >>> c.add_transformation(timedim, spacedim, f)
-        >>> c.transform(timedim, spacedim, 2)
-        2
-
-    """
-
-    def __init__(self, name, aliases=(), defaults=None):
-
-        self.name = name
-        self.aliases = aliases
-
-        #: Maps (src, dst) -> transformation function
-        self.funcs = {}
-
-        #: Maps defaults variable names to values
-        self.defaults = defaults or {}
-
-        #: Maps (src, dst) -> self
-        #: Used as a convenience dictionary to be composed by ContextChain
-        self.relation_to_context = weakref.WeakValueDictionary()
-
-    @classmethod
-    def from_context(cls, context, **defaults):
-        """Creates a new context that shares the funcs dictionary with the
-        original context. The default values are copied from the original
-        context and updated with the new defaults.
-
-        If defaults is empty, return the same context.
-        """
-        if defaults:
-            newdef = dict(context.defaults, **defaults)
-            c = cls(context.name, context.aliases, newdef)
-            c.funcs = context.funcs
-            for edge in context.funcs.keys():
-                c.relation_to_context[edge] = c
-            return c
-        return context
-
-    @classmethod
-    def from_lines(cls, lines, to_base_func=None):
-        header, lines = lines[0], lines[1:]
-
-        r = _header_re.search(header)
-        name = r.groupdict()['name'].strip()
-        aliases = r.groupdict()['aliases']
-        if aliases:
-            aliases = tuple(a.strip() for a in r.groupdict()['aliases'].split('='))
-        else:
-            aliases = ()
-        defaults = r.groupdict()['defaults']
-
-        if defaults:
-            def to_num(val):
-                val = complex(val)
-                if not val.imag:
-                    return val.real
-                return val
-
-            try:
-                _txt = defaults
-                defaults = (part.split('=') for part in defaults.strip('()').split(','))
-                defaults = dict((str(k).strip(), to_num(v))
-                                for k, v in defaults)
-            except (ValueError, TypeError):
-                raise ValueError('Could not parse Context definition defaults: %s', _txt)
-
-            ctx = cls(name, aliases, defaults)
-        else:
-            ctx = cls(name, aliases)
-
-        names = set()
-        for line in lines:
-            line = line.strip()
-            if not line or line.startswith('#'):
-                continue
-
-            rel, eq = line.split(':')
-            names.update(_varname_re.findall(eq))
-
-            func = _expression_to_function(eq)
-
-            if '<->' in rel:
-                src, dst = (ParserHelper.from_string(s)
-                            for s in rel.split('<->'))
-                if to_base_func:
-                    src = to_base_func(src)
-                    dst = to_base_func(dst)
-                ctx.add_transformation(src, dst, func)
-                ctx.add_transformation(dst, src, func)
-            elif '->' in rel:
-                src, dst = (ParserHelper.from_string(s)
-                            for s in rel.split('->'))
-                if to_base_func:
-                    src = to_base_func(src)
-                    dst = to_base_func(dst)
-                ctx.add_transformation(src, dst, func)
-            else:
-                raise ValueError('Relationships must be specified with <-> or ->.')
-
-        if defaults:
-            missing_pars = set(defaults.keys()).difference(set(names))
-            if missing_pars:
-                raise ValueError('Context parameters {0} not found in any equation.'.format(missing_pars))
-
-        return ctx
-
-    def add_transformation(self, src, dst, func):
-        """Add a transformation function to the context.
-        """
-        _key = self.__keytransform__(src, dst)
-        self.funcs[_key] = func
-        self.relation_to_context[_key] = self
-
-    def remove_transformation(self, src, dst):
-        """Add a transformation function to the context.
-        """
-        _key = self.__keytransform__(src, dst)
-        del self.funcs[_key]
-        del self.relation_to_context[_key]
-
-    @staticmethod
-    def __keytransform__(src, dst):
-        return to_units_container(src), to_units_container(dst)
-
-    def transform(self, src, dst, registry, value):
-        """Transform a value.
-        """
-        _key = self.__keytransform__(src, dst)
-        return self.funcs[_key](registry, value, **self.defaults)
-
-
-class ContextChain(ChainMap):
-    """A specialized ChainMap for contexts that simplifies finding rules
-    to transform from one dimension to another.
-    """
-
-    def __init__(self, *args, **kwargs):
-        super(ContextChain, self).__init__(*args, **kwargs)
-        self._graph = None
-        self._contexts = []
-
-    def insert_contexts(self, *contexts):
-        """Insert one or more contexts in reversed order the chained map.
-        (A rule in last context will take precedence)
-
-        To facilitate the identification of the context with the matching rule,
-        the *relation_to_context* dictionary of the context is used.
-        """
-        self._contexts.insert(0, contexts)
-        self.maps = [ctx.relation_to_context for ctx in reversed(contexts)] + self.maps
-        self._graph = None
-
-    def remove_contexts(self, n):
-        """Remove the last n inserted contexts from the chain.
-        """
-        self._contexts = self._contexts[n:]
-        self.maps = self.maps[n:]
-        self._graph = None
-
-    @property
-    def defaults(self):
-        if self:
-            return list(self.maps[0].values())[0].defaults
-        return {}
-
-    @property
-    def graph(self):
-        """The graph relating
-        """
-        if self._graph is None:
-            self._graph = defaultdict(set)
-            for fr_, to_ in self:
-                self._graph[fr_].add(to_)
-        return self._graph
-
-    def transform(self, src, dst, registry, value):
-        """Transform the value, finding the rule in the chained context.
-        (A rule in last context will take precedence)
-
-        :raises: KeyError if the rule is not found.
-        """
-        return self[(src, dst)].transform(src, dst, registry, value)
diff --git a/lib/taurus/external/pint/pint_local/converters.py b/lib/taurus/external/pint/pint_local/converters.py
deleted file mode 100644
index 0768537..0000000
--- a/lib/taurus/external/pint/pint_local/converters.py
+++ /dev/null
@@ -1,82 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    pint.converters
-    ~~~~~~~~~
-
-    Functions and classes related to unit conversions.
-
-    :copyright: 2014 by Pint Authors, see AUTHORS for more details.
-    :license: BSD, see LICENSE for more details.
-"""
-from __future__ import (division, unicode_literals, print_function,
-                        absolute_import)
-
-
-class Converter(object):
-    """Base class for value converters.
-    """
-
-    is_multiplicative = True
-
-    def to_reference(self, value, inplace=False):
-        return value
-
-    def from_reference(self, value, inplace=False):
-        return value
-
-
-class ScaleConverter(Converter):
-    """A linear transformation
-    """
-
-    is_multiplicative = True
-
-    def __init__(self, scale):
-        self.scale = scale
-
-    def to_reference(self, value, inplace=False):
-        if inplace:
-            value *= self.scale
-        else:
-            value = value * self.scale
-
-        return value
-
-    def from_reference(self, value, inplace=False):
-        if inplace:
-            value /= self.scale
-        else:
-            value = value / self.scale
-
-        return value
-
-
-class OffsetConverter(Converter):
-    """An affine transformation
-    """
-
-    def __init__(self, scale, offset):
-        self.scale = scale
-        self.offset = offset
-
-    @property
-    def is_multiplicative(self):
-        return self.offset == 0
-
-    def to_reference(self, value, inplace=False):
-        if inplace:
-            value *= self.scale
-            value += self.offset
-        else:
-            value = value * self.scale + self.offset
-
-        return value
-
-    def from_reference(self, value, inplace=False):
-        if inplace:
-            value -= self.offset
-            value /= self.scale
-        else:
-            value = (value - self.offset) / self.scale
-
-        return value
diff --git a/lib/taurus/external/pint/pint_local/default_en.txt b/lib/taurus/external/pint/pint_local/default_en.txt
deleted file mode 100644
index a1145c7..0000000
--- a/lib/taurus/external/pint/pint_local/default_en.txt
+++ /dev/null
@@ -1,377 +0,0 @@
-# Default Pint units definition file
-# Based on the International System of Units
-# Language: english
-# :copyright: 2013 by Pint Authors, see AUTHORS for more details.
-
-# decimal prefixes
-yocto- = 1e-24 = y-
-zepto- = 1e-21 = z-
-atto- =  1e-18 = a-
-femto- = 1e-15 = f-
-pico- =  1e-12 = p-
-nano- =  1e-9  = n-
-micro- = 1e-6  = u- = µ-
-milli- = 1e-3  = m-
-centi- = 1e-2  = c-
-deci- =  1e-1  = d-
-deca- =  1e+1  = da-
-hecto- = 1e2   = h-
-kilo- =  1e3   = k-
-mega- =  1e6   = M-
-giga- =  1e9   = G-
-tera- =  1e12  = T-
-peta- =  1e15  = P-
-exa- =   1e18  = E-
-zetta- = 1e21  = Z-
-yotta- = 1e24  = Y-
-
-# binary_prefixes
-kibi- = 2**10 = Ki-
-mebi- = 2**20 = Mi-
-gibi- = 2**30 = Gi-
-tebi- = 2**40 = Ti-
-pebi- = 2**50 = Pi-
-exbi- = 2**60 = Ei-
-zebi- = 2**70 = Zi-
-yobi- = 2**80 = Yi-
-
-# reference
-meter = [length] = m = metre
-second = [time] = s = sec
-ampere = [current] = A = amp
-candela = [luminosity] = cd = candle
-gram = [mass] = g
-mole = [substance] = mol
-kelvin = [temperature]; offset: 0 = K = degK
-radian = [] = rad
-bit = []
-count = []
-
- at import constants_en.txt
-
-# acceleration
-[acceleration] = [length] / [time] ** 2
-
-# Angle
-turn = 2 * pi * radian = revolution = cycle = circle
-degree = pi / 180 * radian = deg = arcdeg = arcdegree = angular_degree
-arcminute = arcdeg / 60 = arcmin = arc_minute = angular_minute
-arcsecond = arcmin / 60 =  arcsec = arc_second = angular_second
-steradian = radian ** 2 = sr
-
-# Area
-[area] = [length] ** 2
-are = 100 * m**2
-barn = 1e-28 * m ** 2 = b
-cmil = 5.067075e-10 * m ** 2 = circular_mils
-darcy = 9.869233e-13 * m ** 2
-acre = 4046.8564224 * m ** 2 = international_acre
-hectare = 100 * are = ha
-US_survey_acre = 160 * rod ** 2
-
-# EM
-esu = 1 * erg**0.5 * centimeter**0.5 = statcoulombs = statC = franklin = Fr
-esu_per_second = 1 * esu / second = statampere
-ampere_turn = 1 * A
-gilbert = 10 / (4 * pi ) * ampere_turn
-coulomb = ampere * second = C
-volt = joule / coulomb = V
-farad = coulomb / volt = F
-ohm = volt / ampere = Ω
-siemens = ampere / volt = S = mho
-weber = volt * second = Wb
-tesla = weber / meter ** 2 = T
-henry = weber / ampere = H
-elementary_charge = 1.602176487e-19 * coulomb = e
-chemical_faraday = 9.64957e4 * coulomb
-physical_faraday = 9.65219e4 * coulomb
-faraday =  96485.3399 * coulomb = C12_faraday
-gamma = 1e-9 * tesla
-gauss = 1e-4 * tesla
-maxwell = 1e-8 * weber = mx
-oersted = 1000 / (4 * pi) * A / m = Oe
-statfarad = 1.112650e-12 * farad = statF = stF
-stathenry = 8.987554e11 * henry = statH = stH
-statmho = 1.112650e-12 * siemens = statS = stS
-statohm = 8.987554e11 * ohm
-statvolt = 2.997925e2 * volt = statV = stV
-unit_pole = 1.256637e-7 * weber
-
-# Energy
-[energy] = [force] * [length]
-joule = newton * meter = J
-erg = dyne * centimeter
-btu = 1.05505585262e3 * joule = Btu = BTU = british_thermal_unit
-electron_volt = 1.60217653e-19 * J = eV
-quadrillion_btu = 10**15 * btu = quad
-thm = 100000 * BTU = therm = EC_therm
-cal = 4.184 * joule = calorie = thermochemical_calorie
-international_steam_table_calorie = 4.1868 * joule
-ton_TNT = 4.184e9 * joule = tTNT
-US_therm = 1.054804e8 * joule
-watt_hour = watt * hour = Wh = watthour
-hartree = 4.35974394e-18 * joule = E_h = hartree_energy
-
-# Force
-[force] = [mass] * [acceleration]
-newton = kilogram * meter / second ** 2 = N
-dyne = gram * centimeter / second ** 2 = dyn
-force_kilogram = g_0 * kilogram = kgf = kilogram_force = pond
-force_gram = g_0 * gram = gf = gram_force
-force_ounce = g_0 * ounce = ozf = ounce_force
-force_pound = g_0 * lb = lbf = pound_force
-force_ton = 2000 * force_pound = ton_force
-poundal = lb * feet / second ** 2 = pdl
-kip = 1000*lbf
-
-# Frequency
-[frequency] = 1 / [time]
-hertz = 1 / second = Hz = rps
-revolutions_per_minute = revolution / minute = rpm
-counts_per_second = count / second = cps
-
-# Heat
-#RSI = degK * meter ** 2 / watt
-#clo = 0.155 * RSI = clos
-#R_value = foot ** 2 * degF * hour / btu
-
-# Information
-byte = 8 * bit = Bo = octet
-baud = bit / second = Bd = bps
-
-# Irradiance
-peak_sun_hour = 1000 * watt_hour / meter**2 = PSH
-langley = thermochemical_calorie / centimeter**2 = Langley
-
-# Length
-angstrom = 1e-10 * meter = Å = ångström = Å
-inch = 2.54 * centimeter = in = international_inch = inches = international_inches
-foot = 12 * inch = ft = international_foot = feet = international_feet
-mile = 5280 * foot = mi = international_mile
-yard = 3 * feet = yd = international_yard
-mil = inch / 1000 = thou
-parsec = 3.08568025e16 * meter = pc
-light_year = speed_of_light * julian_year = ly = lightyear
-astronomical_unit = 149597870691 * meter = au
-nautical_mile = 1.852e3 * meter = nmi
-printers_point = 127 * millimeter / 360 = point
-printers_pica = 12 * printers_point = pica
-US_survey_foot = 1200 * meter / 3937
-US_survey_yard =  3 * US_survey_foot
-US_survey_mile = 5280 * US_survey_foot = US_statute_mile
-rod = 16.5 * US_survey_foot = pole = perch
-furlong = 660 * US_survey_foot
-fathom = 6 * US_survey_foot
-chain = 66 * US_survey_foot
-barleycorn = inch / 3
-arpentlin = 191.835 * feet
-kayser = 1 / centimeter = wavenumber
-
-# Mass
-dram = oz / 16 = dr = avoirdupois_dram
-ounce = 28.349523125 * gram = oz = avoirdupois_ounce
-pound = 0.45359237 * kilogram = lb = avoirdupois_pound
-stone = 14 * lb = st
-carat = 200 * milligram
-grain = 64.79891 * milligram = gr
-long_hundredweight = 112 * lb
-short_hundredweight = 100 * lb
-metric_ton = 1000 * kilogram = t = tonne
-pennyweight = 24 * gram = dwt
-slug = 14.59390 * kilogram
-troy_ounce = 480 * grain = toz = apounce = apothecary_ounce
-troy_pound = 12 * toz = tlb = appound = apothecary_pound
-drachm = 60 * grain = apdram = apothecary_dram
-atomic_mass_unit = 1.660538782e-27 * kilogram =  u = amu = dalton = Da
-scruple = 20 * grain
-bag = 94 * lb
-ton = 2000 * lb = short_ton
-
-# Textile
-denier =  gram / (9000 * meter)
-tex = gram/ (1000 * meter)
-dtex = decitex
-
-# Photometry
-lumen = candela * steradian = lm
-lux = lumen / meter ** 2 = lx
-
-# Power
-[power] = [energy] / [time]
-watt = joule / second = W = volt_ampere = VA
-horsepower = 33000 * ft * lbf / min = hp = UK_horsepower = British_horsepower
-boiler_horsepower = 33475 * btu / hour
-metric_horsepower =  75 * force_kilogram * meter / second
-electric_horsepower = 746 * watt
-hydraulic_horsepower = 550 * feet * lbf / second
-refrigeration_ton = 12000 * btu / hour = ton_of_refrigeration
-
-# Pressure
-[pressure] = [force] / [area]
-Hg = gravity * 13.59510 * gram / centimeter ** 3 = mercury = conventional_mercury
-mercury_60F = gravity * 13.5568 * gram / centimeter ** 3
-H2O = gravity * 1000 * kilogram / meter ** 3 = h2o = water = conventional_water
-water_4C = gravity * 999.972 * kilogram / meter ** 3 = water_39F
-water_60F = gravity * 999.001 * kilogram / m ** 3
-pascal = newton / meter ** 2 = Pa
-bar = 100000 * pascal
-atmosphere = 101325 * pascal = atm = standard_atmosphere
-technical_atmosphere = kilogram * gravity / centimeter ** 2 = at
-torr = atm / 760
-psi = pound * gravity / inch ** 2 = pound_force_per_square_inch
-ksi = kip / inch ** 2 = kip_per_square_inch
-barye = 0.1 * newton / meter ** 2 = barie = barad = barrie = baryd = Ba
-mmHg = millimeter * Hg = mm_Hg = millimeter_Hg = millimeter_Hg_0C
-cmHg = centimeter * Hg = cm_Hg = centimeter_Hg
-inHg = inch * Hg = in_Hg = inch_Hg = inch_Hg_32F
-inch_Hg_60F = inch * mercury_60F
-inch_H2O_39F = inch * water_39F
-inch_H2O_60F = inch * water_60F
-footH2O = ft * water
-cmH2O = centimeter * water
-foot_H2O = ft * water = ftH2O
-standard_liter_per_minute = 1.68875 * Pa * m ** 3 / s = slpm = slm
-
-# Radiation
-Bq = Hz = becquerel
-curie = 3.7e10 * Bq = Ci
-rutherford = 1e6*Bq = rd = Rd
-Gy = joule / kilogram = gray = Sv = sievert
-rem = 1e-2 * sievert
-rads = 1e-2 * gray
-roentgen = 2.58e-4 * coulomb / kilogram
-
-# Temperature
-degC = kelvin; offset: 273.15 = celsius
-degR = 5 / 9 * kelvin; offset: 0 = rankine
-degF = 5 / 9 * kelvin; offset: 255.372222 = fahrenheit
-
-# Time
-minute = 60 * second = min
-hour = 60 * minute = hr
-day = 24 * hour
-week = 7 * day
-fortnight = 2 * week
-year = 31556925.9747 * second
-month = year/12
-shake = 1e-8 * second
-sidereal_day = day / 1.00273790935079524
-sidereal_hour = sidereal_day/24
-sidereal_minute=sidereal_hour/60
-sidereal_second =sidereal_minute/60
-sidereal_year = 366.25636042 * sidereal_day
-sidereal_month = 27.321661 * sidereal_day
-tropical_month = 27.321661 * day
-synodic_month = 29.530589 * day = lunar_month
-common_year = 365 * day
-leap_year = 366 * day
-julian_year = 365.25 * day
-gregorian_year = 365.2425 * day
-millenium = 1000 * year = millenia = milenia = milenium
-eon = 1e9 * year
-work_year = 2056 * hour
-work_month = work_year/12
-
-# Velocity
-[speed] = [length] / [time]
-knot = nautical_mile / hour = kt = knot_international = international_knot = nautical_miles_per_hour
-mph = mile / hour = MPH
-kph = kilometer / hour = KPH
-
-# Viscosity
-[viscosity] = [pressure] * [time]
-poise = 1e-1 * Pa * second = P
-stokes = 1e-4 * meter ** 2 / second = St
-rhe = 10 / (Pa * s)
-
-# Volume
-[volume] = [length] ** 3
-liter = 1e-3 * m ** 3 = l = L = litre
-cc = centimeter ** 3 = cubic_centimeter
-stere = meter ** 3
-gross_register_ton = 100 * foot ** 3 = register_ton = GRT
-acre_foot = acre * foot = acre_feet
-board_foot = foot ** 2 * inch = FBM
-bushel = 2150.42 * inch ** 3 = bu = US_bushel
-dry_gallon = bushel / 8 = US_dry_gallon
-dry_quart = dry_gallon / 4 = US_dry_quart
-dry_pint = dry_quart / 2 = US_dry_pint
-gallon = 231 * inch ** 3 = liquid_gallon = US_liquid_gallon
-quart = gallon / 4 = liquid_quart = US_liquid_quart
-pint = quart / 2 = pt = liquid_pint = US_liquid_pint
-cup = pint / 2 = liquid_cup = US_liquid_cup
-gill = cup / 2 = liquid_gill = US_liquid_gill
-fluid_ounce = gill / 4 = floz = US_fluid_ounce = US_liquid_ounce
-imperial_bushel = 36.36872 * liter = UK_bushel
-imperial_gallon = imperial_bushel / 8 = UK_gallon
-imperial_quart = imperial_gallon / 4 = UK_quart
-imperial_pint = imperial_quart / 2 = UK_pint
-imperial_cup = imperial_pint / 2 = UK_cup
-imperial_gill = imperial_cup / 2 = UK_gill
-imperial_floz = imperial_gill / 5 = UK_fluid_ounce = imperial_fluid_ounce
-barrel = 42 * gallon = bbl
-tablespoon = floz / 2 = tbsp = Tbsp = Tblsp = tblsp = tbs = Tbl
-teaspoon = tablespoon / 3 = tsp
-peck = bushel / 4 = pk
-fluid_dram = floz / 8 = fldr = fluidram
-firkin = barrel / 4
-
-
- at context(n=1) spectroscopy = sp
-    # n index of refraction of the medium.
-    [length] <-> [frequency]: speed_of_light / n / value
-    [frequency] -> [energy]: planck_constant * value
-    [energy] -> [frequency]: value / planck_constant
- at end
-
- at context boltzmann
-    [temperature] -> [energy]: boltzmann_constant * value
-    [energy] -> [temperature]: value / boltzmann_constant
- at end
-
- at context(mw=0,volume=0,solvent_mass=0) chemistry = chem
-    # mw is the molecular weight of the species
-    # volume is the volume of the solution
-    # solvent_mass is the mass of solvent in the solution
-
-    # moles -> mass require the molecular weight
-    [substance] -> [mass]: value * mw
-    [mass] -> [substance]: value / mw
-
-    # moles/volume -> mass/volume and moles/mass -> mass / mass
-    # require the  molecular weight
-    [substance] / [volume] -> [mass] / [volume]: value * mw
-    [mass] / [volume] -> [substance] / [volume]: value / mw
-    [substance] / [mass] -> [mass] / [mass]: value * mw
-    [mass] / [mass] -> [substance] / [mass]: value / mw
-
-    # moles/volume -> moles requires the solution volume
-    [substance] / [volume] -> [substance]: value * volume
-    [substance] -> [substance] / [volume]: value / volume
-
-    # moles/mass -> moles requires the solvent (usually water) mass
-    [substance] / [mass] -> [substance]: value * solvent_mass
-    [substance] -> [substance] / [mass]: value / solvent_mass
-
-    # moles/mass -> moles/volume require the solvent mass and the volume
-    [substance] / [mass] -> [substance]/[volume]: value * solvent_mass / volume
-    [substance] / [volume] -> [substance] / [mass]: value / solvent_mass * volume
-
- at end
-
- at system mks
-    meter
-    kilogram
-    second
- at end
-
- at system cgs
-    centimeter
-    gram
-    second
- at end
-
- at system imperial
-    yard
-    pound
- at end
diff --git a/lib/taurus/external/pint/pint_local/definitions.py b/lib/taurus/external/pint/pint_local/definitions.py
deleted file mode 100644
index a25fd73..0000000
--- a/lib/taurus/external/pint/pint_local/definitions.py
+++ /dev/null
@@ -1,157 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    pint.definitions
-    ~~~~~~~~~
-
-    Functions and classes related to unit definitions.
-
-    :copyright: 2014 by Pint Authors, see AUTHORS for more details.
-    :license: BSD, see LICENSE for more details.
-"""
-
-from __future__ import (division, unicode_literals, print_function,
-                        absolute_import)
-
-from .converters import ScaleConverter, OffsetConverter
-from .util import UnitsContainer, _is_dim, ParserHelper
-from .compat import string_types
-
-
-class Definition(object):
-    """Base class for definitions.
-
-    :param name: name.
-    :param symbol: a short name or symbol for the definition
-    :param aliases: iterable of other names.
-    :param converter: an instance of Converter.
-    """
-
-    def __init__(self, name, symbol, aliases, converter):
-        self._name = name
-        self._symbol = symbol
-        self._aliases = aliases
-        self._converter = converter
-
-    @property
-    def is_multiplicative(self):
-        return self._converter.is_multiplicative
-
-    @classmethod
-    def from_string(cls, definition):
-        """Parse a definition
-        """
-        name, definition = definition.split('=', 1)
-        name = name.strip()
-
-        result = [res.strip() for res in definition.split('=')]
-        value, aliases = result[0], tuple(result[1:])
-        symbol, aliases = (aliases[0], aliases[1:]) if aliases else (None,
-                                                                     aliases)
-
-        if name.startswith('['):
-            return DimensionDefinition(name, symbol, aliases, value)
-        elif name.endswith('-'):
-            name = name.rstrip('-')
-            return PrefixDefinition(name, symbol, aliases, value)
-        else:
-            return UnitDefinition(name, symbol, aliases, value)
-
-    @property
-    def name(self):
-        return self._name
-
-    @property
-    def symbol(self):
-        return self._symbol or self._name
-
-    @property
-    def has_symbol(self):
-        return bool(self._symbol)
-
-    @property
-    def aliases(self):
-        return self._aliases
-
-    @property
-    def converter(self):
-        return self._converter
-
-    def __str__(self):
-        return self.name
-
-
-class PrefixDefinition(Definition):
-    """Definition of a prefix.
-    """
-
-    def __init__(self, name, symbol, aliases, converter):
-        if isinstance(converter, string_types):
-            converter = ScaleConverter(eval(converter))
-        aliases = tuple(alias.strip('-') for alias in aliases)
-        if symbol:
-            symbol = symbol.strip('-')
-        super(PrefixDefinition, self).__init__(name, symbol, aliases,
-                                               converter)
-
-
-class UnitDefinition(Definition):
-    """Definition of a unit.
-
-    :param reference: Units container with reference units.
-    :param is_base: indicates if it is a base unit.
-    """
-
-    def __init__(self, name, symbol, aliases, converter,
-                 reference=None, is_base=False):
-        self.reference = reference
-        self.is_base = is_base
-        if isinstance(converter, string_types):
-            if ';' in converter:
-                [converter, modifiers] = converter.split(';', 2)
-                modifiers = dict((key.strip(), eval(value)) for key, value in
-                                 (part.split(':')
-                                  for part in modifiers.split(';')))
-            else:
-                modifiers = {}
-
-            converter = ParserHelper.from_string(converter)
-            if all(_is_dim(key) for key in converter.keys()):
-                self.is_base = True
-            elif not any(_is_dim(key) for key in converter.keys()):
-                self.is_base = False
-            else:
-                raise ValueError('Cannot mix dimensions and units in the same definition. '
-                                 'Base units must be referenced only to dimensions. '
-                                 'Derived units must be referenced only to units.')
-            self.reference = UnitsContainer(converter)
-            if modifiers.get('offset', 0.) != 0.:
-                converter = OffsetConverter(converter.scale,
-                                            modifiers['offset'])
-            else:
-                converter = ScaleConverter(converter.scale)
-
-        super(UnitDefinition, self).__init__(name, symbol, aliases, converter)
-
-
-class DimensionDefinition(Definition):
-    """Definition of a dimension.
-    """
-
-    def __init__(self, name, symbol, aliases, converter,
-                 reference=None, is_base=False):
-        self.reference = reference
-        self.is_base = is_base
-        if isinstance(converter, string_types):
-            converter = ParserHelper.from_string(converter)
-            if not converter:
-                self.is_base = True
-            elif all(_is_dim(key) for key in converter.keys()):
-                self.is_base = False
-            else:
-                raise ValueError('Base dimensions must be referenced to None. '
-                                 'Derived dimensions must only be referenced '
-                                 'to dimensions.')
-            self.reference = UnitsContainer(converter)
-
-        super(DimensionDefinition, self).__init__(name, symbol, aliases,
-                                                  converter=None)
diff --git a/lib/taurus/external/pint/pint_local/errors.py b/lib/taurus/external/pint/pint_local/errors.py
deleted file mode 100644
index 4d86198..0000000
--- a/lib/taurus/external/pint/pint_local/errors.py
+++ /dev/null
@@ -1,113 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    pint.errors
-    ~~~~~~~~~
-
-    Functions and classes related to unit definitions and conversions.
-
-    :copyright: 2013 by Pint Authors, see AUTHORS for more details.
-    :license: BSD, see LICENSE for more details.
-"""
-from __future__ import (division, unicode_literals, print_function,
-                        absolute_import)
-
-from .compat import string_types
-
-
-class DefinitionSyntaxError(ValueError):
-    """Raised when a textual definition has a syntax error.
-    """
-
-    def __init__(self, msg, filename=None, lineno=None):
-        super(ValueError, self).__init__()
-        self.msg = msg
-        self.filename = None
-        self.lineno = None
-
-    def __str__(self):
-        mess = "While opening {0}, in line {1}: "
-        return mess.format(self.filename, self.lineno) + self.msg
-
-
-class RedefinitionError(ValueError):
-    """Raised when a unit or prefix is redefined.
-    """
-
-    def __init__(self, name, definition_type):
-        super(ValueError, self).__init__()
-        self.name = name
-        self.definition_type = definition_type
-        self.filename = None
-        self.lineno = None
-
-    def __str__(self):
-        msg = "cannot redefine '{0}' ({1})".format(self.name,
-                                                   self.definition_type)
-        if self.filename:
-            mess = "While opening {0}, in line {1}: "
-            return mess.format(self.filename, self.lineno) + msg
-        return msg
-
-
-class UndefinedUnitError(ValueError):
-    """Raised when the units are not defined in the unit registry.
-    """
-
-    def __init__(self, unit_names):
-        super(ValueError, self).__init__()
-        self.unit_names = unit_names
-
-    def __str__(self):
-        mess = "'{0}' is not defined in the unit registry"
-        mess_plural = "'{0}' are not defined in the unit registry"
-        if isinstance(self.unit_names, string_types):
-            return mess.format(self.unit_names)
-        elif isinstance(self.unit_names, (list, tuple))\
-                and len(self.unit_names) == 1:
-            return mess.format(self.unit_names[0])
-        elif isinstance(self.unit_names, set) and len(self.unit_names) == 1:
-            uname = list(self.unit_names)[0]
-            return mess.format(uname)
-        else:
-            return mess_plural.format(self.unit_names)
-
-
-class DimensionalityError(ValueError):
-    """Raised when trying to convert between incompatible units.
-    """
-
-    def __init__(self, units1, units2, dim1=None, dim2=None, extra_msg=''):
-        super(DimensionalityError, self).__init__()
-        self.units1 = units1
-        self.units2 = units2
-        self.dim1 = dim1
-        self.dim2 = dim2
-        self.extra_msg = extra_msg
-
-    def __str__(self):
-        if self.dim1 or self.dim2:
-            dim1 = ' ({0})'.format(self.dim1)
-            dim2 = ' ({0})'.format(self.dim2)
-        else:
-            dim1 = ''
-            dim2 = ''
-
-        msg = "Cannot convert from '{0}'{1} to '{2}'{3}" + self.extra_msg
-
-        return msg.format(self.units1, dim1, self.units2, dim2)
-
-
-class OffsetUnitCalculusError(ValueError):
-    """Raised on ambiguous operations with offset units.
-    """
-    def __init__(self, units1, units2='', extra_msg=''):
-        super(ValueError, self).__init__()
-        self.units1 = units1
-        self.units2 = units2
-        self.extra_msg = extra_msg
-
-    def __str__(self):
-        msg = ("Ambiguous operation with offset unit (%s)." %
-               ', '.join(['%s' % u for u in [self.units1, self.units2] if u])
-               + self.extra_msg)
-        return msg.format(self.units1, self.units2)
diff --git a/lib/taurus/external/pint/pint_local/formatting.py b/lib/taurus/external/pint/pint_local/formatting.py
deleted file mode 100644
index f9b43d0..0000000
--- a/lib/taurus/external/pint/pint_local/formatting.py
+++ /dev/null
@@ -1,200 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    pint.formatter
-    ~~~~~~~~~~~~~~
-
-    Format units for pint.
-
-    :copyright: 2013 by Pint Authors, see AUTHORS for more details.
-    :license: BSD, see LICENSE for more details.
-"""
-
-from __future__ import division, unicode_literals, print_function, absolute_import
-
-import re
-
-__JOIN_REG_EXP = re.compile("\{\d*\}")
-
-
-def _join(fmt, iterable):
-    """Join an iterable with the format specified in fmt.
-
-    The format can be specified in two ways:
-    - PEP3101 format with two replacement fields (eg. '{0} * {1}')
-    - The concatenating string (eg. ' * ')
-    """
-    if not iterable:
-        return ''
-    if not __JOIN_REG_EXP.search(fmt):
-        return fmt.join(iterable)
-    miter = iter(iterable)
-    first = next(miter)
-    for val in miter:
-        ret = fmt.format(first, val)
-        first = ret
-    return first
-
-_PRETTY_EXPONENTS = '⁰¹²³⁴⁵⁶⁷⁸⁹'
-
-
-def _pretty_fmt_exponent(num):
-    """Format an number into a pretty printed exponent.
-    """
-    # TODO: Will not work for decimals
-    ret = '{0:n}'.format(num).replace('-', '⁻')
-    for n in range(10):
-        ret = ret.replace(str(n), _PRETTY_EXPONENTS[n])
-    return ret
-
-
-#: _FORMATS maps format specifications to the corresponding argument set to
-#: formatter().
-_FORMATS = {
-    'P': {   # Pretty format.
-        'as_ratio': True,
-        'single_denominator': False,
-        'product_fmt': '·',
-        'division_fmt': '/',
-        'power_fmt': '{0}{1}',
-        'parentheses_fmt': '({0})',
-        'exp_call': _pretty_fmt_exponent,
-        },
-
-    'L': {   # Latex format.
-        'as_ratio': True,
-        'single_denominator': True,
-        'product_fmt': r' \cdot ',
-        'division_fmt': r'\frac[{0}][{1}]',
-        'power_fmt': '{0}^[{1}]',
-        'parentheses_fmt': r'\left({0}\right)',
-        },
-
-    'H': {   # HTML format.
-        'as_ratio': True,
-        'single_denominator': True,
-        'product_fmt': r' ',
-        'division_fmt': r'{0}/{1}',
-        'power_fmt': '{0}<sup>{1}</sup>',
-        'parentheses_fmt': r'({0})',
-        },
-
-    '': {   # Default format.
-        'as_ratio': True,
-        'single_denominator': False,
-        'product_fmt': ' * ',
-        'division_fmt': ' / ',
-        'power_fmt': '{0} ** {1}',
-        'parentheses_fmt': r'({0})',
-        },
-
-    'C': {  # Compact format.
-        'as_ratio': True,
-        'single_denominator': False,
-        'product_fmt': '*',  # TODO: Should this just be ''?
-        'division_fmt': '/',
-        'power_fmt': '{0}**{1}',
-        'parentheses_fmt': r'({0})',
-        },
-    }
-
-
-def formatter(items, as_ratio=True, single_denominator=False,
-              product_fmt=' * ', division_fmt=' / ', power_fmt='{0} ** {1}',
-              parentheses_fmt='({0})', exp_call=lambda x: '{0:n}'.format(x)):
-    """Format a list of (name, exponent) pairs.
-
-    :param items: a list of (name, exponent) pairs.
-    :param as_ratio: True to display as ratio, False as negative powers.
-    :param single_denominator: all with terms with negative exponents are
-                               collected together.
-    :param product_fmt: the format used for multiplication.
-    :param division_fmt: the format used for division.
-    :param power_fmt: the format used for exponentiation.
-    :param parentheses_fmt: the format used for parenthesis.
-
-    :return: the formula as a string.
-    """
-
-    if not items:
-        return ''
-
-    if as_ratio:
-        fun = lambda x: exp_call(abs(x))
-    else:
-        fun = exp_call
-
-    pos_terms, neg_terms = [], []
-
-    for key, value in sorted(items):
-        if value == 1:
-            pos_terms.append(key)
-        elif value > 0:
-            pos_terms.append(power_fmt.format(key, fun(value)))
-        elif value == -1 and as_ratio:
-            neg_terms.append(key)
-        else:
-            neg_terms.append(power_fmt.format(key, fun(value)))
-
-    if not as_ratio:
-        # Show as Product: positive * negative terms ** -1
-        return _join(product_fmt, pos_terms + neg_terms)
-
-    # Show as Ratio: positive terms / negative terms
-    pos_ret = _join(product_fmt, pos_terms) or '1'
-
-    if not neg_terms:
-        return pos_ret
-
-    if single_denominator:
-        neg_ret = _join(product_fmt, neg_terms)
-        if len(neg_terms) > 1:
-            neg_ret = parentheses_fmt.format(neg_ret)
-    else:
-        neg_ret = _join(division_fmt, neg_terms)
-
-    return _join(division_fmt, [pos_ret, neg_ret])
-
-# Extract just the type from the specification mini-langage: see
-# http://docs.python.org/2/library/string.html#format-specification-mini-language
-# We also add uS for uncertainties.
-_BASIC_TYPES = frozenset('bcdeEfFgGnosxX%uS')
-_KNOWN_TYPES = frozenset(list(_FORMATS.keys()) + ['~'])
-
-def _parse_spec(spec):
-    result = ''
-    for ch in reversed(spec):
-        if ch == '~' or ch in _BASIC_TYPES:
-            continue
-        elif ch in _KNOWN_TYPES:
-            if result:
-                raise ValueError("expected ':' after format specifier")
-            else:
-                result = ch
-        elif ch.isalpha():
-            raise ValueError("Unknown conversion specified " + ch)
-        else:
-            break
-    return result
-
-
-def format_unit(unit, spec):
-    if not unit:
-        return 'dimensionless'
-
-    spec = _parse_spec(spec)
-    fmt = {}
-    # Convert keys and values to str to avoid a bug in Python2.6
-    for k, v in _FORMATS[spec].items():
-        fmt[str(k)] = str(v)
-
-    result = formatter(unit.items(), **fmt)
-    if spec == 'L':
-        result = result.replace('[', '{').replace(']', '}')
-    return result
-
-
-def remove_custom_flags(spec):
-    for flag in _KNOWN_TYPES:
-        if flag:
-            spec = spec.replace(flag, '')
-    return spec
diff --git a/lib/taurus/external/pint/pint_local/measurement.py b/lib/taurus/external/pint/pint_local/measurement.py
deleted file mode 100644
index e82591d..0000000
--- a/lib/taurus/external/pint/pint_local/measurement.py
+++ /dev/null
@@ -1,99 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    pint.measurement
-    ~~~~~~~~~~~~~~~~
-
-    :copyright: 2013 by Pint Authors, see AUTHORS for more details.
-    :license: BSD, see LICENSE for more details.
-"""
-
-from __future__ import division, unicode_literals, print_function, absolute_import
-
-from .compat import ufloat
-from .formatting import _FORMATS
-
-MISSING = object()
-
-
-class _Measurement(object):
-    """Implements a class to describe a quantity with uncertainty.
-
-    :param value: The most likely value of the measurement.
-    :type value: Quantity or Number
-    :param error: The error or uncertainty of the measurement.
-    :type error: Quantity or Number
-    """
-
-    def __new__(cls, value, error, units=MISSING):
-        if units is MISSING:
-            try:
-                value, units = value.magnitude, value.units
-            except AttributeError:
-                try:
-                    value, error, units = value.nominal_value, value.std_dev, error
-                except AttributeError:
-                    units = ''
-        try:
-            error = error.to(units).magnitude
-        except AttributeError:
-            pass
-
-        inst = super(_Measurement, cls).__new__(cls, ufloat(value, error), units)
-
-        if error < 0:
-            raise ValueError('The magnitude of the error cannot be negative'.format(value, error))
-        return inst
-
-    @property
-    def value(self):
-        return self._REGISTRY.Quantity(self.magnitude.nominal_value, self.units)
-
-    @property
-    def error(self):
-        return self._REGISTRY.Quantity(self.magnitude.std_dev, self.units)
-
-    @property
-    def rel(self):
-        return float(abs(self.magnitude.std_dev / self.magnitude.nominal_value))
-
-    def __repr__(self):
-        return "<Measurement({0:.2f}, {1:.2f}, {2})>".format(self.magnitude.nominal_value,
-                                                             self.magnitude.std_dev,
-                                                             self.units)
-
-    def __str__(self):
-        return '{0}'.format(self)
-
-    def __format__(self, spec):
-        if 'L' in spec:
-            newpm = pm = r'  \pm  '
-            pars = _FORMATS['L']['parentheses_fmt']
-        elif 'P' in spec:
-            newpm = pm = '±'
-            pars = _FORMATS['P']['parentheses_fmt']
-        else:
-            newpm = pm = '+/-'
-            pars = _FORMATS['']['parentheses_fmt']
-
-        if 'C' in spec:
-            sp = ''
-            newspec = spec.replace('C', '')
-            pars = _FORMATS['C']['parentheses_fmt']
-        else:
-            sp = ' '
-            newspec = spec
-
-        if 'H' in spec:
-            newpm = '±'
-            newspec = spec.replace('H', '')
-            pars = _FORMATS['H']['parentheses_fmt']
-
-        mag = format(self.magnitude, newspec).replace(pm, sp + newpm + sp)
-
-        if 'L' in newspec and 'S' in newspec:
-            mag = mag.replace('(', r'\left(').replace(')', r'\right)')
-
-        if 'uS' in newspec or 'ue' in newspec or 'u%' in newspec:
-            return mag + ' ' + format(self.units, spec)
-        else:
-            return pars.format(mag) + ' ' + format(self.units, spec)
diff --git a/lib/taurus/external/pint/pint_local/pint_eval.py b/lib/taurus/external/pint/pint_local/pint_eval.py
deleted file mode 100644
index bae61c0..0000000
--- a/lib/taurus/external/pint/pint_local/pint_eval.py
+++ /dev/null
@@ -1,258 +0,0 @@
-'''
-Created on Mar 4, 2015
-
- at author: aaron
-'''
-
-from decimal import Decimal
-import math
-import operator
-
-import token as tokenlib
-
-#for controlling order of operations
-_OP_PRIORITY = {
-    '**' : 3,
-    '^' : 3,
-    'unary' : 2,
-    '*' : 1,
-    '' : 1, #operator for implicit ops
-    '/' : 1,
-    '+' : 0,
-    '-' : 0
-}
-
-_BINARY_OPERATOR_MAP = {
-    '**': operator.pow,
-    '*': operator.mul,
-    '': operator.mul, #operator for implicit ops
-    '/': operator.truediv,
-    '+': operator.add,
-    '-': operator.sub
-}
-
-_UNARY_OPERATOR_MAP = {
-    '+': lambda x : x,
-    '-': lambda x : x * -1
-}
-
-
-class EvalTreeNode(object):
-    
-    def __init__(self, left, operator=None, right=None):
-        '''
-        left + operator + right --> binary op
-        left + operator --> unary op
-        left + right --> implicit op
-        left --> single value
-        '''
-        self.left = left
-        self.operator = operator
-        self.right = right
-        
-    def to_string(self):
-        #for debugging purposes
-        if self.right:
-            comps = [self.left.to_string()]
-            if self.operator:
-                comps.append(self.operator[1])
-            comps.append(self.right.to_string())
-        elif self.operator:
-            comps = [self.operator[1], self.left.to_string()]
-        else:
-            return self.left[1]
-        return '(%s)' % ' '.join(comps)
-    
-    def evaluate(self, define_op, bin_op=_BINARY_OPERATOR_MAP, un_op=_UNARY_OPERATOR_MAP):
-        '''
-        define_op is a callable that translates tokens into objects
-        bin_op and un_op provide functions for performing binary and unary operations
-        '''
-        
-        if self.right:
-            #binary or implicit operator
-            op_text = self.operator[1] if self.operator else ''
-            if op_text not in bin_op:
-                raise Exception('missing binary operator "%s"' % op_text)
-            left = self.left.evaluate(define_op, bin_op, un_op)
-            return bin_op[op_text](left, self.right.evaluate(define_op, bin_op, un_op))
-        elif self.operator:
-            #unary operator
-            op_text = self.operator[1]
-            if op_text not in un_op:
-                raise Exception('missing unary operator "%s"' % op_text)
-            return un_op[op_text](self.left.evaluate(define_op, bin_op, un_op))
-        else:
-            #single value
-            return define_op(self.left)
-        
-
-def build_eval_tree(tokens, op_priority=_OP_PRIORITY, index=0, depth=0, prev_op=None, ):
-    '''
-    Params:
-    Index, depth, and prev_op used recursively, so don't touch.
-    Tokens is an iterable of tokens from an expression to be evaluated.
-    
-    Transform the tokens from an expression into a recursive parse tree, following order of operations.
-    Operations can include binary ops (3 + 4), implicit ops (3 kg), or unary ops (-1).
-    
-    General Strategy:
-    1) Get left side of operator
-    2) If no tokens left, return final result
-    3) Get operator
-    4) Use recursion to create tree starting at token on right side of operator (start at step #1)
-    4.1) If recursive call encounters an operator with lower or equal priority to step #2, exit recursion
-    5) Combine left side, operator, and right side into a new left side
-    6) Go back to step #2
-    '''
-    if depth == 0 and prev_op == None:
-        #ensure tokens is list so we can access by index
-        tokens = list(tokens)
-        
-    result = None
-    
-    while True:
-        current_token = tokens[index]
-        token_type = current_token[0]
-        token_text = current_token[1]
-        
-        if token_type == tokenlib.OP:
-            if token_text == ')':
-                if prev_op == None:
-                    raise Exception('unopened parentheses in tokens: %s' % current_token)
-                elif prev_op == '(':
-                    #close parenthetical group
-                    return result, index
-                else:
-                    #parenthetical group ending, but we need to close sub-operations within group
-                    return result, index - 1
-            elif token_text == '(':
-                #gather parenthetical group
-                right, index = build_eval_tree(tokens, op_priority, index+1, 0, token_text)
-                if not tokens[index][1] == ')':
-                    raise Exception('weird exit from parentheses')
-                if result:
-                    #implicit op with a parenthetical group, i.e. "3 (kg ** 2)"
-                    result = EvalTreeNode(left=result, right=right)
-                else:
-                    #get first token
-                    result = right
-            elif token_text in op_priority:
-                if result:
-                    #equal-priority operators are grouped in a left-to-right order, unless they're
-                    #exponentiation, in which case they're grouped right-to-left
-                    #this allows us to get the expected behavior for multiple exponents 
-                    #    (2^3^4)  --> (2^(3^4))
-                    #    (2 * 3 / 4) --> ((2 * 3) / 4)
-                    if op_priority[token_text] <= op_priority.get(prev_op, -1) and token_text not in ['**', '^']:
-                        #previous operator is higher priority, so end previous binary op
-                        return result, index - 1
-                    #get right side of binary op
-                    right, index = build_eval_tree(tokens, op_priority, index+1, depth+1, token_text)
-                    result = EvalTreeNode(left=result, operator=current_token, right=right)
-                else:
-                    #unary operator
-                    right, index = build_eval_tree(tokens, op_priority, index+1, depth+1, 'unary')
-                    result = EvalTreeNode(left=right, operator=current_token)
-        elif token_type == tokenlib.NUMBER or token_type == tokenlib.NAME:
-            if result:
-                #tokens with an implicit operation i.e. "1 kg"
-                if op_priority[''] <= op_priority.get(prev_op, -1):
-                    #previous operator is higher priority than implicit, so end previous binary op
-                    return result, index - 1
-                right, index = build_eval_tree(tokens, op_priority, index, depth+1, '')
-                result = EvalTreeNode(left=result, right=right)
-            else:
-                #get first token
-                result = EvalTreeNode(left=current_token)
-        
-        if tokens[index][0] == tokenlib.ENDMARKER:
-            if prev_op == '(':
-                raise Exception('unclosed parentheses in tokens')
-            if depth > 0 or prev_op:
-                #have to close recursion
-                return result, index
-            else:
-                #recursion all closed, so just return the final result
-                return result
-            
-        if index + 1 >= len(tokens):
-            #should hit ENDMARKER before this ever happens
-            raise Exception('unexpected end to tokens')
-        
-        index += 1
-
-def _test_build_tree(input_text):
-    '''
-    
-    ####
-    >>> _test_build_tree('3') #single number
-    u'3'
-    >>> _test_build_tree('1 + 2') #basic addition
-    u'(1 + 2)'
-    >>> _test_build_tree('2 * 3 + 4') #order of operations
-    u'((2 * 3) + 4)'
-    >>> _test_build_tree('2 * (3 + 4)') #parentheses
-    u'(2 * (3 + 4))'
-    >>> _test_build_tree('1 + 2 * 3 ** (4 + 3 / 5)') #more order of operations
-    u'(1 + (2 * (3 ** (4 + (3 / 5)))))'
-    >>> _test_build_tree('1 * ((3 + 4) * 5)') #nested parentheses at beginning
-    u'(1 * ((3 + 4) * 5))'
-    >>> _test_build_tree('1 * (5 * (3 + 4))') #nested parentheses at end
-    u'(1 * (5 * (3 + 4)))'
-    >>> _test_build_tree('1 * (5 * (3 + 4) / 6)') #nested parentheses in middle
-    u'(1 * ((5 * (3 + 4)) / 6))'
-    >>> _test_build_tree('-1') #unary
-    u'(- 1)'
-    >>> _test_build_tree('3 * -1') #unary
-    u'(3 * (- 1))'
-    >>> _test_build_tree('3 * --1') #double unary
-    u'(3 * (- (- 1)))'
-    >>> _test_build_tree('3 * -(2 + 4)') #parenthetical unary
-    u'(3 * (- (2 + 4)))'
-    >>> _test_build_tree('3 * -((2 + 4))') #parenthetical unary
-    u'(3 * (- (2 + 4)))'
-    >>> _test_build_tree('3 4') #implicit op
-    u'(3 4)'
-    >>> _test_build_tree('3 (2 + 4)') #implicit op, then parentheses
-    u'(3 (2 + 4))'
-    >>> _test_build_tree('(3 ** 4 ) 5') #parentheses, then implicit
-    u'((3 ** 4) 5)'
-    >>> _test_build_tree('3 4 ** 5') #implicit op, then exponentiation
-    u'(3 (4 ** 5))'
-    >>> _test_build_tree('3 4 + 5') #implicit op, then addition
-    u'((3 4) + 5)'
-    >>> _test_build_tree('3 ** 4 5') #power followed by implicit
-    u'((3 ** 4) 5)'
-    >>> _test_build_tree('3 (4 ** 5)') #implicit with parentheses
-    u'(3 (4 ** 5))'
-    >>> _test_build_tree('3e-1') #exponent with e
-    u'3e-1'
-    
-    >>> _test_build_tree('kg ** 1 * s ** 2') #multiple units with exponents
-    u'((kg ** 1) * (s ** 2))'
-    >>> _test_build_tree('kg ** -1 * s ** -2') #multiple units with neg exponents
-    u'((kg ** (- 1)) * (s ** (- 2)))'
-    >>> _test_build_tree('kg^-1 * s^-2') #multiple units with neg exponents
-    u'((kg ^ (- 1)) * (s ^ (- 2)))'
-    >>> _test_build_tree('kg^-1 s^-2') #multiple units with neg exponents, implicit op
-    u'((kg ^ (- 1)) (s ^ (- 2)))'
-    
-    >>> _test_build_tree('2 ^ 3 ^ 2') #nested power
-    u'(2 ^ (3 ^ 2))'
-    
-    >>> _test_build_tree('gram * second / meter ** 2') #nested power
-    u'((gram * second) / (meter ** 2))'
-    >>> _test_build_tree('gram / meter ** 2 / second') #nested power
-    u'((gram / (meter ** 2)) / second)'
-    
-    #units should behave like numbers, so we don't need a bunch of extra tests for them
-    >>> _test_build_tree('3 kg + 5') #implicit op, then addition
-    u'((3 kg) + 5)'
-    '''
-    return build_eval_tree(tokenizer(input_text)).to_string()
-
-if __name__ == "__main__":
-    import doctest, pint
-    from pint.compat import tokenizer
-    doctest.testmod()
diff --git a/lib/taurus/external/pint/pint_local/quantity.py b/lib/taurus/external/pint/pint_local/quantity.py
deleted file mode 100644
index 0eba47c..0000000
--- a/lib/taurus/external/pint/pint_local/quantity.py
+++ /dev/null
@@ -1,1337 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    pint.quantity
-    ~~~~~~~~~~~~~
-
-    :copyright: 2013 by Pint Authors, see AUTHORS for more details.
-    :license: BSD, see LICENSE for more details.
-"""
-
-from __future__ import division, unicode_literals, print_function, absolute_import
-
-import copy
-import math
-import operator
-import functools
-import bisect
-
-from .formatting import remove_custom_flags
-from .errors import (DimensionalityError, OffsetUnitCalculusError,
-                     UndefinedUnitError)
-from .definitions import UnitDefinition
-from .compat import string_types, ndarray, np, _to_magnitude, long_type
-from .util import (logger, UnitsContainer, SharedRegistryObject,
-                   to_units_container, infer_base_unit)
-
-
-def _eq(first, second, check_all):
-    """Comparison of scalars and arrays
-    """
-    out = first == second
-    if check_all and isinstance(out, ndarray):
-        return np.all(out)
-    return out
-
-
-class _Exception(Exception):            # pragma: no cover
-
-    def __init__(self, internal):
-        self.internal = internal
-
-
-class _Quantity(SharedRegistryObject):
-    """Implements a class to describe a physical quantity:
-    the product of a numerical value and a unit of measurement.
-
-    :param value: value of the physical quantity to be created.
-    :type value: str, Quantity or any numeric type.
-    :param units: units of the physical quantity to be created.
-    :type units: UnitsContainer, str or Quantity.
-    """
-
-    #: Default formatting string.
-    default_format = ''
-
-    def __reduce__(self):
-        from . import _build_quantity
-        return _build_quantity, (self.magnitude, self._units)
-
-    def __new__(cls, value, units=None):
-        if units is None:
-            if isinstance(value, string_types):
-                if value == '':
-                    raise ValueError('Expression to parse as Quantity cannot '
-                                     'be an empty string.')
-                inst = cls._REGISTRY.parse_expression(value)
-                return cls.__new__(cls, inst)
-            elif isinstance(value, cls):
-                inst = copy.copy(value)
-            else:
-                inst = object.__new__(cls)
-                inst._magnitude = _to_magnitude(value, inst.force_ndarray)
-                inst._units = UnitsContainer()
-        elif isinstance(units, (UnitsContainer, UnitDefinition)):
-            inst = object.__new__(cls)
-            inst._magnitude = _to_magnitude(value, inst.force_ndarray)
-            inst._units = units
-        elif isinstance(units, string_types):
-            inst = object.__new__(cls)
-            inst._magnitude = _to_magnitude(value, inst.force_ndarray)
-            inst._units = inst._REGISTRY.parse_units(units)._units
-        elif isinstance(units, SharedRegistryObject):
-            if isinstance(units, _Quantity) and units.magnitude != 1:
-                inst = copy.copy(units)
-                logger.warning('Creating new Quantity using a non unity '
-                               'Quantity as units.')
-            else:
-                inst = object.__new__(cls)
-                inst._units = units._units
-            inst._magnitude = _to_magnitude(value, inst.force_ndarray)
-        else:
-            raise TypeError('units must be of type str, Quantity or '
-                            'UnitsContainer; not {0}.'.format(type(units)))
-
-        inst.__used = False
-        inst.__handling = None
-        return inst
-
-    @property
-    def debug_used(self):
-        return self.__used
-
-    def __copy__(self):
-        ret = self.__class__(copy.copy(self._magnitude), self._units)
-        ret.__used = self.__used
-        return ret
-
-    def __deepcopy__(self, memo):
-        ret = self.__class__(copy.deepcopy(self._magnitude, memo),
-                             copy.deepcopy(self._units, memo))
-        ret.__used = self.__used
-        return ret
-
-    def __str__(self):
-        return format(self)
-
-    def __repr__(self):
-        return "<Quantity({0}, '{1}')>".format(self._magnitude, self._units)
-
-    def __format__(self, spec):
-        spec = spec or self.default_format
-        if '#' in spec:
-            spec = spec.replace('#', '')
-            obj = self.to_compact()
-        else:
-            obj = self
-        return '{0} {1}'.format(
-            format(obj.magnitude, remove_custom_flags(spec)),
-            format(obj.units, spec))
-
-    # IPython related code
-    def _repr_html_(self):
-        return self.__format__('H')
-
-    def _repr_latex_(self):
-        return "$" + self.__format__('L') + "$"
-
-    @property
-    def magnitude(self):
-        """Quantity's magnitude. Long form for `m`
-        """
-        return self._magnitude
-
-    @property
-    def m(self):
-        """Quantity's magnitude. Short form for `magnitude`
-        """
-        return self._magnitude
-
-    def m_as(self, unit):
-        """Quantity's magnitude expressed in particular units.
-
-        :param other: destination units.
-        :type other: Quantity, str or dict
-        """
-        return (self / unit).to('').magnitude
-
-    @property
-    def units(self):
-        """Quantity's units. Long form for `u`
-
-        :rtype: UnitContainer
-        """
-        return self._REGISTRY.Unit(self._units)
-
-    @property
-    def u(self):
-        """Quantity's units. Short form for `units`
-
-        :rtype: UnitContainer
-        """
-        return self._REGISTRY.Unit(self._units)
-
-    @property
-    def unitless(self):
-        """Return true if the quantity does not have units.
-        """
-        return not bool(self.to_root_units()._units)
-
-    @property
-    def dimensionless(self):
-        """Return true if the quantity is dimensionless.
-        """
-        tmp = self.to_root_units()
-
-        return not bool(tmp.dimensionality)
-
-    @property
-    def dimensionality(self):
-        """Quantity's dimensionality (e.g. {length: 1, time: -1})
-        """
-        try:
-            return self._dimensionality
-        except AttributeError:
-            self._dimensionality = self._REGISTRY._get_dimensionality(self._units)
-
-        return self._dimensionality
-
-    def compatible_units(self, *contexts):
-        if contexts:
-            with self._REGISTRY.context(*contexts):
-                return self._REGISTRY.get_compatible_units(self._units)
-
-        return self._REGISTRY.get_compatible_units(self._units)
-
-    def _convert_magnitude_not_inplace(self, other, *contexts, **ctx_kwargs):
-        if contexts:
-            with self._REGISTRY.context(*contexts, **ctx_kwargs):
-                return self._REGISTRY.convert(self._magnitude, self._units, other)
-
-        return self._REGISTRY.convert(self._magnitude, self._units, other)
-
-    def _convert_magnitude(self, other, *contexts, **ctx_kwargs):
-        if contexts:
-            with self._REGISTRY.context(*contexts, **ctx_kwargs):
-                return self._REGISTRY.convert(self._magnitude, self._units, other)
-
-        return self._REGISTRY.convert(self._magnitude, self._units, other,
-                                      inplace=isinstance(self._magnitude, ndarray))
-
-    def ito(self, other=None, *contexts, **ctx_kwargs):
-        """Inplace rescale to different units.
-
-        :param other: destination units.
-        :type other: Quantity, str or dict
-        """
-        other = to_units_container(other, self._REGISTRY)
-
-        self._magnitude = self._convert_magnitude(other, *contexts,
-                                                  **ctx_kwargs)
-        self._units = other
-
-        return None
-
-    def to(self, other=None, *contexts, **ctx_kwargs):
-        """Return Quantity rescaled to different units.
-
-        :param other: destination units.
-        :type other: Quantity, str or dict
-        """
-        other = to_units_container(other, self._REGISTRY)
-
-        magnitude = self._convert_magnitude_not_inplace(other, *contexts, **ctx_kwargs)
-
-        return self.__class__(magnitude, other)
-
-    def ito_root_units(self):
-        """Return Quantity rescaled to base units
-        """
-
-        _, other = self._REGISTRY._get_root_units(self._units)
-
-        self._magnitude = self._convert_magnitude(other)
-        self._units = other
-
-        return None
-
-    def to_root_units(self):
-        """Return Quantity rescaled to base units
-        """
-        _, other = self._REGISTRY._get_root_units(self._units)
-
-        magnitude = self._convert_magnitude_not_inplace(other)
-
-        return self.__class__(magnitude, other)
-
-    def ito_base_units(self):
-        """Return Quantity rescaled to base units
-        """
-
-        _, other = self._REGISTRY._get_base_units(self._units)
-
-        self._magnitude = self._convert_magnitude(other)
-        self._units = other
-
-        return None
-
-    def to_base_units(self):
-        """Return Quantity rescaled to base units
-        """
-        _, other = self._REGISTRY._get_base_units(self._units)
-
-        magnitude = self._convert_magnitude_not_inplace(other)
-
-        return self.__class__(magnitude, other)
-
-
-    def to_compact(self, unit=None):
-        """Return Quantity rescaled to compact, human-readable units.
-
-        To get output in terms of a different unit, use the unit parameter.
-
-        >>> import pint
-        >>> ureg = pint.UnitRegistry()
-        >>> (200e-9*ureg.s).to_compact()
-        <Quantity(200.0, 'nanosecond')>
-        >>> (1e-2*ureg('kg m/s^2')).to_compact('N')
-        <Quantity(10.0, 'millinewton')>
-        """
-        if self.unitless:
-            return self
-
-        SI_prefixes = {}
-        for prefix in self._REGISTRY._prefixes.values():
-            try:
-                scale = prefix.converter.scale
-                # Kludgy way to check if this is an SI prefix
-                log10_scale = int(math.log10(scale))
-                if log10_scale == math.log10(scale):
-                    SI_prefixes[log10_scale] = prefix.name
-            except:
-                SI_prefixes[0] = ''
-
-        SI_prefixes = sorted(SI_prefixes.items())
-        SI_powers = [item[0] for item in SI_prefixes]
-        SI_bases = [item[1] for item in SI_prefixes]
-
-        if unit is None:
-            unit = infer_base_unit(self)
-
-        q_base = self.to(unit)
-
-        magnitude = q_base.magnitude
-        # Only changes the prefix on the first unit in the UnitContainer
-        unit_str = list(q_base._units.items())[0][0]
-        unit_power = list(q_base._units.items())[0][1]
-
-        if unit_power > 0:
-            power = int(math.floor(math.log10(magnitude) / unit_power / 3)) * 3
-        else:
-            power = int(math.ceil(math.log10(magnitude) / unit_power / 3)) * 3
-
-        prefix = SI_bases[bisect.bisect_left(SI_powers, power)]
-
-        new_unit_str = prefix+unit_str
-        new_unit_container = q_base._units.rename(unit_str, new_unit_str)
-
-        return self.to(new_unit_container)
-
-    # Mathematical operations
-    def __int__(self):
-        if self.dimensionless:
-            return int(self._convert_magnitude_not_inplace(UnitsContainer()))
-        raise DimensionalityError(self._units, 'dimensionless')
-
-    def __long__(self):
-        if self.dimensionless:
-            return long_type(self._convert_magnitude_not_inplace(UnitsContainer()))
-        raise DimensionalityError(self._units, 'dimensionless')
-
-    def __float__(self):
-        if self.dimensionless:
-            return float(self._convert_magnitude_not_inplace(UnitsContainer()))
-        raise DimensionalityError(self._units, 'dimensionless')
-
-    def __complex__(self):
-        if self.dimensionless:
-            return complex(self._convert_magnitude_not_inplace(UnitsContainer()))
-        raise DimensionalityError(self._units, 'dimensionless')
-
-    def _iadd_sub(self, other, op):
-        """Perform addition or subtraction operation in-place and return the result.
-
-        :param other: object to be added to / subtracted from self
-        :type other: Quantity or any type accepted by :func:`_to_magnitude`
-        :param op: operator function (e.g. operator.add, operator.isub)
-        :type op: function
-        """
-        if not self._check(other):
-            # other not from same Registry or not a Quantity
-            try:
-                other_magnitude = _to_magnitude(other, self.force_ndarray)
-            except TypeError:
-                return NotImplemented
-            if _eq(other, 0, True):
-                # If the other value is 0 (but not Quantity 0)
-                # do the operation without checking units.
-                # We do the calculation instead of just returning the same
-                # value to enforce any shape checking and type casting due to
-                # the operation.
-                self._magnitude = op(self._magnitude, other_magnitude)
-            elif self.dimensionless:
-                self.ito(UnitsContainer())
-                self._magnitude = op(self._magnitude, other_magnitude)
-            else:
-                raise DimensionalityError(self._units, 'dimensionless')
-            return self
-
-        if not self.dimensionality == other.dimensionality:
-            raise DimensionalityError(self._units, other._units,
-                                      self.dimensionality,
-                                      other.dimensionality)
-
-        # Next we define some variables to make if-clauses more readable.
-        self_non_mul_units = self._get_non_multiplicative_units()
-        is_self_multiplicative = len(self_non_mul_units) == 0
-        if len(self_non_mul_units) == 1:
-            self_non_mul_unit = self_non_mul_units[0]
-        other_non_mul_units = other._get_non_multiplicative_units()
-        is_other_multiplicative = len(other_non_mul_units) == 0
-        if len(other_non_mul_units) == 1:
-            other_non_mul_unit = other_non_mul_units[0]
-
-        # Presence of non-multiplicative units gives rise to several cases.
-        if is_self_multiplicative and is_other_multiplicative:
-            if self._units == other._units:
-                self._magnitude = op(self._magnitude, other._magnitude)
-            # If only self has a delta unit, other determines unit of result.
-            elif self._get_delta_units() and not other._get_delta_units():
-                self._magnitude = op(self._convert_magnitude(other._units),
-                                     other._magnitude)
-                self._units = other._units
-            else:
-                self._magnitude = op(self._magnitude,
-                                     other.to(self._units)._magnitude)
-
-        elif (op == operator.isub and len(self_non_mul_units) == 1
-                and self._units[self_non_mul_unit] == 1
-                and not other._has_compatible_delta(self_non_mul_unit)):
-            if self._units == other._units:
-                self._magnitude = op(self._magnitude, other._magnitude)
-            else:
-                self._magnitude = op(self._magnitude,
-                                     other.to(self._units)._magnitude)
-            self._units = self._units.rename(self_non_mul_unit,
-                                             'delta_' + self_non_mul_unit)
-
-        elif (op == operator.isub and len(other_non_mul_units) == 1
-                and other._units[other_non_mul_unit] == 1
-                and not self._has_compatible_delta(other_non_mul_unit)):
-            # we convert to self directly since it is multiplicative
-            self._magnitude = op(self._magnitude,
-                                 other.to(self._units)._magnitude)
-
-        elif (len(self_non_mul_units) == 1
-                # order of the dimension of offset unit == 1 ?
-                and self._units[self_non_mul_unit] == 1
-                and other._has_compatible_delta(self_non_mul_unit)):
-            # Replace offset unit in self by the corresponding delta unit.
-            # This is done to prevent a shift by offset in the to()-call.
-            tu = self._units.rename(self_non_mul_unit,
-                                    'delta_' + self_non_mul_unit)
-            self._magnitude = op(self._magnitude, other.to(tu)._magnitude)
-        elif (len(other_non_mul_units) == 1
-                # order of the dimension of offset unit == 1 ?
-                and other._units[other_non_mul_unit] == 1
-                and self._has_compatible_delta(other_non_mul_unit)):
-            # Replace offset unit in other by the corresponding delta unit.
-            # This is done to prevent a shift by offset in the to()-call.
-            tu = other._units.rename(other_non_mul_unit,
-                                     'delta_' + other_non_mul_unit)
-            self._magnitude = op(self._convert_magnitude(tu), other._magnitude)
-            self._units = other._units
-        else:
-            raise OffsetUnitCalculusError(self._units, other._units)
-
-        return self
-
-    def _add_sub(self, other, op):
-        """Perform addition or subtraction operation and return the result.
-
-        :param other: object to be added to / subtracted from self
-        :type other: Quantity or any type accepted by :func:`_to_magnitude`
-        :param op: operator function (e.g. operator.add, operator.isub)
-        :type op: function
-        """
-        if not self._check(other):
-            # other not from same Registry or not a Quantity
-            if _eq(other, 0, True):
-                # If the other value is 0 (but not Quantity 0)
-                # do the operation without checking units.
-                # We do the calculation instead of just returning the same
-                # value to enforce any shape checking and type casting due to
-                # the operation.
-                units = self._units
-                magnitude = op(self._magnitude,
-                               _to_magnitude(other, self.force_ndarray))
-            elif self.dimensionless:
-                units = UnitsContainer()
-                magnitude = op(self.to(units)._magnitude,
-                               _to_magnitude(other, self.force_ndarray))
-            else:
-                raise DimensionalityError(self._units, 'dimensionless')
-            return self.__class__(magnitude, units)
-
-        if not self.dimensionality == other.dimensionality:
-            raise DimensionalityError(self._units, other._units,
-                                      self.dimensionality,
-                                      other.dimensionality)
-
-        # Next we define some variables to make if-clauses more readable.
-        self_non_mul_units = self._get_non_multiplicative_units()
-        is_self_multiplicative = len(self_non_mul_units) == 0
-        if len(self_non_mul_units) == 1:
-            self_non_mul_unit = self_non_mul_units[0]
-        other_non_mul_units = other._get_non_multiplicative_units()
-        is_other_multiplicative = len(other_non_mul_units) == 0
-        if len(other_non_mul_units) == 1:
-            other_non_mul_unit = other_non_mul_units[0]
-
-        # Presence of non-multiplicative units gives rise to several cases.
-        if is_self_multiplicative and is_other_multiplicative:
-            if self._units == other._units:
-                magnitude = op(self._magnitude, other._magnitude)
-                units = self._units
-            # If only self has a delta unit, other determines unit of result.
-            elif self._get_delta_units() and not other._get_delta_units():
-                magnitude = op(self._convert_magnitude(other._units),
-                               other._magnitude)
-                units = other._units
-            else:
-                units = self._units
-                magnitude = op(self._magnitude,
-                               other.to(self._units).magnitude)
-
-        elif (op == operator.sub and len(self_non_mul_units) == 1
-                and self._units[self_non_mul_unit] == 1
-                and not other._has_compatible_delta(self_non_mul_unit)):
-            if self._units == other._units:
-                magnitude = op(self._magnitude, other._magnitude)
-            else:
-                magnitude = op(self._magnitude,
-                               other.to(self._units)._magnitude)
-            units = self._units.rename(self_non_mul_unit,
-                                      'delta_' + self_non_mul_unit)
-
-        elif (op == operator.sub and len(other_non_mul_units) == 1
-                and other._units[other_non_mul_unit] == 1
-                and not self._has_compatible_delta(other_non_mul_unit)):
-            # we convert to self directly since it is multiplicative
-            magnitude = op(self._magnitude,
-                           other.to(self._units)._magnitude)
-            units = self._units
-
-        elif (len(self_non_mul_units) == 1
-                # order of the dimension of offset unit == 1 ?
-                and self._units[self_non_mul_unit] == 1
-                and other._has_compatible_delta(self_non_mul_unit)):
-            # Replace offset unit in self by the corresponding delta unit.
-            # This is done to prevent a shift by offset in the to()-call.
-            tu = self._units.rename(self_non_mul_unit,
-                                    'delta_' + self_non_mul_unit)
-            magnitude = op(self._magnitude, other.to(tu).magnitude)
-            units = self._units
-        elif (len(other_non_mul_units) == 1
-                # order of the dimension of offset unit == 1 ?
-                and other._units[other_non_mul_unit] == 1
-                and self._has_compatible_delta(other_non_mul_unit)):
-            # Replace offset unit in other by the corresponding delta unit.
-            # This is done to prevent a shift by offset in the to()-call.
-            tu = other._units.rename(other_non_mul_unit,
-                                     'delta_' + other_non_mul_unit)
-            magnitude = op(self._convert_magnitude(tu), other._magnitude)
-            units = other._units
-        else:
-            raise OffsetUnitCalculusError(self._units, other._units)
-
-        return self.__class__(magnitude, units)
-
-    def __iadd__(self, other):
-        if not isinstance(self._magnitude, ndarray):
-            return self._add_sub(other, operator.add)
-        else:
-            return self._iadd_sub(other, operator.iadd)
-
-    def __add__(self, other):
-        return self._add_sub(other, operator.add)
-
-    __radd__ = __add__
-
-    def __isub__(self, other):
-        if not isinstance(self._magnitude, ndarray):
-            return self._add_sub(other, operator.sub)
-        else:
-            return self._iadd_sub(other, operator.isub)
-
-    def __sub__(self, other):
-        return self._add_sub(other, operator.sub)
-
-    def __rsub__(self, other):
-        return -self._add_sub(other, operator.sub)
-
-    def _imul_div(self, other, magnitude_op, units_op=None):
-        """Perform multiplication or division operation in-place and return the
-        result.
-
-        :param other: object to be multiplied/divided with self
-        :type other: Quantity or any type accepted by :func:`_to_magnitude`
-        :param magnitude_op: operator function to perform on the magnitudes
-            (e.g. operator.mul)
-        :type magnitude_op: function
-        :param units_op: operator function to perform on the units; if None,
-            *magnitude_op* is used
-        :type units_op: function or None
-        """
-        if units_op is None:
-            units_op = magnitude_op
-
-        offset_units_self = self._get_non_multiplicative_units()
-        no_offset_units_self = len(offset_units_self)
-
-        if not self._check(other):
-
-            if not self._ok_for_muldiv(no_offset_units_self):
-                raise OffsetUnitCalculusError(self._units,
-                                              getattr(other, 'units', ''))
-            if len(offset_units_self) == 1:
-                if (self._units[offset_units_self[0]] != 1
-                        or magnitude_op not in [operator.mul, operator.imul]):
-                    raise OffsetUnitCalculusError(self._units,
-                                                  getattr(other, 'units', ''))
-            try:
-                other_magnitude = _to_magnitude(other, self.force_ndarray)
-            except TypeError:
-                return NotImplemented
-            self._magnitude = magnitude_op(self._magnitude, other_magnitude)
-            self._units = units_op(self._units, UnitsContainer())
-            return self
-
-        if not isinstance(other, _Quantity):
-            self._magnitude = magnitude_op(self._magnitude, 1)
-            self._units = units_op(self._units, other._units)
-            return self
-
-        if not self._ok_for_muldiv(no_offset_units_self):
-            raise OffsetUnitCalculusError(self._units, other._units)
-        elif no_offset_units_self == 1 and len(self._units) == 1:
-            self.ito_root_units()
-
-        no_offset_units_other = len(other._get_non_multiplicative_units())
-
-        if not other._ok_for_muldiv(no_offset_units_other):
-            raise OffsetUnitCalculusError(self._units, other._units)
-        elif no_offset_units_other == 1 and len(other._units) == 1:
-            other.ito_root_units()
-
-        self._magnitude = magnitude_op(self._magnitude, other._magnitude)
-        self._units = units_op(self._units, other._units)
-
-        return self
-
-    def _mul_div(self, other, magnitude_op, units_op=None):
-        """Perform multiplication or division operation and return the result.
-
-        :param other: object to be multiplied/divided with self
-        :type other: Quantity or any type accepted by :func:`_to_magnitude`
-        :param magnitude_op: operator function to perform on the magnitudes
-            (e.g. operator.mul)
-        :type magnitude_op: function
-        :param units_op: operator function to perform on the units; if None,
-            *magnitude_op* is used
-        :type units_op: function or None
-        """
-        if units_op is None:
-            units_op = magnitude_op
-
-        offset_units_self = self._get_non_multiplicative_units()
-        no_offset_units_self = len(offset_units_self)
-
-        if not self._check(other):
-
-            if not self._ok_for_muldiv(no_offset_units_self):
-                raise OffsetUnitCalculusError(self._units,
-                                              getattr(other, 'units', ''))
-            if len(offset_units_self) == 1:
-                if (self._units[offset_units_self[0]] != 1
-                        or magnitude_op not in [operator.mul, operator.imul]):
-                    raise OffsetUnitCalculusError(self._units,
-                                                  getattr(other, 'units', ''))
-            try:
-                other_magnitude = _to_magnitude(other, self.force_ndarray)
-            except TypeError:
-                return NotImplemented
-
-            magnitude = magnitude_op(self._magnitude, other_magnitude)
-            units = units_op(self._units, UnitsContainer())
-
-            return self.__class__(magnitude, units)
-
-        if not isinstance(other, _Quantity):
-            magnitude = self._magnitude
-            units = units_op(self._units, other._units)
-            return self.__class__(magnitude, units)
-
-        new_self = self
-
-        if not self._ok_for_muldiv(no_offset_units_self):
-            raise OffsetUnitCalculusError(self._units, other._units)
-        elif no_offset_units_self == 1 and len(self._units) == 1:
-            new_self = self.to_root_units()
-
-        no_offset_units_other = len(other._get_non_multiplicative_units())
-
-        if not other._ok_for_muldiv(no_offset_units_other):
-            raise OffsetUnitCalculusError(self._units, other._units)
-        elif no_offset_units_other == 1 and len(other._units) == 1:
-            other = other.to_root_units()
-
-        magnitude = magnitude_op(new_self._magnitude, other._magnitude)
-        units = units_op(new_self._units, other._units)
-
-        return self.__class__(magnitude, units)
-
-    def __imul__(self, other):
-        if not isinstance(self._magnitude, ndarray):
-            return self._mul_div(other, operator.mul)
-        else:
-            return self._imul_div(other, operator.imul)
-
-    def __mul__(self, other):
-        return self._mul_div(other, operator.mul)
-
-    __rmul__ = __mul__
-
-    def __itruediv__(self, other):
-        if not isinstance(self._magnitude, ndarray):
-            return self._mul_div(other, operator.truediv)
-        else:
-            return self._imul_div(other, operator.itruediv)
-
-    def __truediv__(self, other):
-        return self._mul_div(other, operator.truediv)
-
-    def __ifloordiv__(self, other):
-        if not isinstance(self._magnitude, ndarray):
-            return self._mul_div(other, operator.floordiv, units_op=operator.itruediv)
-        else:
-            return self._imul_div(other, operator.ifloordiv, units_op=operator.itruediv)
-
-    def __floordiv__(self, other):
-        return self._mul_div(other, operator.floordiv, units_op=operator.truediv)
-
-    def __rtruediv__(self, other):
-        try:
-            other_magnitude = _to_magnitude(other, self.force_ndarray)
-        except TypeError:
-            return NotImplemented
-
-        no_offset_units_self = len(self._get_non_multiplicative_units())
-        if not self._ok_for_muldiv(no_offset_units_self):
-            raise OffsetUnitCalculusError(self._units, '')
-        elif no_offset_units_self == 1 and len(self._units) == 1:
-            self = self.to_root_units()
-
-        return self.__class__(other_magnitude / self._magnitude, 1 / self._units)
-
-    def __rfloordiv__(self, other):
-        try:
-            other_magnitude = _to_magnitude(other, self.force_ndarray)
-        except TypeError:
-            return NotImplemented
-
-        no_offset_units_self = len(self._get_non_multiplicative_units())
-        if not self._ok_for_muldiv(no_offset_units_self):
-            raise OffsetUnitCalculusError(self._units, '')
-        elif no_offset_units_self == 1 and len(self._units) == 1:
-            self = self.to_root_units()
-
-        return self.__class__(other_magnitude // self._magnitude, 1 / self._units)
-
-    __div__ = __truediv__
-    __rdiv__ = __rtruediv__
-    __idiv__ = __itruediv__
-
-    def __ipow__(self, other):
-        if not isinstance(self._magnitude, ndarray):
-            return self.__pow__(other)
-
-        try:
-            other_magnitude = _to_magnitude(other, self.force_ndarray)
-        except TypeError:
-            return NotImplemented
-        else:
-            if not self._ok_for_muldiv:
-                raise OffsetUnitCalculusError(self._units)
-
-            if isinstance(getattr(other, '_magnitude', other), ndarray):
-                # arrays are refused as exponent, because they would create
-                #  len(array) quanitites of len(set(array)) different units
-                if np.size(other) > 1:
-                    raise DimensionalityError(self._units, 'dimensionless')
-
-            if other == 1:
-                return self
-            elif other == 0:
-                self._units = UnitsContainer()
-            else:
-                if not self._is_multiplicative:
-                    if self._REGISTRY.autoconvert_offset_to_baseunit:
-                        self.ito_base_units()
-                    else:
-                        raise OffsetUnitCalculusError(self._units)
-
-                if getattr(other, 'dimensionless', False):
-                    other = other.to_base_units()
-                    self._units **= other.magnitude
-                elif not getattr(other, 'dimensionless', True):
-                    raise DimensionalityError(self._units, 'dimensionless')
-                else:
-                    self._units **= other
-
-            self._magnitude **= _to_magnitude(other, self.force_ndarray)
-            return self
-
-    def __pow__(self, other):
-        try:
-            other_magnitude = _to_magnitude(other, self.force_ndarray)
-        except TypeError:
-            return NotImplemented
-        else:
-            if not self._ok_for_muldiv:
-                raise OffsetUnitCalculusError(self._units)
-
-            if isinstance(getattr(other, '_magnitude', other), ndarray):
-                # arrays are refused as exponent, because they would create
-                #  len(array) quantities of len(set(array)) different units
-                if np.size(other) > 1:
-                    raise DimensionalityError(self._units, 'dimensionless')
-
-            new_self = self
-            if other == 1:
-                return self
-            elif other == 0:
-                units = UnitsContainer()
-            else:
-                if not self._is_multiplicative:
-                    if self._REGISTRY.autoconvert_offset_to_baseunit:
-                        new_self = self.to_root_units()
-                    else:
-                        raise OffsetUnitCalculusError(self._units)
-
-                if getattr(other, 'dimensionless', False):
-                    units = new_self._units ** other.to_root_units().magnitude
-                elif not getattr(other, 'dimensionless', True):
-                    raise DimensionalityError(self._units, 'dimensionless')
-                else:
-                    units = new_self._units ** other
-
-            magnitude = new_self._magnitude ** _to_magnitude(other, self.force_ndarray)
-            return self.__class__(magnitude, units)
-
-    def __rpow__(self, other):
-        try:
-            other_magnitude = _to_magnitude(other, self.force_ndarray)
-        except TypeError:
-            return NotImplemented
-        else:
-            if not self.dimensionless:
-                raise DimensionalityError(self._units, 'dimensionless')
-            if isinstance(self._magnitude, ndarray):
-                if np.size(self._magnitude) > 1:
-                    raise DimensionalityError(self._units, 'dimensionless')
-            new_self = self.to_root_units()
-            return other**new_self._magnitude
-
-    def __abs__(self):
-        return self.__class__(abs(self._magnitude), self._units)
-
-    def __round__(self, ndigits=0):
-        return self.__class__(round(self._magnitude, ndigits=ndigits), self._units)
-
-    def __pos__(self):
-        return self.__class__(operator.pos(self._magnitude), self._units)
-
-    def __neg__(self):
-        return self.__class__(operator.neg(self._magnitude), self._units)
-
-    def __eq__(self, other):
-        # We compare to the base class of Quantity because
-        # each Quantity class is unique.
-        if not isinstance(other, _Quantity):
-            return (self.dimensionless and
-                    _eq(self._convert_magnitude(UnitsContainer()), other, False))
-
-        if _eq(self._magnitude, 0, True) and _eq(other._magnitude, 0, True):
-            return self.dimensionality == other.dimensionality
-
-        if self._units == other._units:
-            return _eq(self._magnitude, other._magnitude, False)
-
-        try:
-            return _eq(self._convert_magnitude_not_inplace(other._units),
-                       other._magnitude, False)
-        except DimensionalityError:
-            return False
-
-    def __ne__(self, other):
-        out = self.__eq__(other)
-        if isinstance(out, ndarray):
-            return np.logical_not(out)
-        return not out
-
-    def compare(self, other, op):
-        if not isinstance(other, self.__class__):
-            if self.dimensionless:
-                return op(self._convert_magnitude_not_inplace(UnitsContainer()), other)
-            else:
-                raise ValueError('Cannot compare Quantity and {0}'.format(type(other)))
-
-        if self._units == other._units:
-            return op(self._magnitude, other._magnitude)
-        if self.dimensionality != other.dimensionality:
-            raise DimensionalityError(self._units, other._units,
-                                      self.dimensionality, other.dimensionality)
-        return op(self.to_root_units().magnitude,
-                  other.to_root_units().magnitude)
-
-    __lt__ = lambda self, other: self.compare(other, op=operator.lt)
-    __le__ = lambda self, other: self.compare(other, op=operator.le)
-    __ge__ = lambda self, other: self.compare(other, op=operator.ge)
-    __gt__ = lambda self, other: self.compare(other, op=operator.gt)
-
-    def __bool__(self):
-        return bool(self._magnitude)
-
-    __nonzero__ = __bool__
-
-    # NumPy Support
-    __radian = 'radian'
-    __same_units = 'equal greater greater_equal less less_equal not_equal arctan2'.split()
-    #: Dictionary mapping ufunc/attributes names to the units that they
-    #: require (conversion will be tried).
-    __require_units = {'cumprod': '',
-                       'arccos': '', 'arcsin': '', 'arctan': '',
-                       'arccosh': '', 'arcsinh': '', 'arctanh': '',
-                       'exp': '', 'expm1': '', 'exp2': '',
-                       'log': '', 'log10': '', 'log1p': '', 'log2': '',
-                       'sin': __radian, 'cos': __radian, 'tan': __radian,
-                       'sinh': __radian, 'cosh': __radian, 'tanh': __radian,
-                       'radians': 'degree', 'degrees': __radian,
-                       'deg2rad': 'degree', 'rad2deg': __radian,
-                       'logaddexp': '', 'logaddexp2': ''}
-
-    #: Dictionary mapping ufunc/attributes names to the units that they
-    #: will set on output.
-    __set_units = {'cos': '', 'sin': '', 'tan': '',
-                   'cosh': '', 'sinh': '', 'tanh': '',
-                   'arccos': __radian, 'arcsin': __radian,
-                   'arctan': __radian, 'arctan2': __radian,
-                   'arccosh': __radian, 'arcsinh': __radian,
-                   'arctanh': __radian,
-                   'degrees': 'degree', 'radians': __radian,
-                   'expm1': '', 'cumprod': '',
-                   'rad2deg': 'degree', 'deg2rad': __radian}
-
-    #: List of ufunc/attributes names in which units are copied from the
-    #: original.
-    __copy_units = 'compress conj conjugate copy cumsum diagonal flatten ' \
-                   'max mean min ptp ravel repeat reshape round ' \
-                   'squeeze std sum take trace transpose ' \
-                   'ceil floor hypot rint ' \
-                   'add subtract ' \
-                   'copysign nextafter trunc ' \
-                   'frexp ldexp modf modf__1 ' \
-                   'absolute negative remainder fmod mod'.split()
-
-    #: Dictionary mapping ufunc/attributes names to the units that they will
-    #: set on output. The value is interpreted as the power to which the unit
-    #: will be raised.
-    __prod_units = {'var': 2, 'prod': 'size', 'multiply': 'mul',
-                    'true_divide': 'div', 'divide': 'div', 'floor_divide': 'div',
-                    'remainder': 'div',
-                    'sqrt': .5, 'square': 2, 'reciprocal': -1}
-
-    __skip_other_args = 'ldexp multiply ' \
-                        'true_divide divide floor_divide fmod mod ' \
-                        'remainder'.split()
-
-    __handled = tuple(__same_units) + \
-                tuple(__require_units.keys()) + \
-                tuple(__prod_units.keys()) + \
-                tuple(__copy_units) + tuple(__skip_other_args)
-
-    def clip(self, first=None, second=None, out=None, **kwargs):
-        min = kwargs.get('min', first)
-        max = kwargs.get('max', second)
-
-        if min is None and max is None:
-            raise TypeError('clip() takes at least 3 arguments (2 given)')
-
-        if max is None and 'min' not in kwargs:
-            min, max = max, min
-
-        kwargs = {'out': out}
-
-        if min is not None:
-            if isinstance(min, self.__class__):
-                kwargs['min'] = min.to(self).magnitude
-            elif self.dimensionless:
-                kwargs['min'] = min
-            else:
-                raise DimensionalityError('dimensionless', self._units)
-
-        if max is not None:
-            if isinstance(max, self.__class__):
-                kwargs['max'] = max.to(self).magnitude
-            elif self.dimensionless:
-                kwargs['max'] = max
-            else:
-                raise DimensionalityError('dimensionless', self._units)
-
-        return self.__class__(self.magnitude.clip(**kwargs), self._units)
-
-    def fill(self, value):
-        self._units = value._units
-        return self.magnitude.fill(value.magnitude)
-
-    def put(self, indices, values, mode='raise'):
-        if isinstance(values, self.__class__):
-            values = values.to(self).magnitude
-        elif self.dimensionless:
-            values = self.__class__(values, '').to(self)
-        else:
-            raise DimensionalityError('dimensionless', self._units)
-        self.magnitude.put(indices, values, mode)
-
-    @property
-    def real(self):
-        return self.__class__(self._magnitude.real, self._units)
-
-    @property
-    def imag(self):
-        return self.__class__(self._magnitude.imag, self._units)
-
-    @property
-    def T(self):
-        return self.__class__(self._magnitude.T, self._units)
-
-    def searchsorted(self, v, side='left'):
-        if isinstance(v, self.__class__):
-            v = v.to(self).magnitude
-        elif self.dimensionless:
-            v = self.__class__(v, '').to(self)
-        else:
-            raise DimensionalityError('dimensionless', self._units)
-        return self.magnitude.searchsorted(v, side)
-
-    def __ito_if_needed(self, to_units):
-        if self.unitless and to_units == 'radian':
-            return
-
-        self.ito(to_units)
-
-    def __numpy_method_wrap(self, func, *args, **kwargs):
-        """Convenience method to wrap on the fly numpy method taking
-        care of the units.
-        """
-        if func.__name__ in self.__require_units:
-            self.__ito_if_needed(self.__require_units[func.__name__])
-
-        value = func(*args, **kwargs)
-
-        if func.__name__ in self.__copy_units:
-            return self.__class__(value, self._units)
-
-        if func.__name__ in self.__prod_units:
-            tmp = self.__prod_units[func.__name__]
-            if tmp == 'size':
-                return self.__class__(value, self._units ** self._magnitude.size)
-            return self.__class__(value, self._units ** tmp)
-
-        return value
-
-    def __len__(self):
-        return len(self._magnitude)
-
-    def __iter__(self):
-        # Allow exception to propagate in case of non-iterable magnitude
-        it_mag = iter(self.magnitude)
-        return iter((self.__class__(mag, self._units) for mag in it_mag))
-
-    def __getattr__(self, item):
-        # Attributes starting with `__array_` are common attributes of NumPy ndarray.
-        # They are requested by numpy functions.
-        if item.startswith('__array_'):
-            if isinstance(self._magnitude, ndarray):
-                return getattr(self._magnitude, item)
-            else:
-                # If an `__array_` attributes is requested but the magnitude is not an ndarray,
-                # we convert the magnitude to a numpy ndarray.
-                self._magnitude = _to_magnitude(self._magnitude, force_ndarray=True)
-                return getattr(self._magnitude, item)
-        elif item in self.__handled:
-            if not isinstance(self._magnitude, ndarray):
-                self._magnitude = _to_magnitude(self._magnitude, True)
-            attr = getattr(self._magnitude, item)
-            if callable(attr):
-                return functools.partial(self.__numpy_method_wrap, attr)
-            return attr
-        try:
-            return getattr(self._magnitude, item)
-        except AttributeError as ex:
-            raise AttributeError("Neither Quantity object nor its magnitude ({0}) "
-                                 "has attribute '{1}'".format(self._magnitude, item))
-
-    def __getitem__(self, key):
-        try:
-            value = self._magnitude[key]
-            return self.__class__(value, self._units)
-        except TypeError:
-            raise TypeError("Neither Quantity object nor its magnitude ({0})"
-                            "supports indexing".format(self._magnitude))
-
-    def __setitem__(self, key, value):
-        try:
-            if math.isnan(value):
-                self._magnitude[key] = value
-                return
-        except (TypeError, DimensionalityError):
-            pass
-
-        try:
-            if isinstance(value, self.__class__):
-                factor = self.__class__(value.magnitude, value._units / self._units).to_root_units()
-            else:
-                factor = self.__class__(value, self._units ** (-1)).to_root_units()
-
-            if isinstance(factor, self.__class__):
-                if not factor.dimensionless:
-                    raise DimensionalityError(value, self.units,
-                                              extra_msg='. Assign a quantity with the same dimensionality or '
-                                                        'access the magnitude directly as '
-                                                        '`obj.magnitude[%s] = %s`' % (key, value))
-                self._magnitude[key] = factor.magnitude
-            else:
-                self._magnitude[key] = factor
-
-        except TypeError:
-            raise TypeError("Neither Quantity object nor its magnitude ({0})"
-                            "supports indexing".format(self._magnitude))
-
-    def tolist(self):
-        units = self._units
-        return [self.__class__(value, units).tolist() if isinstance(value, list) else self.__class__(value, units)
-                for value in self._magnitude.tolist()]
-
-    __array_priority__ = 17
-
-    def __array_prepare__(self, obj, context=None):
-        # If this uf is handled by Pint, write it down in the handling dictionary.
-
-        # name of the ufunc, argument of the ufunc, domain of the ufunc
-        # In ufuncs with multiple outputs, domain indicates which output
-        # is currently being prepared (eg. see modf).
-        # In ufuncs with a single output, domain is 0
-        uf, objs, huh = context
-
-        if uf.__name__ in self.__handled and huh == 0:
-            # Only one ufunc should be handled at a time.
-            # If a ufunc is already being handled (and this is not another domain),
-            # something is wrong..
-            if self.__handling:
-                raise Exception('Cannot handled nested ufuncs.\n'
-                                'Current: {0}\n'
-                                'New: {1}'.format(context, self.__handling))
-            self.__handling = context
-
-        return obj
-
-    def __array_wrap__(self, obj, context=None):
-        uf, objs, huh = context
-
-        # if this ufunc is not handled by Pint, pass it to the magnitude.
-        if uf.__name__ not in self.__handled:
-            return self.magnitude.__array_wrap__(obj, context)
-
-        try:
-            ufname = uf.__name__ if huh == 0 else '{0}__{1}'.format(uf.__name__, huh)
-
-            # First, we check the units of the input arguments.
-
-            if huh == 0:
-                # Do this only when the wrap is called for the first ouput.
-
-                # Store the destination units
-                dst_units = None
-                # List of magnitudes of Quantities with the right units
-                # to be used as argument of the ufunc
-                mobjs = None
-
-                if uf.__name__ in self.__require_units:
-                    # ufuncs in __require_units
-                    # require specific units
-                    # This is more complex that it should be due to automatic
-                    # conversion between radians/dimensionless
-                    # TODO: maybe could be simplified using Contexts
-                    dst_units = self.__require_units[uf.__name__]
-                    if dst_units == 'radian':
-                        mobjs = []
-                        for other in objs:
-                            unt = getattr(other, '_units', '')
-                            if unt == 'radian':
-                                mobjs.append(getattr(other, 'magnitude', other))
-                            else:
-                                factor, units = self._REGISTRY._get_root_units(unt)
-                                if units and units != UnitsContainer({'radian': 1}):
-                                    raise DimensionalityError(units, dst_units)
-                                mobjs.append(getattr(other, 'magnitude', other) * factor)
-                        mobjs = tuple(mobjs)
-                    else:
-                        dst_units = self._REGISTRY.parse_expression(dst_units)._units
-
-                elif len(objs) > 1 and uf.__name__ not in self.__skip_other_args:
-                    # ufunc with multiple arguments require that all inputs have
-                    # the same arguments unless they are in __skip_other_args
-                    dst_units = objs[0]._units
-
-                # Do the conversion (if needed) and extract the magnitude for each input.
-                if mobjs is None:
-                    if dst_units is not None:
-                        mobjs = tuple(self._REGISTRY.convert(getattr(other, 'magnitude', other),
-                                                             getattr(other, 'units', ''),
-                                                             dst_units)
-                                      for other in objs)
-                    else:
-                        mobjs = tuple(getattr(other, 'magnitude', other)
-                                      for other in objs)
-
-                # call the ufunc
-                out = uf(*mobjs)
-
-                # If there are multiple outputs,
-                # store them in __handling (uf, objs, huh, out0, out1, ...)
-                # and return the first
-                if uf.nout > 1:
-                    self.__handling += out
-                    out = out[0]
-            else:
-                # If this is not the first output,
-                # just grab the result that was previously calculated.
-                out = self.__handling[3 + huh]
-
-            # Second, we set the units of the output value.
-            if ufname in self.__set_units:
-                try:
-                    out = self.__class__(out, self.__set_units[ufname])
-                except:
-                    raise _Exception(ValueError)
-            elif ufname in self.__copy_units:
-                try:
-                    out = self.__class__(out, self._units)
-                except:
-                    raise _Exception(ValueError)
-            elif ufname in self.__prod_units:
-                tmp = self.__prod_units[ufname]
-                if tmp == 'size':
-                    out = self.__class__(out, self._units ** self._magnitude.size)
-                elif tmp == 'div':
-                    units1 = objs[0]._units if isinstance(objs[0], self.__class__) else UnitsContainer()
-                    units2 = objs[1]._units if isinstance(objs[1], self.__class__) else UnitsContainer()
-                    out = self.__class__(out, units1 / units2)
-                elif tmp == 'mul':
-                    units1 = objs[0]._units if isinstance(objs[0], self.__class__) else UnitsContainer()
-                    units2 = objs[1]._units if isinstance(objs[1], self.__class__) else UnitsContainer()
-                    out = self.__class__(out, units1 * units2)
-                else:
-                    out = self.__class__(out, self._units ** tmp)
-
-            return out
-        except (DimensionalityError, UndefinedUnitError) as ex:
-            raise ex
-        except _Exception as ex:
-            raise ex.internal
-        except Exception as ex:
-            print(ex)
-        finally:
-            # If this is the last output argument for the ufunc,
-            # we are done handling this ufunc.
-            if uf.nout == huh + 1:
-                self.__handling = None
-
-        return self.magnitude.__array_wrap__(obj, context)
-
-    # Measurement support
-    def plus_minus(self, error, relative=False):
-        if isinstance(error, self.__class__):
-            if relative:
-                raise ValueError('{} is not a valid relative error.'.format(error))
-            error = error.to(self._units).magnitude
-        else:
-            if relative:
-                error = error * abs(self.magnitude)
-
-        return self._REGISTRY.Measurement(copy.copy(self.magnitude), error, self._units)
-
-    # methods/properties that help for math operations with offset units
-    @property
-    def _is_multiplicative(self):
-        """Check if the Quantity object has only multiplicative units.
-        """
-        return not self._get_non_multiplicative_units()
-
-    def _get_non_multiplicative_units(self):
-        """Return a list of the of non-multiplicative units of the Quantity object
-        """
-        offset_units = [unit for unit in self._units.keys()
-                        if not self._REGISTRY._units[unit].is_multiplicative]
-        return offset_units
-
-    def _get_delta_units(self):
-        """Return list of delta units ot the Quantity object
-        """
-        delta_units = [u for u in self._units.keys() if u.startswith("delta_")]
-        return delta_units
-
-    def _has_compatible_delta(self, unit):
-        """"Check if Quantity object has a delta_unit that is compatible with unit
-        """
-        deltas = self._get_delta_units()
-        if 'delta_' + unit in deltas:
-            return True
-        else:  # Look for delta units with same dimension as the offset unit
-            offset_unit_dim = self._REGISTRY._units[unit].reference
-            for d in deltas:
-                if self._REGISTRY._units[d].reference == offset_unit_dim:
-                    return True
-        return False
-
-    def _ok_for_muldiv(self, no_offset_units=None):
-        """Checks if Quantity object can be multiplied or divided
-
-        :q: quantity object that is checked
-        :no_offset_units: number of offset units in q
-        """
-        is_ok = True
-        if no_offset_units is None:
-            no_offset_units = len(self._get_non_multiplicative_units())
-        if no_offset_units > 1:
-            is_ok = False
-        if no_offset_units == 1:
-            if len(self._units) > 1:
-                is_ok = False
-            if (len(self._units) == 1
-                    and not self._REGISTRY.autoconvert_offset_to_baseunit):
-                is_ok = False
-            if next(iter(self._units.values())) != 1:
-                is_ok = False
-        return is_ok
diff --git a/lib/taurus/external/pint/pint_local/systems.py b/lib/taurus/external/pint/pint_local/systems.py
deleted file mode 100644
index 164d089..0000000
--- a/lib/taurus/external/pint/pint_local/systems.py
+++ /dev/null
@@ -1,423 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    pint.systems
-    ~~~~~~~~~~~~
-
-    Functions and classes related to system definitions and conversions.
-
-    :copyright: 2013 by Pint Authors, see AUTHORS for more details.
-    :license: BSD, see LICENSE for more details.
-"""
-
-from __future__ import division, unicode_literals, print_function, absolute_import
-
-import re
-
-from .unit import Definition, UnitDefinition, DefinitionSyntaxError
-from .util import to_units_container, UnitsContainer
-
-
-class Group(object):
-    """A group is a list of units.
-
-    Units can be added directly or by including other groups.
-
-    Members are computed dynamically, that is if a unit is added to a group X
-    all groups that include X are affected.
-    """
-
-    #: Regex to match the header parts of a context.
-    _header_re = re.compile('@group\s+(?P<name>\w+)\s*(using\s(?P<used_groups>.*))*')
-
-    def __init__(self, name, groups_systems):
-        """
-        :param name: Name of the group
-        :type name: str
-        :param groups_systems: dictionary containing groups and system.
-                               The newly created group will be added after creation.
-        :type groups_systems: dict[str, Group | System]
-        """
-
-        if name in groups_systems:
-            t = 'group' if isinstance(groups_systems['name'], Group) else 'system'
-            raise ValueError('The system name already in use by a %s' % t)
-
-        # The name of the group.
-        #: type: str
-        self.name = name
-
-        #: Names of the units in this group.
-        #: :type: set[str]
-        self._unit_names = set()
-
-        #: Names of the groups in this group.
-        #: :type: set[str]
-        self._used_groups = set()
-
-        #: Names of the groups in which this group is contained.
-        #: :type: set[str]
-        self._used_by = set()
-
-        #: Maps group name to Group.
-        #: :type: dict[str, Group]
-        self._groups_systems = groups_systems
-
-        self._groups_systems[self.name] = self
-
-        if name != 'root':
-            # All groups are added to root group
-            groups_systems['root'].add_groups(name)
-
-        #: A cache of the included units.
-        #: None indicates that the cache has been invalidated.
-        #: :type: frozenset[str] | None
-        self._computed_members = None
-
-    @property
-    def members(self):
-        """Names of the units that are members of the group.
-
-        Calculated to include to all units in all included _used_groups.
-
-        :rtype: frozenset[str]
-        """
-        if self._computed_members is None:
-            self._computed_members = set(self._unit_names)
-
-            for _, group in self.iter_used_groups():
-                self._computed_members |= group.members
-
-            self._computed_members = frozenset(self._computed_members)
-
-        return self._computed_members
-
-    def invalidate_members(self):
-        """Invalidate computed members in this Group and all parent nodes.
-        """
-        self._computed_members = None
-        d = self._groups_systems
-        for name in self._used_by:
-            d[name].invalidate_members()
-
-    def iter_used_groups(self):
-        pending = set(self._used_groups)
-        d = self._groups_systems
-        while pending:
-            name = pending.pop()
-            group = d[name]
-            pending |= group._used_groups
-            yield name, d[name]
-
-    def is_used_group(self, group_name):
-        for name, _ in self.iter_used_groups():
-            if name == group_name:
-                return True
-        return False
-
-    def add_units(self, *unit_names):
-        """Add units to group.
-
-        :type unit_names: str
-        """
-        for unit_name in unit_names:
-            self._unit_names.add(unit_name)
-
-        self.invalidate_members()
-
-    def remove_units(self, *unit_names):
-        """Remove units from group.
-
-        :type unit_names: str
-        """
-        for unit_name in unit_names:
-            self._unit_names.remove(unit_name)
-
-        self.invalidate_members()
-
-    def add_groups(self, *group_names):
-        """Add groups to group.
-
-        :type group_names: str
-        """
-        d = self._groups_systems
-        for group_name in group_names:
-
-            grp = d[group_name]
-
-            if grp.is_used_group(self.name):
-                raise ValueError('Cyclic relationship found between %s and %s' % (self.name, group_name))
-
-            self._used_groups.add(group_name)
-            grp._used_by.add(self.name)
-
-        self.invalidate_members()
-
-    def remove_groups(self, *group_names):
-        """Remove groups from group.
-
-        :type group_names: str
-        """
-        d = self._groups_systems
-        for group_name in group_names:
-            grp = d[group_name]
-
-            self._used_groups.remove(group_name)
-            grp._used_by.remove(self.name)
-
-
-        self.invalidate_members()
-
-    @classmethod
-    def from_lines(cls, lines, define_func, group_dict):
-        """Return a Group object parsing an iterable of lines.
-
-        :param lines: iterable
-        :type lines: list[str]
-        :param define_func: Function to define a unit in the registry.
-        :type define_func: str -> None
-        :param group_dict: Maps group name to Group.
-        :type group_dict: dict[str, Group]
-        """
-        header, lines = lines[0], lines[1:]
-
-        r = cls._header_re.search(header)
-        name = r.groupdict()['name'].strip()
-        groups = r.groupdict()['used_groups']
-        if groups:
-            group_names = tuple(a.strip() for a in groups.split(','))
-        else:
-            group_names = ()
-
-        unit_names = []
-        for line in lines:
-            if '=' in line:
-                # Is a definition
-                definition = Definition.from_string(line)
-                if not isinstance(definition, UnitDefinition):
-                    raise DefinitionSyntaxError('Only UnitDefinition are valid inside _used_groups, '
-                                                'not %s' % type(definition))
-                define_func(definition)
-                unit_names.append(definition.name)
-            else:
-                unit_names.append(line.strip())
-
-        grp = cls(name, group_dict)
-
-        grp.add_units(*unit_names)
-
-        if group_names:
-            grp.add_groups(*group_names)
-
-        return grp
-
-
-class System(object):
-    """A system is a Group plus a set of base units.
-
-    @system <name> [using <group 1>, ..., <group N>]
-        <rule 1>
-        ...
-        <rule N>
-    @end
-
-    """
-
-    #: Regex to match the header parts of a context.
-    _header_re = re.compile('@system\s+(?P<name>\w+)\s*(using\s(?P<used_groups>.*))*')
-
-    def __init__(self, name, groups_systems):
-        """
-        :param name: Name of the group
-        :type name: str
-        :param groups_systems: dictionary containing groups and system.
-                               The newly created group will be added after creation.
-        :type groups_systems: dict[str, Group | System]
-        """
-
-        if name in groups_systems:
-            t = 'group' if isinstance(groups_systems[name], Group) else 'system'
-            raise ValueError('The system name (%s) already in use by a %s' % (name, t))
-
-        #: Name of the system
-        #: :type: str
-        self.name = name
-
-        #: Maps root unit names to a dict indicating the new unit and its exponent.
-        #: :type: dict[str, dict[str, number]]]
-        self.base_units = {}
-
-        #: Derived unit names.
-        #: :type: set(str)
-        self.derived_units = set()
-
-        #: Names of the _used_groups in used by this system.
-        #: :type: set(str)
-        self._used_groups = set()
-
-        #: :type: frozenset | None
-        self._computed_members = None
-
-        #: Maps group name to Group.
-        self._group_systems_dict = groups_systems
-
-        self._group_systems_dict[self.name] = self
-
-    @property
-    def members(self):
-        if self._computed_members is None:
-            self._computed_members = set()
-
-            for group_name in self._used_groups:
-                self._computed_members |= self._group_systems_dict[group_name].members
-
-            self._computed_members = frozenset(self._computed_members)
-
-        return self._computed_members
-
-    def invalidate_members(self):
-        """Invalidate computed members in this Group and all parent nodes.
-        """
-        self._computed_members = None
-
-    def add_groups(self, *group_names):
-        """Add groups to group.
-
-        :type group_names: str
-        """
-        self._used_groups |= set(group_names)
-
-        self.invalidate_members()
-
-    def remove_groups(self, *group_names):
-        """Remove groups from group.
-
-        :type group_names: str
-        """
-        self._used_groups -= set(group_names)
-
-        self.invalidate_members()
-
-    @classmethod
-    def from_lines(cls, lines, get_root_func, group_dict):
-        header, lines = lines[0], lines[1:]
-
-        r = cls._header_re.search(header)
-        name = r.groupdict()['name'].strip()
-        groups = r.groupdict()['used_groups']
-
-        # If the systems has no group, it automatically uses the root group.
-        if groups:
-            group_names = tuple(a.strip() for a in groups.split(','))
-        else:
-            group_names = ('root', )
-
-        base_unit_names = {}
-        derived_unit_names = []
-        for line in lines:
-            line = line.strip()
-
-            # We would identify a
-            #  - old_unit: a root unit part which is going to be removed from the system.
-            #  - new_unit: a non root unit which is going to replace the old_unit.
-
-            if ':' in line:
-                # The syntax is new_unit:old_unit
-
-                new_unit, old_unit = line.split(':')
-                new_unit, old_unit = new_unit.strip(), old_unit.strip()
-
-                # The old unit MUST be a root unit, if not raise an error.
-                if old_unit != str(get_root_func(old_unit)[1]):
-                    raise ValueError('In `%s`, the unit at the right of the `:` must be a root unit.' % line)
-
-                # Here we find new_unit expanded in terms of root_units
-                new_unit_expanded = to_units_container(get_root_func(new_unit)[1])
-
-                # We require that the old unit is present in the new_unit expanded
-                if old_unit not in new_unit_expanded:
-                    raise ValueError('Old unit must be a component of new unit')
-
-                # Here we invert the equation, in other words
-                # we write old units in terms new unit and expansion
-                new_unit_dict = dict((new_unit, -1./value)
-                                     for new_unit, value in new_unit_expanded.items()
-                                     if new_unit != old_unit)
-                new_unit_dict[new_unit] = 1 / new_unit_expanded[old_unit]
-
-                base_unit_names[old_unit] = new_unit_dict
-
-            else:
-                # The syntax is new_unit
-                # old_unit is inferred as the root unit with the same dimensionality.
-
-                new_unit = line
-                old_unit_dict = to_units_container(get_root_func(line)[1])
-
-                if len(old_unit_dict) != 1:
-                    raise ValueError('The new base must be a root dimension if not discarded unit is specified.')
-
-                old_unit, value = dict(old_unit_dict).popitem()
-
-                base_unit_names[old_unit] = {new_unit: 1./value}
-
-        system = cls(name, group_dict)
-
-        system.add_groups(*group_names)
-
-        system.base_units.update(**base_unit_names)
-        system.derived_units |= set(derived_unit_names)
-
-        return system
-
-
-class GSManager(object):
-
-    def __init__(self):
-        #: :type: dict[str, Group | System]
-        self._groups_systems = dict()
-        self._root_group = Group('root', self._groups_systems)
-
-    def add_system_from_lines(self, lines, get_root_func):
-        System.from_lines(lines, get_root_func, self._groups_systems)
-
-    def add_group_from_lines(self, lines, define_func):
-        Group.from_lines(lines, define_func, self._groups_systems)
-
-    def get_group(self, name, create_if_needed=True):
-        """Return a Group.
-
-        :param name: Name of the group.
-        :param create_if_needed: Create a group if not Found. If False, raise an Exception.
-        :return: Group
-        """
-        try:
-            return self._groups_systems[name]
-        except KeyError:
-            if create_if_needed:
-                if name == 'root':
-                    raise ValueError('The name root is reserved.')
-                return Group(name, self._groups_systems)
-            else:
-                raise KeyError('No group %s found.' % name)
-
-    def get_system(self, name, create_if_needed=True):
-        """Return a Group.
-
-        :param name: Name of the system
-        :param create_if_needed: Create a group if not Found. If False, raise an Exception.
-        :return: System
-        """
-
-        try:
-            return self._groups_systems[name]
-        except KeyError:
-            if create_if_needed:
-                return System(name, self._groups_systems)
-            else:
-                raise KeyError('No system found named %s.' % name)
-
-    def __getitem__(self, item):
-        if item in self._groups_systems:
-            return self._groups_systems[item]
-
-        raise KeyError('No group or system found named %s.' % item)
diff --git a/lib/taurus/external/pint/pint_local/unit.py b/lib/taurus/external/pint/pint_local/unit.py
deleted file mode 100644
index bbf9dfb..0000000
--- a/lib/taurus/external/pint/pint_local/unit.py
+++ /dev/null
@@ -1,1375 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    pint.unit
-    ~~~~~~~~~
-
-    Functions and classes related to unit definitions and conversions.
-
-    :copyright: 2013 by Pint Authors, see AUTHORS for more details.
-    :license: BSD, see LICENSE for more details.
-"""
-
-from __future__ import division, unicode_literals, print_function, absolute_import
-
-import os
-import math
-import itertools
-import functools
-import operator
-import pkg_resources
-from decimal import Decimal
-from contextlib import contextmanager, closing
-from io import open, StringIO
-from collections import defaultdict
-from tokenize import untokenize, NUMBER, STRING, NAME, OP
-from numbers import Number
-
-from .context import Context, ContextChain
-from .util import (logger, pi_theorem, solve_dependencies, ParserHelper,
-                   string_preprocessor, find_connected_nodes,
-                   find_shortest_path, UnitsContainer, _is_dim,
-                   SharedRegistryObject, to_units_container)
-from .compat import tokenizer, string_types, NUMERIC_TYPES, long_type, zip_longest
-from .definitions import (Definition, UnitDefinition, PrefixDefinition,
-                          DimensionDefinition)
-from .converters import ScaleConverter
-from .errors import (DimensionalityError, UndefinedUnitError,
-                     DefinitionSyntaxError, RedefinitionError)
-
-from .pint_eval import build_eval_tree
-from . import systems
-
-
-def _capture_till_end(ifile):
-    context = []
-    for no, line in ifile:
-        line = line.strip()
-        if line.startswith('@end'):
-            break
-        elif line.startswith('@'):
-            raise DefinitionSyntaxError('cannot nest @ directives', lineno=no)
-        context.append(line)
-    return context
-
-
-class _Unit(SharedRegistryObject):
-    """Implements a class to describe a unit supporting math operations.
-
-    :type units: UnitsContainer, str, Unit or Quantity.
-
-    """
-
-    #: Default formatting string.
-    default_format = ''
-
-    def __reduce__(self):
-        from . import _build_unit
-        return _build_unit, (self._units)
-
-    def __new__(cls, units):
-        inst = object.__new__(cls)
-        if isinstance(units, (UnitsContainer, UnitDefinition)):
-            inst._units = units
-        elif isinstance(units, string_types):
-            inst._units = inst._REGISTRY.parse_units(units)._units
-        elif isinstance(units, _Unit):
-            inst._units = units._units
-        else:
-            raise TypeError('units must be of type str, Unit or '
-                            'UnitsContainer; not {0}.'.format(type(units)))
-
-        inst.__used = False
-        inst.__handling = None
-        return inst
-
-    @property
-    def debug_used(self):
-        return self.__used
-
-    def __copy__(self):
-        ret = self.__class__(self._units)
-        ret.__used = self.__used
-        return ret
-
-    def __str__(self):
-        return format(self)
-
-    def __repr__(self):
-        return "<Unit('{0}')>".format(self._units)
-
-    def __format__(self, spec):
-        spec = spec or self.default_format
-
-        if '~' in spec:
-            if self.dimensionless:
-                return ''
-            units = UnitsContainer(dict((self._REGISTRY._get_symbol(key),
-                                         value)
-                                   for key, value in self._units.items()))
-            spec = spec.replace('~', '')
-        else:
-            units = self._units
-
-        return '%s' % (format(units, spec))
-
-    # IPython related code
-    def _repr_html_(self):
-        return self.__format__('H')
-
-    def _repr_latex_(self):
-        return "$" + self.__format__('L') + "$"
-
-    @property
-    def dimensionless(self):
-        """Return true if the Unit is dimensionless.
-
-        """
-        return not bool(self.dimensionality)
-
-    @property
-    def dimensionality(self):
-        """Unit's dimensionality (e.g. {length: 1, time: -1})
-
-        """
-        try:
-            return self._dimensionality
-        except AttributeError:
-            dim = self._REGISTRY._get_dimensionality(self._units)
-            self._dimensionality = dim
-
-        return self._dimensionality
-
-    def compatible_units(self, *contexts):
-        if contexts:
-            with self._REGISTRY.context(*contexts):
-                return self._REGISTRY.get_compatible_units(self)
-
-        return self._REGISTRY.get_compatible_units(self)
-
-    def __mul__(self, other):
-        if self._check(other):
-            if isinstance(other, self.__class__):
-                return self.__class__(self._units*other._units)
-            else:
-                return self._REGISTRY.Quantity(other._magnitude,
-                                               self._units*other._units)
-
-        return self._REGISTRY.Quantity(other, self._units)
-
-    __rmul__ = __mul__
-
-    def __truediv__(self, other):
-        if self._check(other):
-            if isinstance(other, self.__class__):
-                return self.__class__(self._units/other._units)
-            else:
-                return self._REGISTRY.Quantity(1/other._magnitude,
-                                           self._units/other._units)
-
-        return self._REGISTRY.Quantity(1/other, self._units)
-
-    def __rtruediv__(self, other):
-        # As Unit and Quantity both handle truediv with each other rtruediv can
-        # only be called for something different.
-        if isinstance(other, NUMERIC_TYPES):
-            return self._REGISTRY.Quantity(other, 1/self._units)
-        elif isinstance(other, UnitsContainer):
-            return self.__class__(other/self._units)
-        else:
-            return NotImplemented
-
-    __div__ = __truediv__
-    __rdiv__ = __rtruediv__
-
-    def __pow__(self, other):
-        if isinstance(other, NUMERIC_TYPES):
-            return self.__class__(self._units**other)
-
-        else:
-            mess = 'Cannot power Unit by {}'.format(type(other))
-            raise TypeError(mess)
-
-    def __hash__(self):
-        return self._units.__hash__()
-
-    def __eq__(self, other):
-        # We compare to the base class of Unit because each Unit class is
-        # unique.
-        if self._check(other):
-            if isinstance(other, self.__class__):
-                return self._units == other._units
-            else:
-                return other == self._REGISTRY.Quantity(1, self._units)
-
-        elif isinstance(other, NUMERIC_TYPES):
-            return other == self._REGISTRY.Quantity(1, self._units)
-
-        else:
-            return self._units == other
-
-    def compare(self, other, op):
-        self_q = self._REGISTRY.Quantity(1, self)
-
-        if isinstance(other, NUMERIC_TYPES):
-            return self_q.compare(other, op)
-        elif isinstance(other, (_Unit, UnitsContainer, dict)):
-            return self_q.compare(self._REGISTRY.Quantity(1, other), op)
-        else:
-            return NotImplemented
-
-    __lt__ = lambda self, other: self.compare(other, op=operator.lt)
-    __le__ = lambda self, other: self.compare(other, op=operator.le)
-    __ge__ = lambda self, other: self.compare(other, op=operator.ge)
-    __gt__ = lambda self, other: self.compare(other, op=operator.gt)
-
-    def __int__(self):
-        return int(self._REGISTRY.Quantity(1, self._units))
-
-    def __long__(self):
-        return long_type(self._REGISTRY.Quantity(1, self._units))
-
-    def __float__(self):
-        return float(self._REGISTRY.Quantity(1, self._units))
-
-    def __complex__(self):
-        return complex(self._REGISTRY.Quantity(1, self._units))
-
-    __array_priority__ = 17
-
-    def __array_prepare__(self, array, context=None):
-        return 1
-
-    def __array_wrap__(self, array, context=None):
-        uf, objs, huh = context
-
-        if uf.__name__ in ('true_divide', 'divide', 'floor_divide'):
-            return self._REGISTRY.Quantity(array, 1/self._units)
-        elif uf.__name__ in ('multiply',):
-            return self._REGISTRY.Quantity(array, self._units)
-        else:
-            raise ValueError('Unsupproted operation for Unit')
-
-
-class UnitRegistry(object):
-    """The unit registry stores the definitions and relationships between
-    units.
-
-    :param filename: path of the units definition file to load.
-                     Empty to load the default definition file.
-                     None to leave the UnitRegistry empty.
-    :param force_ndarray: convert any input, scalar or not to a numpy.ndarray.
-    :param default_as_delta: In the context of a multiplication of units, interpret
-                             non-multiplicative units as their *delta* counterparts.
-    :autoconvert_offset_to_baseunit: If True converts offset units in quantites are
-                                     converted to their base units in multiplicative
-                                     context. If False no conversion happens.
-    :param on_redefinition: action to take in case a unit is redefined.
-                            'warn', 'raise', 'ignore'
-    :type on_redefintion: str
-    """
-
-    def __init__(self, filename='', force_ndarray=False, default_as_delta=True,
-                 autoconvert_offset_to_baseunit=False,
-                 on_redefinition='warn', system=None):
-        self.Unit = build_unit_class(self)
-        self.Quantity = build_quantity_class(self, force_ndarray)
-        self.Measurement = build_measurement_class(self, force_ndarray)
-
-        #: Action to take in case a unit is redefined. 'warn', 'raise', 'ignore'
-        self._on_redefinition = on_redefinition
-
-        #: Map dimension name (string) to its definition (DimensionDefinition).
-        self._dimensions = {}
-
-        #: :type: systems.GSManager
-        self._gsmanager = systems.GSManager()
-
-        #: Map unit name (string) to its definition (UnitDefinition).
-        #: Might contain prefixed units.
-        self._units = {}
-
-        #: Map unit name in lower case (string) to a set of unit names with the right case.
-        #: Does not contain prefixed units.
-        #: e.g: 'hz' - > set('Hz', )
-        self._units_casei = defaultdict(set)
-
-        #: Map prefix name (string) to its definition (PrefixDefinition).
-        self._prefixes = {'': PrefixDefinition('', '', (), 1)}
-
-        #: Map suffix name (string) to canonical , and unit alias to canonical unit name
-        self._suffixes = {'': None, 's': ''}
-
-        #: Map context name (string) or abbreviation to context.
-        self._contexts = {}
-
-        #: Stores active contexts.
-        self._active_ctx = ContextChain()
-
-        #: Maps dimensionality (UnitsContainer) to Units (str)
-        self._dimensional_equivalents = dict()
-
-        #: Maps dimensionality (UnitsContainer) to Dimensionality (UnitsContainer)
-        self._root_units_cache = dict()
-
-        #: Maps dimensionality (UnitsContainer) to Dimensionality (UnitsContainer)
-        self._base_units_cache = dict()
-
-        #: Maps dimensionality (UnitsContainer) to Units (UnitsContainer)
-        self._dimensionality_cache = dict()
-
-        #: Cache the unit name associated to user input. ('mV' -> 'millivolt')
-        self._parse_unit_cache = dict()
-
-        #: When performing a multiplication of units, interpret
-        #: non-multiplicative units as their *delta* counterparts.
-        self.default_as_delta = default_as_delta
-
-        #: System name to be used by default.
-        self._default_system_name = None
-
-        # Determines if quantities with offset units are converted to their
-        # base units on multiplication and division.
-        self.autoconvert_offset_to_baseunit = autoconvert_offset_to_baseunit
-
-        if filename == '':
-            self.load_definitions('default_en.txt', True)
-        elif filename is not None:
-            self.load_definitions(filename)
-
-        self.define(UnitDefinition('pi', 'π', (), ScaleConverter(math.pi)))
-
-        self._build_cache()
-
-        self.set_default_system(system)
-
-    def __name__(self):
-        return 'UnitRegistry'
-
-    def __getattr__(self, item):
-        return self.Unit(item)
-
-    def __getitem__(self, item):
-        logger.warning('Calling the getitem method from a UnitRegistry is deprecated. '
-                       'use `parse_expression` method or use the registry as a callable.')
-        return self.parse_expression(item)
-
-    def __dir__(self):
-        return list(self._units.keys()) + \
-            ['define', 'load_definitions', 'get_name', 'get_symbol',
-             'get_dimensionality', 'Quantity', 'wraps',
-             'parse_units', 'parse_expression', 'pi_theorem',
-             'convert', 'get_base_units']
-
-    @property
-    def default_format(self):
-        """Default formatting string for quantities.
-        """
-        return self.Quantity.default_format
-
-    @default_format.setter
-    def default_format(self, value):
-        self.Unit.default_format = value
-        self.Quantity.default_format = value
-
-    def get_group(self, name, create_if_needed=True):
-        """Return a Group.
-
-        :param name: Name of the group to be
-        :param create_if_needed: Create a group if not Found. If False, raise an Exception.
-        :return: Group
-        """
-        return self._gsmanager.get_group(name, create_if_needed)
-
-    def get_system(self, name, create_if_needed=True):
-        """Return a Group.
-
-        :param registry:
-        :param name: Name of the group to be
-        :param create_if_needed: Create a group if not Found. If False, raise an Exception.
-        :return: System
-        """
-        return self._gsmanager.get_system(name, create_if_needed)
-
-    def set_default_system(self, name):
-        # Test if exists
-        if name:
-            system = self._gsmanager.get_system(name, False)
-            self._default_system_name = name
-            self._base_units_cache = {}
-
-    def add_context(self, context):
-        """Add a context object to the registry.
-
-        The context will be accessible by its name and aliases.
-
-        Notice that this method will NOT enable the context. Use `enable_contexts`.
-        """
-        if context.name in self._contexts:
-            logger.warning('The name %s was already registered for another context.',
-                           context.name)
-        self._contexts[context.name] = context
-        for alias in context.aliases:
-            if alias in self._contexts:
-                logger.warning('The name %s was already registered for another context',
-                               context.name)
-            self._contexts[alias] = context
-
-    def remove_context(self, name_or_alias):
-        """Remove a context from the registry and return it.
-
-        Notice that this methods will not disable the context. Use `disable_contexts`.
-        """
-        context = self._contexts[name_or_alias]
-
-        del self._contexts[context.name]
-        for alias in context.aliases:
-            del self._contexts[alias]
-
-        return context
-
-    def enable_contexts(self, *names_or_contexts, **kwargs):
-        """Enable contexts provided by name or by object.
-
-        :param names_or_contexts: sequence of the contexts or contexts names/alias
-        :param kwargs: keyword arguments for the context
-        """
-
-        # If present, copy the defaults from the containing contexts
-        if self._active_ctx.defaults:
-            kwargs = dict(self._active_ctx.defaults, **kwargs)
-
-        # For each name, we first find the corresponding context
-        ctxs = tuple((self._contexts[name] if isinstance(name, string_types) else name)
-                     for name in names_or_contexts)
-
-        # Check if the contexts have been checked first, if not we make sure
-        # that dimensions are expressed in terms of base dimensions.
-        for ctx in ctxs:
-            if getattr(ctx, '_checked', False):
-                continue
-            for (src, dst), func in ctx.funcs.items():
-                src_ = self._get_dimensionality(src)
-                dst_ = self._get_dimensionality(dst)
-                if src != src_ or dst != dst_:
-                    ctx.remove_transformation(src, dst)
-                    ctx.add_transformation(src_, dst_, func)
-            ctx._checked = True
-
-        # and create a new one with the new defaults.
-        ctxs = tuple(Context.from_context(ctx, **kwargs)
-                     for ctx in ctxs)
-
-        # Finally we add them to the active context.
-        self._active_ctx.insert_contexts(*ctxs)
-
-    def disable_contexts(self, n=None):
-        """Disable the last n enabled contexts.
-        """
-        if n is None:
-            n = len(self._contexts)
-        self._active_ctx.remove_contexts(n)
-
-    @contextmanager
-    def context(self, *names, **kwargs):
-        """Used as a context manager, this function enables to activate a context
-        which is removed after usage.
-
-        :param names: name of the context.
-        :param kwargs: keyword arguments for the contexts.
-
-        Context are called by their name::
-
-            >>> with ureg.context('one'):
-            ...     pass
-
-        If the context has an argument, you can specify its value as a keyword
-        argument::
-
-            >>> with ureg.context('one', n=1):
-            ...     pass
-
-        Multiple contexts can be entered in single call:
-
-            >>> with ureg.context('one', 'two', n=1):
-            ...     pass
-
-        or nested allowing you to give different values to the same keyword argument::
-
-            >>> with ureg.context('one', n=1):
-            ...     with ureg.context('two', n=2):
-            ...         pass
-
-        A nested context inherits the defaults from the containing context::
-
-            >>> with ureg.context('one', n=1):
-            ...     with ureg.context('two'): # Here n takes the value of the upper context
-            ...         pass
-
-        """
-
-        # Enable the contexts.
-        self.enable_contexts(*names, **kwargs)
-
-        try:
-            # After adding the context and rebuilding the graph, the registry
-            # is ready to use.
-            yield self
-        finally:
-            # Upon leaving the with statement,
-            # the added contexts are removed from the active one.
-            self.disable_contexts(len(names))
-
-    def define(self, definition):
-        """Add unit to the registry.
-        """
-        if isinstance(definition, string_types):
-            definition = Definition.from_string(definition)
-
-        if isinstance(definition, DimensionDefinition):
-            d, di = self._dimensions, None
-        elif isinstance(definition, UnitDefinition):
-            d, di = self._units, self._units_casei
-            if definition.is_base:
-                for dimension in definition.reference.keys():
-                    if dimension in self._dimensions:
-                        if dimension != '[]':
-                            raise DefinitionSyntaxError('only one unit per dimension can be a base unit.')
-                        continue
-
-                    self.define(DimensionDefinition(dimension, '', (), None, is_base=True))
-
-        elif isinstance(definition, PrefixDefinition):
-            d, di = self._prefixes, None
-        else:
-            raise TypeError('{0} is not a valid definition.'.format(definition))
-
-        def _adder(key, value, action=self._on_redefinition, selected_dict=d, casei_dict=di):
-            if key in selected_dict:
-                if action == 'raise':
-                    raise RedefinitionError(key, type(value))
-                elif action == 'warn':
-                    logger.warning("Redefining '%s' (%s)", key, type(value))
-
-            selected_dict[key] = value
-            if casei_dict is not None:
-                casei_dict[key.lower()].add(key)
-
-        _adder(definition.name, definition)
-
-        if definition.has_symbol:
-            _adder(definition.symbol, definition)
-
-        for alias in definition.aliases:
-            if ' ' in alias:
-                logger.warn('Alias cannot contain a space: ' + alias)
-
-            _adder(alias, definition)
-
-        # define additional "delta_" units for units with an offset
-        if getattr(definition.converter, "offset", 0.0) != 0.0:
-            d_name = 'delta_' + definition.name
-            if definition.symbol:
-                d_symbol = 'Δ' + definition.symbol
-            else:
-                d_symbol = None
-            d_aliases = tuple('Δ' + alias for alias in definition.aliases)
-
-            def prep(_name):
-                if _name.startswith('['):
-                    return '[delta_' + _name[1:]
-                return 'delta_' + _name
-
-            d_reference = UnitsContainer(dict((ref, value)
-                                         for ref, value in definition.reference.items()))
-
-            self.define(UnitDefinition(d_name, d_symbol, d_aliases,
-                                       ScaleConverter(definition.converter.scale),
-                                       d_reference, definition.is_base))
-
-    def load_definitions(self, file, is_resource=False):
-        """Add units and prefixes defined in a definition text file.
-        """
-        # Permit both filenames and line-iterables
-        if isinstance(file, string_types):
-            try:
-                if is_resource:
-                    with closing(pkg_resources.resource_stream(__name__, file)) as fp:
-                        rbytes = fp.read()
-                    return self.load_definitions(StringIO(rbytes.decode('utf-8')), is_resource)
-                else:
-                    with open(file, encoding='utf-8') as fp:
-                        return self.load_definitions(fp, is_resource)
-            except (RedefinitionError, DefinitionSyntaxError) as e:
-                if e.filename is None:
-                    e.filename = file
-                raise e
-            except Exception as e:
-                msg = getattr(e, 'message', '') or str(e)
-                raise ValueError('While opening {0}\n{1}'.format(file, msg))
-
-        ifile = enumerate(file, 1)
-        for no, line in ifile:
-            line = line.strip()
-            if not line or line.startswith('#'):
-                continue
-            if line.startswith('@import'):
-                if is_resource:
-                    path = line[7:].strip()
-                else:
-                    try:
-                        path = os.path.dirname(file.name)
-                    except AttributeError:
-                        path = os.getcwd()
-                    path = os.path.join(path, os.path.normpath(line[7:].strip()))
-                self.load_definitions(path, is_resource)
-            elif line.startswith('@context'):
-                context = [line, ] + _capture_till_end(ifile)
-                try:
-                    self.add_context(Context.from_lines(context, self.get_dimensionality))
-                except KeyError as e:
-                    raise DefinitionSyntaxError('unknown dimension {0} in context'.format(str(e)), lineno=no)
-            elif line.startswith('@system'):
-                context = [line, ] + _capture_till_end(ifile)
-                try:
-                    self._gsmanager.add_system_from_lines(context, self.get_root_units)
-                except KeyError as e:
-                    raise DefinitionSyntaxError('unknown dimension {0} in context'.format(str(e)), lineno=no)
-            elif line.startswith('@group'):
-                context = [line, ] + _capture_till_end(ifile)
-                try:
-                    self._gsmanager.add_group_from_lines(context, self.define)
-                except KeyError as e:
-                    raise DefinitionSyntaxError('unknown dimension {0} in context'.format(str(e)), lineno=no)
-            else:
-                try:
-                    self.define(Definition.from_string(line))
-                except (RedefinitionError, DefinitionSyntaxError) as ex:
-                    if ex.lineno is None:
-                        ex.lineno = no
-                    raise ex
-                except Exception as ex:
-                    logger.error("In line {0}, cannot add '{1}' {2}".format(no, line, ex))
-
-    def _build_cache(self):
-        """Build a cache of dimensionality and base units.
-        """
-
-        deps = dict((name, set(definition.reference.keys() if definition.reference else {}))
-                    for name, definition in self._units.items())
-
-        for unit_names in solve_dependencies(deps):
-            for unit_name in unit_names:
-                prefixed = False
-                for p in self._prefixes.keys():
-                    if p and unit_name.startswith(p):
-                        prefixed = True
-                        break
-                if '[' in unit_name:
-                    continue
-                try:
-                    uc = ParserHelper.from_word(unit_name)
-
-                    bu = self._get_root_units(uc)
-                    di = self._get_dimensionality(uc)
-
-                    self._root_units_cache[uc] = bu
-                    self._dimensionality_cache[uc] = di
-
-                    if not prefixed:
-                        if di not in self._dimensional_equivalents:
-                            self._dimensional_equivalents[di] = set()
-
-                        self._dimensional_equivalents[di].add(self._units[unit_name]._name)
-
-                except Exception as e:
-                    logger.warning('Could not resolve {0}: {1!r}'.format(unit_name, e))
-
-    def get_name(self, name_or_alias, case_sensitive=True):
-        """Return the canonical name of a unit.
-        """
-
-        if name_or_alias == 'dimensionless':
-            return ''
-
-        try:
-            return self._units[name_or_alias]._name
-        except KeyError:
-            pass
-
-        candidates = self._dedup_candidates(self.parse_unit_name(name_or_alias, case_sensitive))
-        if not candidates:
-            raise UndefinedUnitError(name_or_alias)
-        elif len(candidates) == 1:
-            prefix, unit_name, _ = candidates[0]
-        else:
-            logger.warning('Parsing {0} yield multiple results. '
-                           'Options are: {1}'.format(name_or_alias, candidates))
-            prefix, unit_name, _ = candidates[0]
-
-        if prefix:
-            name = prefix + unit_name
-            symbol = self.get_symbol(name)
-            prefix_def = self._prefixes[prefix]
-            self._units[name] = UnitDefinition(name, symbol, (), prefix_def.converter,
-                                               UnitsContainer({unit_name: 1}))
-            return prefix + unit_name
-
-        return unit_name
-
-    def get_symbol(self, name_or_alias):
-        """Return the preferred alias for a unit
-        """
-        candidates = self._dedup_candidates(self.parse_unit_name(name_or_alias))
-        if not candidates:
-            raise UndefinedUnitError(name_or_alias)
-        elif len(candidates) == 1:
-            prefix, unit_name, _ = candidates[0]
-        else:
-            logger.warning('Parsing {0} yield multiple results. '
-                           'Options are: {1!r}'.format(name_or_alias, candidates))
-            prefix, unit_name, _ = candidates[0]
-
-        return self._prefixes[prefix].symbol + self._units[unit_name].symbol
-
-    def _get_symbol(self, name):
-        return self._units[name].symbol
-
-    def get_dimensionality(self, input_units):
-        """Convert unit or dict of units or dimensions to a dict of base dimensions
-        dimensions
-
-        :param input_units:
-        :return: dimensionality
-        """
-        input_units = to_units_container(input_units)
-
-        return self._get_dimensionality(input_units)
-
-    def _get_dimensionality(self, input_units):
-        """ Convert a UnitsContainer to base dimensions.
-
-        :param input_units:
-        :return: dimensionality
-        """
-        if not input_units:
-            return UnitsContainer()
-
-        if input_units in self._dimensionality_cache:
-            return self._dimensionality_cache[input_units]
-
-        accumulator = defaultdict(float)
-        self._get_dimensionality_recurse(input_units, 1.0, accumulator)
-
-        if '[]' in accumulator:
-            del accumulator['[]']
-
-        dims = UnitsContainer(dict((k, v) for k, v in accumulator.items()
-                                   if v != 0.0))
-
-        self._dimensionality_cache[input_units] = dims
-
-        return dims
-
-    def _get_dimensionality_recurse(self, ref, exp, accumulator):
-        for key in ref:
-            exp2 = exp*ref[key]
-            if _is_dim(key):
-                reg = self._dimensions[key]
-                if reg.is_base:
-                    accumulator[key] += exp2
-                elif reg.reference is not None:
-                    self._get_dimensionality_recurse(reg.reference, exp2, accumulator)
-            else:
-                reg = self._units[self.get_name(key)]
-                if reg.reference is not None:
-                    self._get_dimensionality_recurse(reg.reference, exp2, accumulator)
-
-    def get_root_units(self, input_units, check_nonmult=True):
-        """Convert unit or dict of units to the root units.
-
-        If any unit is non multiplicative and check_converter is True,
-        then None is returned as the multiplicative factor.
-
-        :param input_units: units
-        :type input_units: UnitsContainer or str
-        :param check_nonmult: if True, None will be returned as the
-                              multiplicative factor if a non-multiplicative
-                              units is found in the final Units.
-        :return: multiplicative factor, base units
-        """
-        input_units = to_units_container(input_units)
-
-        f, units = self._get_root_units(input_units, check_nonmult)
-
-        return f, self.Unit(units)
-
-    def _get_root_units(self, input_units, check_nonmult=True):
-        """Convert unit or dict of units to the root units.
-
-        If any unit is non multiplicative and check_converter is True,
-        then None is returned as the multiplicative factor.
-
-        :param input_units: units
-        :type input_units: UnitsContainer or dict
-        :param check_nonmult: if True, None will be returned as the
-                              multiplicative factor if a non-multiplicative
-                              units is found in the final Units.
-        :return: multiplicative factor, base units
-        """
-        if not input_units:
-            return 1., UnitsContainer()
-
-        # The cache is only done for check_nonmult=True
-        if check_nonmult and input_units in self._root_units_cache:
-            return self._root_units_cache[input_units]
-
-        accumulators = [1., defaultdict(float)]
-        self._get_root_units_recurse(input_units, 1.0, accumulators)
-
-        factor = accumulators[0]
-        units = UnitsContainer(dict((k, v) for k, v in accumulators[1].items()
-                                    if v != 0.))
-
-        # Check if any of the final units is non multiplicative and return None instead.
-        if check_nonmult:
-            for unit in units.keys():
-                if not self._units[unit].converter.is_multiplicative:
-                    return None, units
-
-        if check_nonmult:
-            self._root_units_cache[input_units] = factor, units
-
-        return factor, units
-
-    def get_base_units(self, input_units, check_nonmult=True, system=None):
-        """Convert unit or dict of units to the base units.
-
-        If any unit is non multiplicative and check_converter is True,
-        then None is returned as the multiplicative factor.
-
-        :param input_units: units
-        :type input_units: UnitsContainer or str
-        :param check_nonmult: if True, None will be returned as the
-                              multiplicative factor if a non-multiplicative
-                              units is found in the final Units.
-        :return: multiplicative factor, base units
-        """
-        input_units = to_units_container(input_units)
-
-        f, units = self._get_base_units(input_units, check_nonmult, system)
-
-        return f, self.Unit(units)
-
-    def _get_base_units(self, input_units, check_nonmult=True, system=None):
-        """
-        :param registry:
-        :param input_units:
-        :param check_nonmult:
-        :param system: System
-        :return:
-        """
-
-        # The cache is only done for check_nonmult=True
-        if check_nonmult and input_units in self._base_units_cache:
-            return self._base_units_cache[input_units]
-
-        factor, units = self.get_root_units(input_units, check_nonmult)
-
-        if system is None:
-            system = self._default_system_name
-
-        if not system:
-            return factor, units
-
-        # This will not be necessary after integration with the registry as it has a UnitsContainer intermediate
-        units = to_units_container(units, self)
-
-        destination_units = UnitsContainer()
-
-        bu = self._gsmanager.get_system(system, False).base_units
-
-        for unit, value in units.items():
-            if unit in bu:
-                new_unit = bu[unit]
-                new_unit = to_units_container(new_unit, self)
-                destination_units *= new_unit ** value
-            else:
-                destination_units *= UnitsContainer({unit: value})
-
-        base_factor = self.convert(factor, units, destination_units)
-
-        if check_nonmult:
-            self._base_units_cache[input_units] = base_factor, destination_units
-
-        return base_factor, destination_units
-
-    def _get_root_units_recurse(self, ref, exp, accumulators):
-        for key in ref:
-            exp2 = exp*ref[key]
-            key = self.get_name(key)
-            reg = self._units[key]
-            if reg.is_base:
-                accumulators[1][key] += exp2
-            else:
-                accumulators[0] *= reg._converter.scale ** exp2
-                if reg.reference is not None:
-                    self._get_root_units_recurse(reg.reference, exp2,
-                                                 accumulators)
-
-    def get_compatible_units(self, input_units, group_or_system=None):
-        """
-        """
-        input_units = to_units_container(input_units)
-
-        equiv = self._get_compatible_units(input_units, group_or_system)
-
-        return frozenset(self.Unit(eq) for eq in equiv)
-
-    def _get_compatible_units(self, input_units, group_or_system=None):
-        """
-        """
-        if not input_units:
-            return frozenset()
-
-        src_dim = self._get_dimensionality(input_units)
-
-        ret = self._dimensional_equivalents[src_dim]
-
-        if self._active_ctx:
-            nodes = find_connected_nodes(self._active_ctx.graph, src_dim)
-            ret = set()
-            if nodes:
-                for node in nodes:
-                    ret |= self._dimensional_equivalents[node]
-
-        if group_or_system:
-            members = self._gsmanager[group_or_system].members
-            return frozenset(ret.intersection(members))
-
-        return ret
-
-    def convert(self, value, src, dst, inplace=False):
-        """Convert value from some source to destination units.
-
-        :param value: value
-        :param src: source units.
-        :type src: Quantity or str
-        :param dst: destination units.
-        :type dst: Quantity or str
-
-        :return: converted value
-        """
-        src = to_units_container(src, self)
-
-        dst = to_units_container(dst, self)
-
-        return self._convert(value, src, dst, inplace)
-
-    def _convert(self, value, src, dst, inplace=False):
-        """Convert value from some source to destination units.
-
-        :param value: value
-        :param src: source units.
-        :type src: UnitsContainer
-        :param dst: destination units.
-        :type dst: UnitsContainer
-
-        :return: converted value
-        """
-        if src == dst:
-            return value
-
-        src_dim = self._get_dimensionality(src)
-        dst_dim = self._get_dimensionality(dst)
-
-        # If there is an active context, we look for a path connecting source and
-        # destination dimensionality. If it exists, we transform the source value
-        # by applying sequentially each transformation of the path.
-        if self._active_ctx:
-            path = find_shortest_path(self._active_ctx.graph, src_dim, dst_dim)
-            if path:
-                src = self.Quantity(value, src)
-                for a, b in zip(path[:-1], path[1:]):
-                    src = self._active_ctx.transform(a, b, self, src)
-
-                value, src = src._magnitude, src._units
-
-                src_dim = self._get_dimensionality(src)
-
-        # If the source and destination dimensionality are different,
-        # then the conversion cannot be performed.
-
-        if src_dim != dst_dim:
-            raise DimensionalityError(src, dst, src_dim, dst_dim)
-
-        # Conversion needs to consider if non-multiplicative (AKA offset
-        # units) are involved. Conversion is only possible if src and dst
-        # have at most one offset unit per dimension.
-        src_offset_units = [(u, e) for u, e in src.items()
-                            if not self._units[u].is_multiplicative]
-        dst_offset_units = [(u, e) for u, e in dst.items()
-                            if not self._units[u].is_multiplicative]
-
-        # For offset units we need to check if the conversion is allowed.
-        if src_offset_units or dst_offset_units:
-
-            # Validate that not more than one offset unit is present
-            if len(src_offset_units) > 1 or len(dst_offset_units) > 1:
-                raise DimensionalityError(
-                    src, dst, src_dim, dst_dim,
-                    extra_msg=' - more than one offset unit.')
-
-            # validate that offset unit is not used in multiplicative context
-            if ((len(src_offset_units) == 1 and len(src) > 1)
-                    or (len(dst_offset_units) == 1 and len(dst) > 1)
-                    and not self.autoconvert_offset_to_baseunit):
-                raise DimensionalityError(
-                    src, dst, src_dim, dst_dim,
-                    extra_msg=' - offset unit used in multiplicative context.')
-
-            # Validate that order of offset unit is exactly one.
-            if src_offset_units:
-                if src_offset_units[0][1] != 1:
-                    raise DimensionalityError(
-                        src, dst, src_dim, dst_dim,
-                        extra_msg=' - offset units in higher order.')
-            else:
-                if dst_offset_units[0][1] != 1:
-                    raise DimensionalityError(
-                        src, dst, src_dim, dst_dim,
-                        extra_msg=' - offset units in higher order.')
-
-        # Here we convert only the offset quantities. Any remaining scaled
-        # quantities will be converted later.
-
-        # TODO: Shouldn't this (until factor, units) be inside the If above?
-
-        # clean src from offset units by converting to reference
-        for u, e in src_offset_units:
-            value = self._units[u].converter.to_reference(value, inplace)
-        src = src.remove([u for u, e in src_offset_units])
-
-        # clean dst units from offset units
-        dst = dst.remove([u for u, e in dst_offset_units])
-
-        # Here src and dst have only multiplicative units left. Thus we can
-        # convert with a factor.
-        factor, units = self._get_root_units(src / dst)
-
-        # factor is type float and if our magnitude is type Decimal then
-        # must first convert to Decimal before we can '*' the values
-        if isinstance(value, Decimal):
-            factor = Decimal(str(factor))
-
-        if inplace:
-            value *= factor
-        else:
-            value = value * factor
-
-        # Finally convert to offset units specified in destination
-        for u, e in dst_offset_units:
-            value = self._units[u].converter.from_reference(value, inplace)
-
-        return value
-
-    def pi_theorem(self, quantities):
-        """Builds dimensionless quantities using the Buckingham π theorem
-
-        :param quantities: mapping between variable name and units
-        :type quantities: dict
-        :return: a list of dimensionless quantities expressed as dicts
-        """
-        return pi_theorem(quantities, self)
-
-    def _dedup_candidates(self, candidates):
-        """Given a list of units, remove those with different names but equal value.
-        """
-        candidates = tuple(candidates)
-        if len(candidates) < 2:
-            return candidates
-
-        unique = [candidates[0]]
-        for c in candidates[2:]:
-            for u in unique:
-                if c == u:
-                    break
-            else:
-                unique.append(c)
-
-        return tuple(unique)
-
-    def parse_unit_name(self, unit_name, case_sensitive=True):
-        """Parse a unit to identify prefix, unit name and suffix
-        by walking the list of prefix and suffix.
-        """
-        stw = unit_name.startswith
-        edw = unit_name.endswith
-        for suffix, prefix in itertools.product(self._suffixes, self._prefixes):
-            if stw(prefix) and edw(suffix):
-                name = unit_name[len(prefix):]
-                if suffix:
-                    name = name[:-len(suffix)]
-                    if len(name) == 1:
-                        continue
-                if case_sensitive:
-                    if name in self._units:
-                        yield (self._prefixes[prefix]._name,
-                               self._units[name]._name,
-                               self._suffixes[suffix])
-                else:
-                    for real_name in self._units_casei.get(name.lower(), ()):
-                        yield (self._prefixes[prefix]._name,
-                               self._units[real_name]._name,
-                               self._suffixes[suffix])
-
-    def parse_units(self, input_string, as_delta=None):
-        """Parse a units expression and returns a UnitContainer with
-        the canonical names.
-
-        The expression can only contain products, ratios and powers of units.
-
-        :param as_delta: if the expression has multiple units, the parser will
-                         interpret non multiplicative units as their `delta_` counterparts.
-
-        :raises:
-            :class:`pint.UndefinedUnitError` if a unit is not in the registry
-            :class:`ValueError` if the expression is invalid.
-        """
-        units = self._parse_units(input_string, as_delta)
-        return self.Unit(units)
-
-    def _parse_units(self, input_string, as_delta=None):
-        """
-        """
-        if input_string in self._parse_unit_cache:
-            return self._parse_unit_cache[input_string]
-
-        if as_delta is None:
-            as_delta = self.default_as_delta
-
-        if not input_string:
-            return UnitsContainer()
-
-        units = ParserHelper.from_string(input_string)
-        if units.scale != 1:
-            raise ValueError('Unit expression cannot have a scaling factor.')
-
-        ret = {}
-        many = len(units) > 1
-        for name in units:
-            cname = self.get_name(name)
-            value = units[name]
-            if not cname:
-                continue
-            if as_delta and (many or (not many and value != 1)):
-                definition = self._units[cname]
-                if not definition.is_multiplicative:
-                    cname = 'delta_' + cname
-            ret[cname] = value
-
-        ret = UnitsContainer(ret)
-
-        self._parse_unit_cache[input_string] = ret
-
-        return ret
-    
-    def _eval_token(self, token, case_sensitive=True, **values):
-        token_type = token[0]
-        token_text = token[1]
-        if token_type == NAME:
-            if token_text == 'pi':
-                return self.Quantity(math.pi)
-            elif token_text in values:
-                return self.Quantity(values[token_text])
-            else:
-                return self.Quantity(1, UnitsContainer({self.get_name(token_text, 
-                                                                      case_sensitive=case_sensitive) : 1}))
-        elif token_type == NUMBER:
-            return ParserHelper.eval_token(token)
-        else:
-            raise Exception('unknown token type')
-
-    def parse_expression(self, input_string, case_sensitive=True, **values):
-        """Parse a mathematical expression including units and return a quantity object.
-
-        Numerical constants can be specified as keyword arguments and will take precedence
-        over the names defined in the registry.
-        """
-        
-        if not input_string:
-            return self.Quantity(1)
-
-        input_string = string_preprocessor(input_string)
-        gen = tokenizer(input_string)
-        
-        return build_eval_tree(gen).evaluate(lambda x : self._eval_token(x, case_sensitive=case_sensitive,
-                                                                          **values))
-
-    __call__ = parse_expression
-
-    def wraps(self, ret, args, strict=True):
-        """Wraps a function to become pint-aware.
-
-        Use it when a function requires a numerical value but in some specific
-        units. The wrapper function will take a pint quantity, convert to the units
-        specified in `args` and then call the wrapped function with the resulting
-        magnitude.
-
-        The value returned by the wrapped function will be converted to the units
-        specified in `ret`.
-
-        Use None to skip argument conversion.
-        Set strict to False, to accept also numerical values.
-
-        :param ret: output units.
-        :param args: iterable of input units.
-        :param strict: boolean to indicate that only quantities are accepted.
-        :return: the wrapped function.
-        :raises:
-            :class:`ValueError` if strict and one of the arguments is not a Quantity.
-        """
-
-        Q_ = self.Quantity
-
-        if not isinstance(args, (list, tuple)):
-            args = (args, )
-
-        units = [to_units_container(arg, self) for arg in args]
-
-        if isinstance(ret, (list, tuple)):
-            ret = ret.__class__([to_units_container(arg, self) for arg in ret])
-        elif isinstance(ret, string_types):
-            ret = self.parse_units(ret)
-
-        def decorator(func):
-            assigned = tuple(attr for attr in functools.WRAPPER_ASSIGNMENTS if hasattr(func, attr))
-            updated = tuple(attr for attr in functools.WRAPPER_UPDATES if hasattr(func, attr))
-            @functools.wraps(func, assigned=assigned, updated=updated)
-            def wrapper(*values, **kw):
-                new_args = []
-                for unit, value in zip(units, values):
-                    if unit is None:
-                        new_args.append(value)
-                    elif isinstance(value, Q_):
-                        new_args.append(self._convert(value._magnitude,
-                                                      value._units, unit))
-                    elif not strict:
-                        new_args.append(value)
-                    else:
-                        raise ValueError('A wrapped function using strict=True requires '
-                                         'quantity for all arguments with not None units. '
-                                         '(error found for {0}, {1})'.format(unit, value))
-
-                result = func(*new_args, **kw)
-
-                if isinstance(ret, (list, tuple)):
-                    return ret.__class__(res if unit is None else Q_(res, unit)
-                                         for unit, res in zip(ret, result))
-                elif ret is not None:
-                    return Q_(result, ret)
-
-                return result
-            return wrapper
-        return decorator
-
-    def check(self, *args):
-        """Decorator to for quantity type checking for function inputs.
-
-        Use it to ensure that the decorated function input parameters match
-        the expected type of pint quantity.
-
-        Use None to skip argument checking.
-
-        :param args: iterable of input units.
-        :return: the wrapped function.
-        :raises:
-            :class:`DimensionalityError` if the parameters don't match dimensions
-        """
-        dimensions = [self.get_dimensionality(dim) for dim in args]
-
-        def decorator(func):
-            assigned = tuple(attr for attr in functools.WRAPPER_ASSIGNMENTS if hasattr(func, attr))
-            updated = tuple(attr for attr in functools.WRAPPER_UPDATES if hasattr(func, attr))
-
-            @functools.wraps(func, assigned=assigned, updated=updated)
-            def wrapper(*values, **kwargs):
-                for dim, value in zip_longest(dimensions, values):
-                    if dim and value.dimensionality != dim:
-                        raise DimensionalityError(value, 'a quantity of',
-                                                  value.dimensionality, dim)
-                return func(*values, **kwargs)
-            return wrapper
-        return decorator
-
-
-def build_unit_class(registry):
-
-    class Unit(_Unit):
-        pass
-
-    Unit._REGISTRY = registry
-    return Unit
-
-
-def build_quantity_class(registry, force_ndarray=False):
-    from .quantity import _Quantity
-
-    class Quantity(_Quantity):
-        pass
-
-    Quantity._REGISTRY = registry
-    Quantity.force_ndarray = force_ndarray
-
-    return Quantity
-
-
-def build_measurement_class(registry, force_ndarray=False):
-    from .measurement import _Measurement, ufloat
-
-    if ufloat is None:
-        class Measurement(object):
-
-            def __init__(self, *args):
-                raise RuntimeError("Pint requires the 'uncertainties' package to create a Measurement object.")
-
-    else:
-        class Measurement(_Measurement, registry.Quantity):
-            pass
-
-    Measurement._REGISTRY = registry
-    Measurement.force_ndarray = force_ndarray
-
-    return Measurement
-
-
-class LazyRegistry(object):
-
-    def __init__(self, args=None, kwargs=None):
-        self.__dict__['params'] = args or (), kwargs or {}
-
-    def __init(self):
-        args, kwargs = self.__dict__['params']
-        kwargs['on_redefinition'] = 'raise'
-        self.__class__ = UnitRegistry
-        self.__init__(*args, **kwargs)
-
-    def __getattr__(self, item):
-        if item == '_on_redefinition':
-            return 'raise'
-        self.__init()
-        return getattr(self, item)
-
-    def __setattr__(self, key, value):
-        if key == '__class__':
-            super(LazyRegistry, self).__setattr__(key, value)
-        else:
-            self.__init()
-            setattr(self, key, value)
-
-    def __getitem__(self, item):
-        self.__init()
-        return self[item]
-
-    def __call__(self, *args, **kwargs):
-        self.__init()
-        return self(*args, **kwargs)
diff --git a/lib/taurus/external/pint/pint_local/util.py b/lib/taurus/external/pint/pint_local/util.py
deleted file mode 100644
index 7ff28e3..0000000
--- a/lib/taurus/external/pint/pint_local/util.py
+++ /dev/null
@@ -1,643 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-    pint.util
-    ~~~~~~~~~
-
-    Miscellaneous functions for pint.
-
-    :copyright: 2013 by Pint Authors, see AUTHORS for more details.
-    :license: BSD, see LICENSE for more details.
-"""
-
-from __future__ import division, unicode_literals, print_function, absolute_import
-
-import re
-import operator
-from numbers import Number
-from fractions import Fraction
-from collections import Mapping
-
-import logging
-from token import STRING, NAME, OP, NUMBER
-from tokenize import untokenize
-
-from .compat import string_types, tokenizer, lru_cache, NullHandler, maketrans, NUMERIC_TYPES
-from .formatting import format_unit
-from .pint_eval import build_eval_tree
-
-logger = logging.getLogger(__name__)
-logger.addHandler(NullHandler())
-
-
-def matrix_to_string(matrix, row_headers=None, col_headers=None, fmtfun=lambda x: str(int(x))):
-    """Takes a 2D matrix (as nested list) and returns a string.
-    """
-    ret = []
-    if col_headers:
-        ret.append(('\t' if row_headers else '') + '\t'.join(col_headers))
-    if row_headers:
-        ret += [rh + '\t' + '\t'.join(fmtfun(f) for f in row)
-                for rh, row in zip(row_headers, matrix)]
-    else:
-        ret += ['\t'.join(fmtfun(f) for f in row)
-                for row in matrix]
-
-    return '\n'.join(ret)
-
-
-def transpose(matrix):
-    """Takes a 2D matrix (as nested list) and returns the transposed version.
-    """
-    return [list(val) for val in zip(*matrix)]
-
-
-def column_echelon_form(matrix, ntype=Fraction, transpose_result=False):
-    """Calculates the column echelon form using Gaussian elimination.
-
-    :param matrix: a 2D matrix as nested list.
-    :param ntype: the numerical type to use in the calculation.
-    :param transpose_result: indicates if the returned matrix should be transposed.
-    :return: column echelon form, transformed identity matrix, swapped rows
-    """
-    lead = 0
-
-    M = transpose(matrix)
-
-    _transpose = transpose if transpose_result else lambda x: x
-
-    rows, cols = len(M), len(M[0])
-
-    new_M = []
-    for row in M:
-        r = []
-        for x in row:
-            if isinstance(x, float):
-                x = ntype.from_float(x)
-            else:
-                x = ntype(x)
-            r.append(x)
-        new_M.append(r)
-    M = new_M
-
-#    M = [[ntype(x) for x in row] for row in M]
-    I = [[ntype(1) if n == nc else ntype(0) for nc in range(rows)] for n in range(rows)]
-    swapped = []
-
-    for r in range(rows):
-        if lead >= cols:
-            return _transpose(M), _transpose(I), swapped
-        i = r
-        while M[i][lead] == 0:
-            i += 1
-            if i != rows:
-                continue
-            i = r
-            lead += 1
-            if cols == lead:
-                return _transpose(M), _transpose(I), swapped
-
-        M[i], M[r] = M[r], M[i]
-        I[i], I[r] = I[r], I[i]
-
-        swapped.append(i)
-        lv = M[r][lead]
-        M[r] = [mrx / lv for mrx in M[r]]
-        I[r] = [mrx / lv for mrx in I[r]]
-
-        for i in range(rows):
-            if i == r:
-                continue
-            lv = M[i][lead]
-            M[i] = [iv - lv*rv for rv, iv in zip(M[r], M[i])]
-            I[i] = [iv - lv*rv for rv, iv in zip(I[r], I[i])]
-
-        lead += 1
-
-    return _transpose(M), _transpose(I), swapped
-
-
-def pi_theorem(quantities, registry=None):
-    """Builds dimensionless quantities using the Buckingham π theorem
-
-    :param quantities: mapping between variable name and units
-    :type quantities: dict
-    :return: a list of dimensionless quantities expressed as dicts
-    """
-
-    # Preprocess input and build the dimensionality Matrix
-    quant = []
-    dimensions = set()
-
-    if registry is None:
-        getdim = lambda x: x
-    else:
-        getdim = registry.get_dimensionality
-
-    for name, value in quantities.items():
-        if isinstance(value, string_types):
-            value = ParserHelper.from_string(value)
-        if isinstance(value, dict):
-            dims = getdim(UnitsContainer(value))
-        elif not hasattr(value, 'dimensionality'):
-            dims = getdim(value)
-        else:
-            dims = value.dimensionality
-
-        if not registry and any(not key.startswith('[') for key in dims):
-            logger.warning('A non dimension was found and a registry was not provided. '
-                           'Assuming that it is a dimension name: {0}.'.format(dims))
-
-        quant.append((name, dims))
-        dimensions = dimensions.union(dims.keys())
-
-    dimensions = list(dimensions)
-
-    # Calculate dimensionless  quantities
-    M = [[dimensionality[dimension] for name, dimensionality in quant]
-         for dimension in dimensions]
-
-    M, identity, pivot = column_echelon_form(M, transpose_result=False)
-
-    # Collect results
-    # Make all numbers integers and minimize the number of negative exponents.
-    # Remove zeros
-    results = []
-    for rowm, rowi in zip(M, identity):
-        if any(el != 0 for el in rowm):
-            continue
-        max_den = max(f.denominator for f in rowi)
-        neg = -1 if sum(f < 0 for f in rowi) > sum(f > 0 for f in rowi) else 1
-        results.append(dict((q[0], neg * f.numerator * max_den / f.denominator)
-                            for q, f in zip(quant, rowi) if f.numerator != 0))
-    return results
-
-
-def solve_dependencies(dependencies):
-    """Solve a dependency graph.
-
-    :param dependencies: dependency dictionary. For each key, the value is
-                         an iterable indicating its dependencies.
-    :return: list of sets, each containing keys of independents tasks dependent
-                           only of the previous tasks in the list.
-    """
-    d = dict((key, set(dependencies[key])) for key in dependencies)
-    r = []
-    while d:
-        # values not in keys (items without dep)
-        t = set(i for v in d.values() for i in v) - set(d.keys())
-        # and keys without value (items without dep)
-        t.update(k for k, v in d.items() if not v)
-        # can be done right away
-        r.append(t)
-        # and cleaned up
-        d = dict(((k, v - t) for k, v in d.items() if v))
-    return r
-
-
-def find_shortest_path(graph, start, end, path=None):
-    path = (path or []) + [start]
-    if start == end:
-        return path
-    if not start in graph:
-        return None
-    shortest = None
-    for node in graph[start]:
-        if node not in path:
-            newpath = find_shortest_path(graph, node, end, path)
-            if newpath:
-                if not shortest or len(newpath) < len(shortest):
-                    shortest = newpath
-    return shortest
-
-
-def find_connected_nodes(graph, start, visited=None):
-    if not start in graph:
-        return None
-
-    visited = (visited or set())
-    visited.add(start)
-
-    for node in graph[start]:
-        if node not in visited:
-            find_connected_nodes(graph, node, visited)
-
-    return visited
-
-
-class udict(dict):
-    """ Custom dict implementing __missing__.
-
-    """
-    def __missing__(self, key):
-        return 0.
-
-
-class UnitsContainer(Mapping):
-    """The UnitsContainer stores the product of units and their respective
-    exponent and implements the corresponding operations.
-
-    UnitsContainer is a read-only mapping. All operations (even in place ones)
-    return new instances.
-
-    """
-    __slots__ = ('_d', '_hash')
-
-    def __init__(self, *args, **kwargs):
-        d = udict(*args, **kwargs)
-        self._d = d
-        for key, value in d.items():
-            if not isinstance(key, string_types):
-                raise TypeError('key must be a str, not {0}'.format(type(key)))
-            if not isinstance(value, Number):
-                raise TypeError('value must be a number, not {0}'.format(type(value)))
-            if not isinstance(value, float):
-                d[key] = float(value)
-        self._hash = hash(frozenset(self._d.items()))
-
-    def copy(self):
-        return self.__copy__()
-
-    def add(self, key, value):
-        newval = self._d[key] + value
-        new = self.copy()
-        if newval:
-            new._d[key] = newval
-        else:
-            del new._d[key]
-
-        return new
-
-    def remove(self, keys):
-        """ Create a new UnitsContainer purged from given keys.
-
-        """
-        d = udict(self._d)
-        return UnitsContainer(((key, d[key]) for key in d if key not in keys))
-
-    def rename(self, oldkey, newkey):
-        """ Create a new UnitsContainer in which an entry has been renamed.
-
-        """
-        d = udict(self._d)
-        d[newkey] = d.pop(oldkey)
-        return UnitsContainer(d)
-
-    def __iter__(self):
-        return iter(self._d)
-
-    def __len__(self):
-        return len(self._d)
-
-    def __getitem__(self, key):
-        return self._d[key]
-
-    def __hash__(self):
-        return self._hash
-
-    def __getstate__(self):
-        return {'_d': self._d, '_hash': self._hash}
-
-    def __setstate__(self, state):
-        self._d = state['_d']
-        self._hash = state['_hash']
-
-    def __eq__(self, other):
-        if isinstance(other, UnitsContainer):
-            other = other._d
-        elif isinstance(other, string_types):
-            other = ParserHelper.from_string(other)
-            other = other._d
-
-        return dict.__eq__(self._d, other)
-
-    def __str__(self):
-        return self.__format__('')
-
-    def __repr__(self):
-        tmp = '{%s}' % ', '.join(["'{0}': {1}".format(key, value)
-                                  for key, value in sorted(self._d.items())])
-        return '<UnitsContainer({0})>'.format(tmp)
-
-    def __format__(self, spec):
-        return format_unit(self, spec)
-
-    def __copy__(self):
-        return UnitsContainer(self._d)
-
-    def __mul__(self, other):
-        d = udict(self._d)
-        if not isinstance(other, self.__class__):
-            err = 'Cannot multiply UnitsContainer by {0}'
-            raise TypeError(err.format(type(other)))
-        for key, value in other.items():
-            d[key] += value
-        keys = [key for key, value in d.items() if value == 0]
-        for key in keys:
-            del d[key]
-
-        return UnitsContainer(d)
-
-    __rmul__ = __mul__
-
-    def __pow__(self, other):
-        if not isinstance(other, NUMERIC_TYPES):
-            err = 'Cannot power UnitsContainer by {0}'
-            raise TypeError(err.format(type(other)))
-        d = udict(self._d)
-        for key, value in d.items():
-            d[key] *= other
-        return UnitsContainer(d)
-
-    def __truediv__(self, other):
-        if not isinstance(other, self.__class__):
-            err = 'Cannot divide UnitsContainer by {0}'
-            raise TypeError(err.format(type(other)))
-
-        d = udict(self._d)
-
-        for key, value in other.items():
-            d[key] -= value
-
-        keys = [key for key, value in d.items() if value == 0]
-        for key in keys:
-            del d[key]
-
-        return UnitsContainer(d)
-
-    def __rtruediv__(self, other):
-        if not isinstance(other, self.__class__) and other != 1:
-            err = 'Cannot divide {0} by UnitsContainer'
-            raise TypeError(err.format(type(other)))
-
-        return self**-1
-
-
-class ParserHelper(UnitsContainer):
-    """ The ParserHelper stores in place the product of variables and
-    their respective exponent and implements the corresponding operations.
-
-    ParserHelper is a read-only mapping. All operations (even in place ones)
-    return new instances.
-
-    WARNING : The hash value used does not take into account the scale
-    attribute so be careful if you use it as a dict key and then two unequal
-    object can have the same hash.
-
-    """
-
-    __slots__ = ('scale', )
-
-    def __init__(self, scale=1, *args, **kwargs):
-        super(ParserHelper, self).__init__(*args, **kwargs)
-        self.scale = scale
-
-    @classmethod
-    def from_word(cls, input_word):
-        """Creates a ParserHelper object with a single variable with exponent one.
-
-        Equivalent to: ParserHelper({'word': 1})
-
-        """
-        return cls(1, [(input_word, 1)])
-
-    @classmethod
-    def from_string(cls, input_string):
-        return cls._from_string(input_string)
-    
-    @classmethod
-    def eval_token(cls, token, use_decimal=False):
-        token_type = token[0]
-        token_text = token[1]
-        if token_type == NUMBER:
-            if '.' in token_text or 'e' in token_text:
-                if use_decimal:
-                    return Decimal(token_text)
-                return float(token_text)
-            return int(token_text)
-        elif token_type == NAME:
-            return ParserHelper.from_word(token_text)
-        else:
-            raise Exception('unknown token type')
-    
-    @classmethod
-    @lru_cache()
-    def _from_string(cls, input_string):
-        """Parse linear expression mathematical units and return a quantity object.
-
-        """
-        if not input_string:
-            return cls()
-
-        input_string = string_preprocessor(input_string)
-        if '[' in input_string:
-            input_string = input_string.replace('[', '__obra__').replace(']', '__cbra__')
-            reps = True
-        else:
-            reps = False
-
-        gen = tokenizer(input_string)
-        ret = build_eval_tree(gen).evaluate(cls.eval_token)
-
-        if isinstance(ret, Number):
-            return ParserHelper(ret)
-
-        if not reps:
-            return ret
-
-        return ParserHelper(ret.scale,
-                            dict((key.replace('__obra__', '[').replace('__cbra__', ']'), value)
-                                 for key, value in ret.items()))
-
-    def __copy__(self):
-        # workaround for python2.6 compatibility (cast kwarg keys to str)
-        # see http://bugs.python.org/issue2646
-        kwargs = dict([(str(k),v) for k,v in self.items()])
-        return ParserHelper(scale=self.scale, **kwargs)
-
-    def copy(self):
-        return self.__copy__()
-
-    def __hash__(self):
-        if self.scale != 1.0:
-            mess = 'Only scale 1.0 ParserHelper instance should be considered hashable'
-            raise ValueError(mess)
-        return self._hash
-
-    def __eq__(self, other):
-        if isinstance(other, self.__class__):
-            return self.scale == other.scale and\
-                super(ParserHelper, self).__eq__(other)
-        elif isinstance(other, string_types):
-            return self == ParserHelper.from_string(other)
-        elif isinstance(other, Number):
-            return self.scale == other and not len(self._d)
-        else:
-            return self.scale == 1. and super(ParserHelper, self).__eq__(other)
-
-    def operate(self, items, op=operator.iadd, cleanup=True):
-        d = udict(self._d)
-        for key, value in items:
-            d[key] = op(d[key], value)
-
-        if cleanup:
-            keys = [key for key, value in d.items() if value == 0]
-            for key in keys:
-                del d[key]
-
-        return self.__class__(self.scale, d)
-
-    def __str__(self):
-        tmp = '{%s}' % ', '.join(["'{0}': {1}".format(key, value)
-                                  for key, value in sorted(self._d.items())])
-        return '{0} {1}'.format(self.scale, tmp)
-
-    def __repr__(self):
-        tmp = '{%s}' % ', '.join(["'{0}': {1}".format(key, value)
-                                  for key, value in sorted(self._d.items())])
-        return '<ParserHelper({0}, {1})>'.format(self.scale, tmp)
-
-    def __mul__(self, other):
-        if isinstance(other, string_types):
-            new = self.add(other, 1)
-        elif isinstance(other, Number):
-            new = self.copy()
-            new.scale *= other
-        elif isinstance(other, self.__class__):
-            new = self.operate(other.items())
-            new.scale *= other.scale
-        else:
-            new = self.operate(other.items())
-        return new
-
-    __rmul__ = __mul__
-
-    def __pow__(self, other):
-        d = self._d.copy()
-        for key in self._d:
-            d[key] *= other
-        return self.__class__(self.scale**other, d)
-
-    def __truediv__(self, other):
-        if isinstance(other, string_types):
-            new = self.add(other, -1)
-        elif isinstance(other, Number):
-            new = self.copy()
-            new.scale /= other
-        elif isinstance(other, self.__class__):
-            new = self.operate(other.items(), operator.sub)
-            new.scale /= other.scale
-        else:
-            new = self.operate(other.items(), operator.sub)
-        return new
-
-    __floordiv__ = __truediv__
-
-    def __rtruediv__(self, other):
-        new = self.__pow__(-1)
-        if isinstance(other, string_types):
-            new = new.add(other, 1)
-        elif isinstance(other, Number):
-            new.scale *= other
-        elif isinstance(other, self.__class__):
-            new = self.operate(other.items(), operator.add)
-            new.scale *= other.scale
-        else:
-            new = new.operate(other.items(), operator.add)
-        return new
-
-
-#: List of regex substitution pairs.
-_subs_re = [(r"([\w\.\-\+\*\\\^])\s+", r"\1 "), # merge multiple spaces
-            (r"({0}) squared", r"\1**2"),  # Handle square and cube
-            (r"({0}) cubed", r"\1**3"),
-            (r"cubic ({0})", r"\1**3"),
-            (r"square ({0})", r"\1**2"),
-            (r"sq ({0})", r"\1**2"),
-            (r"\b([0-9]+\.?[0-9]*)(?=[e|E][a-zA-Z]|[a-df-zA-DF-Z])", r"\1*"),  # Handle numberLetter for multiplication
-            (r"([\w\.\-])\s+(?=\w)", r"\1*"),  # Handle space for multiplication
-            ]
-
-#: Compiles the regex and replace {0} by a regex that matches an identifier.
-_subs_re = [(re.compile(a.format(r"[_a-zA-Z][_a-zA-Z0-9]*")), b) for a, b in _subs_re]
-_pretty_table = maketrans('⁰¹²³⁴⁵⁶⁷⁸⁹·⁻', '0123456789*-')
-_pretty_exp_re = re.compile(r"⁻?[⁰¹²³⁴⁵⁶⁷⁸⁹]+(?:\.[⁰¹²³⁴⁵⁶⁷⁸⁹]*)?")
-
-
-def string_preprocessor(input_string):
-
-    input_string = input_string.replace(",", "")
-    input_string = input_string.replace(" per ", "/")
-
-    for a, b in _subs_re:
-        input_string = a.sub(b, input_string)
-
-    # Replace pretty format characters
-    for pretty_exp in _pretty_exp_re.findall(input_string):
-        exp = '**' + pretty_exp.translate(_pretty_table)
-        input_string = input_string.replace(pretty_exp, exp)
-    input_string = input_string.translate(_pretty_table)
-
-    # Handle caret exponentiation
-    input_string = input_string.replace("^", "**")
-    return input_string
-
-
-def _is_dim(name):
-    return name[0] == '[' and name[-1] == ']'
-
-
-class SharedRegistryObject(object):
-    """Base class for object keeping a refrence to the registree.
-
-    Such object are for now _Quantity and _Unit, in a number of places it is
-    that an object from this class has a '_units' attribute.
-
-    """
-
-    def _check(self, other):
-        """Check if the other object use a registry and if so that it is the
-        same registry.
-
-        Return True is both use a registry and they use the same, False is
-        other don't use a registry and raise ValueError if other don't use the
-        same unit registry.
-
-        """
-        if self._REGISTRY is getattr(other, '_REGISTRY', None):
-            return True
-
-        elif isinstance(other, SharedRegistryObject):
-            mess = 'Cannot operate with {0} and {1} of different registries.'
-            raise ValueError(mess.format(self.__class__.__name__,
-                                         other.__class__.__name__))
-        else:
-            return False
-
-def to_units_container(unit_like, registry=None):
-    """ Convert a unit compatible type to a UnitsContainer.
-
-    """
-    mro = type(unit_like).mro()
-    if UnitsContainer in mro:
-        return unit_like
-    elif SharedRegistryObject in mro:
-        return unit_like._units
-    elif string_types in mro:
-        if registry:
-            return registry._parse_units(unit_like)
-        else:
-            return ParserHelper.from_string(unit_like)
-    elif dict in mro:
-        return UnitsContainer(unit_like)
-
-
-def infer_base_unit(q):
-    """Return UnitsContainer of q with all prefixes stripped."""
-    d = {}
-    parse = q._REGISTRY.parse_unit_name
-    for unit_name, power in q._units.items():
-        completely_parsed_unit = list(parse(unit_name))[-1]
-
-        _, base_unit, __ = completely_parsed_unit
-        d[base_unit] = power
-    return UnitsContainer(d)
diff --git a/setup.cfg b/setup.cfg
index 8bfd5a1..861a9f5 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,4 +1,5 @@
 [egg_info]
 tag_build = 
 tag_date = 0
+tag_svn_revision = 0
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/taurus.git



More information about the debian-science-commits mailing list