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