| Index: third_party/psutil/psutil/_compat.py
|
| diff --git a/third_party/psutil/psutil/_compat.py b/third_party/psutil/psutil/_compat.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..1cac8b7b6721ba99366945ac441761325e25f38f
|
| --- /dev/null
|
| +++ b/third_party/psutil/psutil/_compat.py
|
| @@ -0,0 +1,154 @@
|
| +#!/usr/bin/env python
|
| +#
|
| +# $Id: _compat.py 1142 2011-10-05 18:45:49Z g.rodola $
|
| +#
|
| +# Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
|
| +# Use of this source code is governed by a BSD-style license that can be
|
| +# found in the LICENSE file.
|
| +
|
| +"""Module which provides compatibility with older Python versions."""
|
| +
|
| +__all__ = ["namedtuple", "property"]
|
| +
|
| +from operator import itemgetter as _itemgetter
|
| +from keyword import iskeyword as _iskeyword
|
| +import sys as _sys
|
| +import __builtin__
|
| +
|
| +try:
|
| + from collections import namedtuple
|
| +except ImportError:
|
| + def namedtuple(typename, field_names, verbose=False, rename=False):
|
| + """A collections.namedtuple implementation written in Python
|
| + to support Python versions < 2.6.
|
| +
|
| + Taken from: http://code.activestate.com/recipes/500261/
|
| + """
|
| + # Parse and validate the field names. Validation serves two
|
| + # purposes, generating informative error messages and preventing
|
| + # template injection attacks.
|
| + if isinstance(field_names, basestring):
|
| + # names separated by whitespace and/or commas
|
| + field_names = field_names.replace(',', ' ').split()
|
| + field_names = tuple(map(str, field_names))
|
| + if rename:
|
| + names = list(field_names)
|
| + seen = set()
|
| + for i, name in enumerate(names):
|
| + if (not min(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):
|
| + names[i] = '_%d' % i
|
| + seen.add(name)
|
| + field_names = tuple(names)
|
| + for name in (typename,) + field_names:
|
| + if not min(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_names = 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_names:
|
| + raise ValueError('Encountered duplicate field name: %r' % name)
|
| + seen_names.add(name)
|
| +
|
| + # Create and fill-in the class template
|
| + numfields = len(field_names)
|
| + # tuple repr without parens or quotes
|
| + argtxt = repr(field_names).replace("'", "")[1:-1]
|
| + reprtxt = ', '.join('%s=%%r' % name for name in field_names)
|
| + template = '''class %(typename)s(tuple):
|
| + '%(typename)s(%(argtxt)s)' \n
|
| + __slots__ = () \n
|
| + _fields = %(field_names)r \n
|
| + def __new__(_cls, %(argtxt)s):
|
| + return _tuple.__new__(_cls, (%(argtxt)s)) \n
|
| + @classmethod
|
| + def _make(cls, iterable, new=tuple.__new__, len=len):
|
| + 'Make a new %(typename)s object from a sequence or iterable'
|
| + result = new(cls, iterable)
|
| + if len(result) != %(numfields)d:
|
| + raise TypeError('Expected %(numfields)d arguments, got %%d' %% len(result))
|
| + return result \n
|
| + def __repr__(self):
|
| + return '%(typename)s(%(reprtxt)s)' %% self \n
|
| + def _asdict(self):
|
| + 'Return a new dict which maps field names to their values'
|
| + return dict(zip(self._fields, self)) \n
|
| + def _replace(_self, **kwds):
|
| + 'Return a new %(typename)s object replacing specified fields 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 \n
|
| + def __getnewargs__(self):
|
| + return tuple(self) \n\n''' % locals()
|
| + for i, name in enumerate(field_names):
|
| + template += ' %s = _property(_itemgetter(%d))\n' % (name, i)
|
| + if verbose:
|
| + print template
|
| +
|
| + # Execute the template string in a temporary namespace
|
| + namespace = dict(_itemgetter=_itemgetter, __name__='namedtuple_%s' % typename,
|
| + _property=property, _tuple=tuple)
|
| + try:
|
| + exec template in namespace
|
| + except SyntaxError, e:
|
| + raise SyntaxError(e.message + ':\n' + template)
|
| + 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 enviroments where sys._getframe is not defined (Jython
|
| + # for example) or sys._getframe is not defined for arguments
|
| + # greater than 0 (IronPython).
|
| + try:
|
| + result.__module__ = _sys._getframe(1).f_globals.get('__name__', '__main__')
|
| + except (AttributeError, ValueError):
|
| + pass
|
| +
|
| + return result
|
| +
|
| +
|
| +# dirty hack to support property.setter on python < 2.6
|
| +property = property
|
| +
|
| +if not hasattr(property, "setter"):
|
| +
|
| + class property(property):
|
| +
|
| + def __init__(self, fget, *args, **kwargs):
|
| + self.__doc__ = fget.__doc__
|
| + super(property, self).__init__(fget, *args, **kwargs)
|
| +
|
| + def setter(self, fset):
|
| + cls_ns = _sys._getframe(1).f_locals
|
| + for k, v in cls_ns.iteritems():
|
| + if v == self:
|
| + propname = k
|
| + break
|
| + cls_ns[propname] = property(self.fget, fset,
|
| + self.fdel, self.__doc__)
|
| + return cls_ns[propname]
|
| +
|
| + def deleter(self, fdel):
|
| + cls_ns = _sys._getframe(1).f_locals
|
| + for k, v in cls_ns.iteritems():
|
| + if v == self:
|
| + propname = k
|
| + break
|
| + cls_ns[propname] = property(self.fget, self.fset,
|
| + fdel, self.__doc__)
|
| + return cls_ns[propname]
|
| +
|
| + __builtin__.property = property
|
| +
|
|
|