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 |
+ |