Mercurial > repos > shellac > guppy_basecaller
diff env/lib/python3.7/site-packages/boltons/namedutils.py @ 0:26e78fe6e8c4 draft
"planemo upload commit c699937486c35866861690329de38ec1a5d9f783"
author | shellac |
---|---|
date | Sat, 02 May 2020 07:14:21 -0400 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/env/lib/python3.7/site-packages/boltons/namedutils.py Sat May 02 07:14:21 2020 -0400 @@ -0,0 +1,369 @@ +# -*- coding: utf-8 -*- +"""\ +The ``namedutils`` module defines two lightweight container types: +:class:`namedtuple` and :class:`namedlist`. Both are subtypes of built-in +sequence types, which are very fast and efficient. They simply add +named attribute accessors for specific indexes within themselves. + +The :class:`namedtuple` is identical to the built-in +:class:`collections.namedtuple`, with a couple of enhancements, +including a ``__repr__`` more suitable to inheritance. + +The :class:`namedlist` is the mutable counterpart to the +:class:`namedtuple`, and is much faster and lighter-weight than +full-blown :class:`object`. Consider this if you're implementing nodes +in a tree, graph, or other mutable data structure. If you want an even +skinnier approach, you'll probably have to look to C. +""" + +from __future__ import print_function + +import sys as _sys +try: + from collections import OrderedDict +except ImportError: + # backwards compatibility (2.6 has no OrderedDict) + OrderedDict = dict +from keyword import iskeyword as _iskeyword +from operator import itemgetter as _itemgetter + +try: + basestring + def exec_(code, global_env): + exec("exec code in global_env") +except NameError: + basestring = (str, bytes) # Python 3 compat + def exec_(code, global_env): + exec(code, global_env) + +__all__ = ['namedlist', 'namedtuple'] + +# Tiny templates + +_repr_tmpl = '{name}=%r' + +_imm_field_tmpl = '''\ + {name} = _property(_itemgetter({index:d}), doc='Alias for field {index:d}') +''' + +_m_field_tmpl = '''\ + {name} = _property(_itemgetter({index:d}), _itemsetter({index:d}), doc='Alias for field {index:d}') +''' + +################################################################# +### namedtuple +################################################################# + +_namedtuple_tmpl = '''\ +class {typename}(tuple): + '{typename}({arg_list})' + + __slots__ = () + + _fields = {field_names!r} + + def __new__(_cls, {arg_list}): # TODO: tweak sig to make more extensible + 'Create new instance of {typename}({arg_list})' + return _tuple.__new__(_cls, ({arg_list})) + + @classmethod + def _make(cls, iterable, new=_tuple.__new__, len=len): + 'Make a new {typename} object from a sequence or iterable' + result = new(cls, iterable) + if len(result) != {num_fields:d}: + raise TypeError('Expected {num_fields:d}' + ' arguments, got %d' % len(result)) + return result + + def __repr__(self): + 'Return a nicely formatted representation string' + tmpl = self.__class__.__name__ + '({repr_fmt})' + return tmpl % self + + def _asdict(self): + 'Return a new OrderedDict which maps field names to their values' + return OrderedDict(zip(self._fields, self)) + + def _replace(_self, **kwds): + 'Return a new {typename} object replacing field(s) with new values' + result = _self._make(map(kwds.pop, {field_names!r}, _self)) + if kwds: + raise ValueError('Got unexpected field names: %r' % kwds.keys()) + return result + + def __getnewargs__(self): + 'Return self as a plain tuple. Used by copy and pickle.' + return tuple(self) + + __dict__ = _property(_asdict) + + def __getstate__(self): + 'Exclude the OrderedDict from pickling' # wat + pass + +{field_defs} +''' + +def namedtuple(typename, field_names, verbose=False, rename=False): + """Returns a new subclass of tuple with named fields. + + >>> Point = namedtuple('Point', ['x', 'y']) + >>> Point.__doc__ # docstring for the new class + 'Point(x, y)' + >>> p = Point(11, y=22) # instantiate with pos args or keywords + >>> p[0] + p[1] # indexable like a plain tuple + 33 + >>> x, y = p # unpack like a regular tuple + >>> x, y + (11, 22) + >>> p.x + p.y # fields also accessible by name + 33 + >>> d = p._asdict() # convert to a dictionary + >>> d['x'] + 11 + >>> Point(**d) # convert from a dictionary + Point(x=11, y=22) + >>> p._replace(x=100) # _replace() is like str.replace() but targets named fields + Point(x=100, y=22) + """ + + # Validate the field names. At the user's option, either generate an error + # message or automatically replace the field name with a valid name. + if isinstance(field_names, basestring): + field_names = field_names.replace(',', ' ').split() + field_names = [str(x) for x in field_names] + if rename: + seen = set() + for index, name in enumerate(field_names): + if (not all(c.isalnum() or c == '_' for c in name) + or _iskeyword(name) + or not name + or name[0].isdigit() + or name.startswith('_') + or name in seen): + field_names[index] = '_%d' % index + seen.add(name) + for name in [typename] + field_names: + if not all(c.isalnum() or c == '_' for c in name): + raise ValueError('Type names and field names can only contain ' + 'alphanumeric characters and underscores: %r' + % name) + if _iskeyword(name): + raise ValueError('Type names and field names cannot be a ' + 'keyword: %r' % name) + if name[0].isdigit(): + raise ValueError('Type names and field names cannot start with ' + 'a number: %r' % name) + seen = set() + for name in field_names: + if name.startswith('_') and not rename: + raise ValueError('Field names cannot start with an underscore: ' + '%r' % name) + if name in seen: + raise ValueError('Encountered duplicate field name: %r' % name) + seen.add(name) + + # Fill-in the class template + fmt_kw = {'typename': typename} + fmt_kw['field_names'] = tuple(field_names) + fmt_kw['num_fields'] = len(field_names) + fmt_kw['arg_list'] = repr(tuple(field_names)).replace("'", "")[1:-1] + fmt_kw['repr_fmt'] = ', '.join(_repr_tmpl.format(name=name) + for name in field_names) + fmt_kw['field_defs'] = '\n'.join(_imm_field_tmpl.format(index=index, name=name) + for index, name in enumerate(field_names)) + class_definition = _namedtuple_tmpl.format(**fmt_kw) + + if verbose: + print(class_definition) + + # Execute the template string in a temporary namespace and support + # tracing utilities by setting a value for frame.f_globals['__name__'] + namespace = dict(_itemgetter=_itemgetter, + __name__='namedtuple_%s' % typename, + OrderedDict=OrderedDict, + _property=property, + _tuple=tuple) + try: + exec_(class_definition, namespace) + except SyntaxError as e: + raise SyntaxError(e.message + ':\n' + class_definition) + result = namespace[typename] + + # For pickling to work, the __module__ variable needs to be set to the frame + # where the named tuple is created. Bypass this step in environments where + # sys._getframe is not defined (Jython for example) or sys._getframe is not + # defined for arguments greater than 0 (IronPython). + try: + frame = _sys._getframe(1) + result.__module__ = frame.f_globals.get('__name__', '__main__') + except (AttributeError, ValueError): + pass + + return result + + +################################################################# +### namedlist +################################################################# + +_namedlist_tmpl = '''\ +class {typename}(list): + '{typename}({arg_list})' + + __slots__ = () + + _fields = {field_names!r} + + def __new__(_cls, {arg_list}): # TODO: tweak sig to make more extensible + 'Create new instance of {typename}({arg_list})' + return _list.__new__(_cls, ({arg_list})) + + def __init__(self, {arg_list}): # tuple didn't need this but list does + return _list.__init__(self, ({arg_list})) + + @classmethod + def _make(cls, iterable, new=_list, len=len): + 'Make a new {typename} object from a sequence or iterable' + # why did this function exist? why not just star the + # iterable like below? + result = cls(*iterable) + if len(result) != {num_fields:d}: + raise TypeError('Expected {num_fields:d} arguments,' + ' got %d' % len(result)) + return result + + def __repr__(self): + 'Return a nicely formatted representation string' + tmpl = self.__class__.__name__ + '({repr_fmt})' + return tmpl % tuple(self) + + def _asdict(self): + 'Return a new OrderedDict which maps field names to their values' + return OrderedDict(zip(self._fields, self)) + + def _replace(_self, **kwds): + 'Return a new {typename} object replacing field(s) with new values' + result = _self._make(map(kwds.pop, {field_names!r}, _self)) + if kwds: + raise ValueError('Got unexpected field names: %r' % kwds.keys()) + return result + + def __getnewargs__(self): + 'Return self as a plain list. Used by copy and pickle.' + return tuple(self) + + __dict__ = _property(_asdict) + + def __getstate__(self): + 'Exclude the OrderedDict from pickling' # wat + pass + +{field_defs} +''' + + +def namedlist(typename, field_names, verbose=False, rename=False): + """Returns a new subclass of list with named fields. + + >>> Point = namedlist('Point', ['x', 'y']) + >>> Point.__doc__ # docstring for the new class + 'Point(x, y)' + >>> p = Point(11, y=22) # instantiate with pos args or keywords + >>> p[0] + p[1] # indexable like a plain list + 33 + >>> x, y = p # unpack like a regular list + >>> x, y + (11, 22) + >>> p.x + p.y # fields also accessible by name + 33 + >>> d = p._asdict() # convert to a dictionary + >>> d['x'] + 11 + >>> Point(**d) # convert from a dictionary + Point(x=11, y=22) + >>> p._replace(x=100) # _replace() is like str.replace() but targets named fields + Point(x=100, y=22) + """ + + # Validate the field names. At the user's option, either generate an error + # message or automatically replace the field name with a valid name. + if isinstance(field_names, basestring): + field_names = field_names.replace(',', ' ').split() + field_names = [str(x) for x in field_names] + if rename: + seen = set() + for index, name in enumerate(field_names): + if (not all(c.isalnum() or c == '_' for c in name) + or _iskeyword(name) + or not name + or name[0].isdigit() + or name.startswith('_') + or name in seen): + field_names[index] = '_%d' % index + seen.add(name) + for name in [typename] + field_names: + if not all(c.isalnum() or c == '_' for c in name): + raise ValueError('Type names and field names can only contain ' + 'alphanumeric characters and underscores: %r' + % name) + if _iskeyword(name): + raise ValueError('Type names and field names cannot be a ' + 'keyword: %r' % name) + if name[0].isdigit(): + raise ValueError('Type names and field names cannot start with ' + 'a number: %r' % name) + seen = set() + for name in field_names: + if name.startswith('_') and not rename: + raise ValueError('Field names cannot start with an underscore: ' + '%r' % name) + if name in seen: + raise ValueError('Encountered duplicate field name: %r' % name) + seen.add(name) + + # Fill-in the class template + fmt_kw = {'typename': typename} + fmt_kw['field_names'] = tuple(field_names) + fmt_kw['num_fields'] = len(field_names) + fmt_kw['arg_list'] = repr(tuple(field_names)).replace("'", "")[1:-1] + fmt_kw['repr_fmt'] = ', '.join(_repr_tmpl.format(name=name) + for name in field_names) + fmt_kw['field_defs'] = '\n'.join(_m_field_tmpl.format(index=index, name=name) + for index, name in enumerate(field_names)) + class_definition = _namedlist_tmpl.format(**fmt_kw) + + if verbose: + print(class_definition) + + def _itemsetter(key): + def _itemsetter(obj, value): + obj[key] = value + return _itemsetter + + # Execute the template string in a temporary namespace and support + # tracing utilities by setting a value for frame.f_globals['__name__'] + namespace = dict(_itemgetter=_itemgetter, + _itemsetter=_itemsetter, + __name__='namedlist_%s' % typename, + OrderedDict=OrderedDict, + _property=property, + _list=list) + try: + exec_(class_definition, namespace) + except SyntaxError as e: + raise SyntaxError(e.message + ':\n' + class_definition) + result = namespace[typename] + + # For pickling to work, the __module__ variable needs to be set to + # the frame where the named list is created. Bypass this step in + # environments where sys._getframe is not defined (Jython for + # example) or sys._getframe is not defined for arguments greater + # than 0 (IronPython). + try: + frame = _sys._getframe(1) + result.__module__ = frame.f_globals.get('__name__', '__main__') + except (AttributeError, ValueError): + pass + + return result