Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Turn constants into Enums #469

Closed
giampaolo opened this issue May 23, 2014 · 2 comments
Closed

Turn constants into Enums #469

giampaolo opened this issue May 23, 2014 · 2 comments

Comments

@giampaolo
Copy link
Owner

From g.rodola on January 23, 2014 22:39:11

Future Python 3.4 will include enums: http://www.python.org/dev/peps/pep-0435/ 
Long story short: all python constants in Python 3.4 now look like this:

>>> import socket
>>> socket.SOCK_STREAM
<SocketType.SOCK_STREAM: 1>
>>> 

That is a great step forward in terms of readability because in older Python 
version socket.SOCK_STREAM was just "1" and as such you couldn't immediately 
tell what that was while debugging:

python 2.7:

>>> import socket
>>> socket.socket()
<socket._socketobject object at 0x7f92d08598a0>

python 3.4:

>>> import socket
>>> socket.socket()
<socket.socket fd=3, family=AddressFamily.AF_INET, type=SocketType.SOCK_STREAM, 
proto=0, laddr=('0.0.0.0', 0)>


Same thing applies to psutil. We have different integer constants such as:

>>> psutil.RLIMIT_AS
9
>>> 

...which we could turn into enums so that they'll look like this:

>>> psutil.RLIMIT_AS
<ProcessLimit.RLIMIT_AS: 1>
>>>

For Python versions < 3.4 we can integrate enum.py module straight into 
psutil/_compat.py.

Note to self: figure out what to do with string constants (psutil.CONN_ and 
psutil.STATUS_).

Original issue: http://code.google.com/p/psutil/issues/detail?id=469

@giampaolo
Copy link
Owner Author

The following patch turns IOPRIO_CLASS_* and _PRIORITY_CLASS constants returned by psutil.Process.ionice() into enums. Still not sure whether it's the case to implement this because:

  • it adds a new ConstIOPriority public class in the psutil namespace
  • we should do the same for psutil.AF_LINK, meaning we need another public class / container
    diff --git a/psutil/__init__.py b/psutil/__init__.py
    index a08e645..292e5bb 100644
    --- a/psutil/__init__.py
    +++ b/psutil/__init__.py
    @@ -25,6 +25,10 @@ try:
         import pwd
     except ImportError:
         pwd = None
    +try:
    +    import enum
    +except ImportError:
    +    enum = None

     from ._common import memoize
     from ._compat import callable, long
    @@ -34,6 +38,7 @@ from ._common import (deprecated_method as _deprecated_method,
                           sdiskio as _nt_sys_diskio,
                           snetio as _nt_sys_netio,
                           snic as _nt_snic,
    +                      pionice as _nt_pionice,
                           )

     from ._common import (STATUS_RUNNING,  # NOQA
    @@ -71,6 +76,14 @@ if sys.platform.startswith("linux"):
                                IOPRIO_CLASS_RT,
                                IOPRIO_CLASS_BE,
                                IOPRIO_CLASS_IDLE)
    +
    +    if enum is not None:
    +        ConstIOPriority = enum.IntEnum(
    +            'ConstIOPriority',
    +            dict((name, value) for name, value in globals().items()
    +                 if name.startswith('IOPRIO_') and name.isupper()))
    +        globals().update(ConstIOPriority.__members__)
    +
         # Linux >= 2.6.36
         if _psplatform.HAS_PRLIMIT:
             from ._psutil_linux import (RLIM_INFINITY,  # NOQA
    @@ -111,6 +124,12 @@ if sys.platform.startswith("linux"):
                 pass
             del _psutil_linux

    +        # _RLimit = enum.IntEnum(
    +        #     '_RLimit',
    +        #     dict((name, value) for name, value in globals().items()
    +        #          if name.startswith('RLIM') and name.isupper()))
    +        # globals().update(_RLimit.__members__)
    +
     elif sys.platform.startswith("win32"):
         from . import _pswindows as _psplatform
         from ._psutil_windows import (ABOVE_NORMAL_PRIORITY_CLASS,  # NOQA
    @@ -119,6 +138,14 @@ elif sys.platform.startswith("win32"):
                                       IDLE_PRIORITY_CLASS,
                                       NORMAL_PRIORITY_CLASS,
                                       REALTIME_PRIORITY_CLASS)
    +
    +    if enum is not None:
    +        ConstIOPriority = enum.IntEnum(
    +            'ConstIOPriority',
    +            dict((name, value) for name, value in globals().items()
    +                 if name.endsswith('_PRIORITY_CLASS') and name.isupper()))
    +        globals().update(ConstIOPriority.__members__)
    +
         from ._pswindows import CONN_DELETE_TCB  # NOQA

     elif sys.platform.startswith("darwin"):
    @@ -665,7 +692,10 @@ class Process(object):
                 if ioclass is None:
                     if value is not None:
                         raise ValueError("'ioclass' must be specified")
    -                return self._proc.ionice_get()
    +                ioclass, value = self._proc.ionice_get()
    +                if enum is not None:
    +                    ioclass = ConstIOPriority(ioclass)
    +                return _nt_pionice(ioclass, value)
                 else:
                     return self._proc.ionice_set(ioclass, value)

    diff --git a/psutil/_pslinux.py b/psutil/_pslinux.py
    index c21d089..ec6495c 100644
    --- a/psutil/_pslinux.py
    +++ b/psutil/_pslinux.py
    @@ -973,8 +973,7 @@ class Process(object):

             @wrap_exceptions
             def ionice_get(self):
    -            ioclass, value = cext.proc_ioprio_get(self.pid)
    -            return _common.pionice(ioclass, value)
    +            return cext.proc_ioprio_get(self.pid)

             @wrap_exceptions
             def ionice_set(self, ioclass, value):
    diff --git a/test/test_psutil.py b/test/test_psutil.py
    index efbcead..8a73ac2 100644
    --- a/test/test_psutil.py
    +++ b/test/test_psutil.py
    @@ -46,6 +46,10 @@ try:
         import ipaddress  # python >= 3.3
     except ImportError:
         ipaddress = None
    +try:
    +    import enum  # python >= 3.4
    +except ImportError:
    +    enum = None

     try:
         import enum  # python >= 3.4
    @@ -1380,6 +1384,8 @@ class TestProcess(unittest.TestCase):
                 try:
                     p.ionice(2)
                     ioclass, value = p.ionice()
    +                if enum is not None:
    +                    self.assertIsInstance(ioclass, enum.IntEnum)
                     self.assertEqual(ioclass, 2)
                     self.assertEqual(value, 4)
                     #
    @@ -1432,6 +1438,8 @@ class TestProcess(unittest.TestCase):
                     self.assertEqual(len(ret), 2)
                     self.assertGreaterEqual(ret[0], -1)
                     self.assertGreaterEqual(ret[1], -1)
    +            if enum is not None:
    +                self.assertIsInstance(getattr(psutil, name), enum.IntEnum)

         @unittest.skipUnless(LINUX and RLIMIT_SUPPORT,
                              "only available on Linux >= 2.6.36")

@giampaolo
Copy link
Owner Author

For now I opted for converting IOPRIO_CLASS_* and *_PRIORITY_CLASS constants into enums on Python 3.4 only. enum might be installed as a third party dep on Python < 3.4 (see https://pypi.python.org/pypi/enum34/) but I decided not to assume that and explicitly ignore Python < 3.4 'cause the JSON module can't serialize those objects.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant