diff --git a/pyudev/_libudev.py b/pyudev/_libudev.py index efc27c9..7d97d35 100644 --- a/pyudev/_libudev.py +++ b/pyudev/_libudev.py @@ -284,6 +284,3 @@ def load_udev_library(): if errorchecker: func.errcheck = errorchecker return libudev - - -libudev = load_udev_library() diff --git a/pyudev/_util.py b/pyudev/_util.py index a99da08..c11b0b2 100644 --- a/pyudev/_util.py +++ b/pyudev/_util.py @@ -33,7 +33,6 @@ import os import sys import stat -from pyudev._libudev import libudev if sys.version_info[0] == 2: from pyudev._py2util import * @@ -101,7 +100,7 @@ def string_to_bool(value): return value == '1' -def udev_list_iterate(entry): +def udev_list_iterate(libudev, entry): """ Iteration helper for udev list entry objects. diff --git a/pyudev/core.py b/pyudev/core.py index 83d2c7c..5017d80 100644 --- a/pyudev/core.py +++ b/pyudev/core.py @@ -35,7 +35,7 @@ except ImportError: from pyudev._compat import check_output from pyudev.device import Device -from pyudev._libudev import libudev +from pyudev._libudev import load_udev_library from pyudev._util import (ensure_unicode_string, ensure_byte_string, udev_list_iterate, property_value_to_bytes) @@ -89,10 +89,11 @@ class Context(object): """ Create a new context. """ - self._as_parameter_ = libudev.udev_new() + self._libudev = load_udev_library() + self._as_parameter_ = self._libudev.udev_new() def __del__(self): - libudev.udev_unref(self) + self._libudev.udev_unref(self) @property def sys_path(self): @@ -102,7 +103,7 @@ class Context(object): The mount point can be overwritten using the environment variable :envvar:`SYSFS_PATH`. Use this for testing purposes. """ - return ensure_unicode_string(libudev.udev_get_sys_path(self)) + return ensure_unicode_string(self._libudev.udev_get_sys_path(self)) @property def device_path(self): @@ -111,7 +112,7 @@ class Context(object): This can be overridden in the udev configuration. """ - return ensure_unicode_string(libudev.udev_get_dev_path(self)) + return ensure_unicode_string(self._libudev.udev_get_dev_path(self)) @property def run_path(self): @@ -123,7 +124,7 @@ class Context(object): .. versionadded:: 0.10 """ - return ensure_unicode_string(libudev.udev_get_run_path(self)) + return ensure_unicode_string(self._libudev.udev_get_run_path(self)) @property def log_priority(self): @@ -142,11 +143,11 @@ class Context(object): .. versionadded:: 0.9 """ - return libudev.udev_get_log_priority(self) + return self._libudev.udev_get_log_priority(self) @log_priority.setter def log_priority(self, value): - libudev.udev_set_log_priority(self, value) + self._libudev.udev_set_log_priority(self, value) def list_devices(self, **kwargs): """ @@ -205,10 +206,11 @@ class Enumerator(object): if not isinstance(context, Context): raise TypeError('Invalid context object') self.context = context - self._as_parameter_ = libudev.udev_enumerate_new(context) + self._as_parameter_ = context._libudev.udev_enumerate_new(context) + self._libudev = context._libudev def __del__(self): - libudev.udev_enumerate_unref(self) + self._libudev.udev_enumerate_unref(self) def match(self, **kwargs): """ @@ -265,9 +267,9 @@ class Enumerator(object): Return the instance again. """ - match = (libudev.udev_enumerate_add_match_subsystem + match = (self._libudev.udev_enumerate_add_match_subsystem if not nomatch else - libudev.udev_enumerate_add_nomatch_subsystem) + self._libudev.udev_enumerate_add_nomatch_subsystem) match(self, ensure_byte_string(subsystem)) return self @@ -281,7 +283,7 @@ class Enumerator(object): .. versionadded:: 0.8 """ - libudev.udev_enumerate_add_match_sysname( + self._libudev.udev_enumerate_add_match_sysname( self, ensure_byte_string(sys_name)) return self @@ -301,7 +303,7 @@ class Enumerator(object): Return the instance again. """ - libudev.udev_enumerate_add_match_property( + self._libudev.udev_enumerate_add_match_property( self, ensure_byte_string(property), property_value_to_bytes(value)) return self @@ -332,9 +334,9 @@ class Enumerator(object): Return the instance again. """ - match = (libudev.udev_enumerate_add_match_sysattr + match = (self._libudev.udev_enumerate_add_match_sysattr if not nomatch else - libudev.udev_enumerate_add_nomatch_sysattr) + self._libudev.udev_enumerate_add_nomatch_sysattr) match(self, ensure_byte_string(attribute), property_value_to_bytes(value)) return self @@ -351,7 +353,7 @@ class Enumerator(object): .. versionadded:: 0.6 """ - libudev.udev_enumerate_add_match_tag(self, ensure_byte_string(tag)) + self._libudev.udev_enumerate_add_match_tag(self, ensure_byte_string(tag)) return self def match_is_initialized(self): @@ -372,7 +374,7 @@ class Enumerator(object): .. versionadded:: 0.8 """ - libudev.udev_enumerate_add_match_is_initialized(self) + self._libudev.udev_enumerate_add_match_is_initialized(self) return self def match_parent(self, parent): @@ -389,7 +391,7 @@ class Enumerator(object): .. versionadded:: 0.13 """ - libudev.udev_enumerate_add_match_parent(self, parent) + self._libudev.udev_enumerate_add_match_parent(self, parent) return self def __iter__(self): @@ -398,7 +400,7 @@ class Enumerator(object): Yield :class:`Device` objects. """ - libudev.udev_enumerate_scan_devices(self) - entry = libudev.udev_enumerate_get_list_entry(self) - for name, _ in udev_list_iterate(entry): + self._libudev.udev_enumerate_scan_devices(self) + entry = self._libudev.udev_enumerate_get_list_entry(self) + for name, _ in udev_list_iterate(self._libudev, entry): yield Device.from_sys_path(self.context, name) diff --git a/pyudev/device.py b/pyudev/device.py index f9a4325..d5ae3da 100644 --- a/pyudev/device.py +++ b/pyudev/device.py @@ -32,7 +32,6 @@ import os from collections import Mapping, Container, Iterable from datetime import timedelta -from pyudev._libudev import libudev from pyudev._util import (ensure_byte_string, ensure_unicode_string, udev_list_iterate, string_to_bool, get_device_type) @@ -219,7 +218,7 @@ class Device(Mapping): Raise :exc:`DeviceNotFoundAtPathError` instead of :exc:`NoSuchDeviceError` """ - device = libudev.udev_device_new_from_syspath( + device = context._libudev.udev_device_new_from_syspath( context, ensure_byte_string(sys_path)) if not device: raise DeviceNotFoundAtPathError(sys_path) @@ -247,7 +246,7 @@ class Device(Mapping): .. versionadded:: 0.5 """ - device = libudev.udev_device_new_from_subsystem_sysname( + device = context._libudev.udev_device_new_from_subsystem_sysname( context, ensure_byte_string(subsystem), ensure_byte_string(sys_name)) if not device: @@ -295,7 +294,7 @@ class Device(Mapping): if type not in ('char', 'block'): raise ValueError('Invalid type: {0!r}. Must be one of "char" ' 'or "block".'.format(type)) - device = libudev.udev_device_new_from_devnum( + device = context._libudev.udev_device_new_from_devnum( context, ensure_byte_string(type[0]), number) if not device: raise DeviceNotFoundByNumberError(type, number) @@ -360,7 +359,7 @@ class Device(Mapping): .. versionadded:: 0.6 """ - device = libudev.udev_device_new_from_environment(context) + device = context._libudev.udev_device_new_from_environment(context) if not device: raise DeviceNotFoundInEnvironmentError() return cls(context, device) @@ -368,9 +367,10 @@ class Device(Mapping): def __init__(self, context, _device): self.context = context self._as_parameter_ = _device + self._libudev = context._libudev def __del__(self): - libudev.udev_device_unref(self) + self._libudev.udev_device_unref(self) def __repr__(self): return 'Device({0.sys_path!r})'.format(self) @@ -381,12 +381,12 @@ class Device(Mapping): The parent :class:`Device` or ``None``, if there is no parent device. """ - parent = libudev.udev_device_get_parent(self) + parent = self._libudev.udev_device_get_parent(self) if not parent: return None # the parent device is not referenced, thus forcibly acquire a # reference - return Device(self.context, libudev.udev_device_ref(parent)) + return Device(self.context, self._libudev.udev_device_ref(parent)) @property def children(self): @@ -432,12 +432,12 @@ class Device(Mapping): subsystem = ensure_byte_string(subsystem) if device_type is not None: device_type = ensure_byte_string(device_type) - parent = libudev.udev_device_get_parent_with_subsystem_devtype( + parent = self._libudev.udev_device_get_parent_with_subsystem_devtype( self, subsystem, device_type) if not parent: return None # parent device is not referenced, thus forcibly acquire a reference - return Device(self.context, libudev.udev_device_ref(parent)) + return Device(self.context, self._libudev.udev_device_ref(parent)) def traverse(self): """ @@ -458,7 +458,8 @@ class Device(Mapping): Absolute path of this device in ``sysfs`` including the ``sysfs`` mount point as unicode string. """ - return ensure_unicode_string(libudev.udev_device_get_syspath(self)) + return ensure_unicode_string( + self._libudev.udev_device_get_syspath(self)) @property def device_path(self): @@ -470,21 +471,24 @@ class Device(Mapping): mount point. However, the path is absolute and starts with a slash ``'/'``. """ - return ensure_unicode_string(libudev.udev_device_get_devpath(self)) + return ensure_unicode_string( + self._libudev.udev_device_get_devpath(self)) @property def subsystem(self): """ Name of the subsystem this device is part of as unicode string. """ - return ensure_unicode_string(libudev.udev_device_get_subsystem(self)) + return ensure_unicode_string( + self._libudev.udev_device_get_subsystem(self)) @property def sys_name(self): """ Device file name inside ``sysfs`` as unicode string. """ - return ensure_unicode_string(libudev.udev_device_get_sysname(self)) + return ensure_unicode_string( + self._libudev.udev_device_get_sysname(self)) @property def sys_number(self): @@ -508,7 +512,7 @@ class Device(Mapping): .. versionadded:: 0.11 """ - number = libudev.udev_device_get_sysnum(self) + number = self._libudev.udev_device_get_sysnum(self) if number is not None: return ensure_unicode_string(number) @@ -529,7 +533,7 @@ class Device(Mapping): .. versionadded:: 0.10 """ - device_type = libudev.udev_device_get_devtype(self) + device_type = self._libudev.udev_device_get_devtype(self) if device_type is not None: return ensure_unicode_string(device_type) @@ -541,7 +545,7 @@ class Device(Mapping): .. versionadded:: 0.5 """ - driver = libudev.udev_device_get_driver(self) + driver = self._libudev.udev_device_get_driver(self) if driver: return ensure_unicode_string(driver) @@ -563,7 +567,7 @@ class Device(Mapping): this property is not necessary equal to the ``filename`` given to :meth:`from_device_file()`. """ - node = libudev.udev_device_get_devnode(self) + node = self._libudev.udev_device_get_devnode(self) if node: return ensure_unicode_string(node) @@ -591,7 +595,7 @@ class Device(Mapping): .. versionadded:: 0.11 """ - return libudev.udev_device_get_devnum(self) + return self._libudev.udev_device_get_devnum(self) @property def is_initialized(self): @@ -614,7 +618,7 @@ class Device(Mapping): .. versionadded:: 0.8 """ - return bool(libudev.udev_device_get_is_initialized(self)) + return bool(self._libudev.udev_device_get_is_initialized(self)) @property def time_since_initialized(self): @@ -631,7 +635,8 @@ class Device(Mapping): .. versionadded:: 0.8 """ - microseconds = libudev.udev_device_get_usec_since_initialized(self) + microseconds = self._libudev.udev_device_get_usec_since_initialized( + self) return timedelta(microseconds=microseconds) @property @@ -650,8 +655,8 @@ class Device(Mapping): The property provides access to all such symbolic links, which were created by UDev for this device. """ - devlinks = libudev.udev_device_get_devlinks_list_entry(self) - for name, _ in udev_list_iterate(devlinks): + devlinks = self._libudev.udev_device_get_devlinks_list_entry(self) + for name, _ in udev_list_iterate(self._libudev, devlinks): yield ensure_unicode_string(name) @property @@ -713,19 +718,16 @@ class Device(Mapping): Return a generator yielding the names of all properties of this device as unicode strings. """ - properties = libudev.udev_device_get_properties_list_entry(self) - for name, _ in udev_list_iterate(properties): + properties = self._libudev.udev_device_get_properties_list_entry(self) + for name, _ in udev_list_iterate(self._libudev, properties): yield ensure_unicode_string(name) def __len__(self): """ Return the amount of properties defined for this device as integer. """ - properties = libudev.udev_device_get_properties_list_entry(self) - i = 0 - for i, _ in enumerate(udev_list_iterate(properties), start=1): - pass - return i + properties = self._libudev.udev_device_get_properties_list_entry(self) + return sum(1 for _ in udev_list_iterate(self._libudev, properties)) def __getitem__(self, property): """ @@ -738,7 +740,7 @@ class Device(Mapping): :exc:`~exceptions.KeyError`, if the given property is not defined for this device. """ - value = libudev.udev_device_get_property_value( + value = self._libudev.udev_device_get_property_value( self, ensure_byte_string(property)) if value is None: raise KeyError(property) @@ -814,14 +816,17 @@ class Tags(Iterable, Container): def __init__(self, device): self.device = device - if hasattr(libudev, 'udev_device_has_tag'): - def _has_tag(self, tag): - return bool(libudev.udev_device_has_tag( + def _has_tag(self, tag): + if hasattr(self._libudev, 'udev_device_has_tag'): + return bool(self._libudev.udev_device_has_tag( self.device, ensure_byte_string(tag))) - else: - def _has_tag(self, tag): + else: return any(t == tag for t in self) + @property + def _libudev(self): + return self.device._libudev + def __contains__(self, tag): """ Check for existence of ``tag``. @@ -839,8 +844,8 @@ class Tags(Iterable, Container): Yield each tag as unicode string. """ - tags = libudev.udev_device_get_tags_list_entry(self.device) - for tag, _ in udev_list_iterate(tags): + tags = self._libudev.udev_device_get_tags_list_entry(self.device) + for tag, _ in udev_list_iterate(self._libudev, tags): yield ensure_unicode_string(tag) @@ -876,29 +881,26 @@ class Attributes(Mapping): def __init__(self, device): self.device = device + self._libudev = device._libudev - if hasattr(libudev, 'udev_device_get_sysattr_list_entry'): - @property - def _attributes(self): - attrs = libudev.udev_device_get_sysattr_list_entry(self.device) - for attribute, _ in udev_list_iterate(attrs): + def _get_attributes(self): + if hasattr(self._libudev, 'udev_device_get_sysattr_list_entry'): + attrs = self._libudev.udev_device_get_sysattr_list_entry( + self.device) + for attribute, _ in udev_list_iterate(self._libudev, attrs): yield ensure_unicode_string(attribute) - else: - @property - def _attributes(self): + else: sys_path = self.device.sys_path - return (fn for fn in os.listdir(sys_path) if - _is_attribute_file(os.path.join(sys_path, fn)) and - fn in self) + for filename in os.listdir(sys_path): + filepath = os.path.join(sys_path, filename) + if _is_attribute_file(filepath): + yield filename def __len__(self): """ Return the amount of attributes defined. """ - i = 0 - for i, _ in enumerate(self._attributes, start=1): - pass - return i + return sum(1 for _ in self._get_attributes()) def __iter__(self): """ @@ -906,10 +908,10 @@ class Attributes(Mapping): Yield each attribute name as unicode string. """ - return self._attributes + return self._get_attributes() def __contains__(self, attribute): - value = libudev.udev_device_get_sysattr_value( + value = self._libudev.udev_device_get_sysattr_value( self.device, ensure_byte_string(attribute)) return value is not None @@ -924,7 +926,7 @@ class Attributes(Mapping): :exc:`~exceptions.KeyError`, if the given attribute is not defined for this device. """ - value = libudev.udev_device_get_sysattr_value( + value = self._libudev.udev_device_get_sysattr_value( self.device, ensure_byte_string(attribute)) if value is None: raise KeyError(attribute) diff --git a/pyudev/monitor.py b/pyudev/monitor.py index 8153ecc..6a51564 100644 --- a/pyudev/monitor.py +++ b/pyudev/monitor.py @@ -36,7 +36,6 @@ import select from threading import Thread from contextlib import closing -from pyudev._libudev import libudev from pyudev._util import ensure_byte_string, ensure_unicode_string, reraise from pyudev.core import Device @@ -82,6 +81,7 @@ class Monitor(object): self.context = context self._as_parameter_ = monitor_p self._socket_path = socket_path + self._libudev = context._libudev def _reraise_with_socket_path(self): _, exc_value, traceback = sys.exc_info() @@ -89,7 +89,7 @@ class Monitor(object): reraise(exc_value, traceback) def __del__(self): - libudev.udev_monitor_unref(self) + self._libudev.udev_monitor_unref(self) @classmethod def from_netlink(cls, context, source='udev'): @@ -117,7 +117,7 @@ class Monitor(object): if source not in ('kernel', 'udev'): raise ValueError('Invalid source: {0!r}. Must be one of "udev" ' 'or "kernel"'.format(source)) - monitor = libudev.udev_monitor_new_from_netlink( + monitor = context._libudev.udev_monitor_new_from_netlink( context, ensure_byte_string(source)) if not monitor: raise EnvironmentError('Could not create udev monitor') @@ -140,7 +140,7 @@ class Monitor(object): socket. Raise :exc:`~exceptions.EnvironmentError`, if the creation of the monitor failed. """ - monitor = libudev.udev_monitor_new_from_socket( + monitor = context._libudev.udev_monitor_new_from_socket( context, ensure_byte_string(socket_path)) if not monitor: raise EnvironmentError('Could not create monitor for socket: ' @@ -154,7 +154,7 @@ class Monitor(object): This is really a real file descriptor ;), which can be watched and :func:`select.select`\ ed. """ - return libudev.udev_monitor_get_fd(self) + return self._libudev.udev_monitor_get_fd(self) def filter_by(self, subsystem, device_type=None): """ @@ -179,9 +179,9 @@ class Monitor(object): subsystem = ensure_byte_string(subsystem) if device_type: device_type = ensure_byte_string(device_type) - libudev.udev_monitor_filter_add_match_subsystem_devtype( + self._libudev.udev_monitor_filter_add_match_subsystem_devtype( self, subsystem, device_type) - libudev.udev_monitor_filter_update(self) + self._libudev.udev_monitor_filter_update(self) def filter_by_tag(self, tag): """ @@ -202,9 +202,9 @@ class Monitor(object): .. versionchanged:: 0.15 This method can also be after :meth:`enable_receiving()` now """ - libudev.udev_monitor_filter_add_match_tag( + self._libudev.udev_monitor_filter_add_match_tag( self, ensure_byte_string(tag)) - libudev.udev_monitor_filter_update(self) + self._libudev.udev_monitor_filter_update(self) def remove_filter(self): """ @@ -223,8 +223,8 @@ class Monitor(object): .. versionadded:: 0.15 """ - libudev.udev_monitor_filter_remove(self) - libudev.udev_monitor_filter_update(self) + self._libudev.udev_monitor_filter_remove(self) + self._libudev.udev_monitor_filter_update(self) def enable_receiving(self): """ @@ -240,7 +240,7 @@ class Monitor(object): monitor. """ try: - libudev.udev_monitor_enable_receiving(self) + self._libudev.udev_monitor_enable_receiving(self) except EnvironmentError: self._reraise_with_socket_path() @@ -272,7 +272,7 @@ class Monitor(object): .. _python-prctl: http://packages.python.org/python-prctl """ try: - libudev.udev_monitor_set_receive_buffer_size(self, size) + self._libudev.udev_monitor_set_receive_buffer_size(self, size) except EnvironmentError: self._reraise_with_socket_path() @@ -301,13 +301,13 @@ class Monitor(object): read. """ try: - device_p = libudev.udev_monitor_receive_device(self) + device_p = self._libudev.udev_monitor_receive_device(self) except EnvironmentError: self._reraise_with_socket_path() if not device_p: raise EnvironmentError('Could not receive device') action = ensure_unicode_string( - libudev.udev_device_get_action(device_p)) + self._libudev.udev_device_get_action(device_p)) return action, Device(self.context, device_p) def __iter__(self):