Skip to content

Commit

Permalink
setup: static modules loader
Browse files Browse the repository at this point in the history
Use the static code instead of entry points

Bug-Url: #1076
  • Loading branch information
svinota committed Mar 14, 2023
1 parent e96f3ad commit a012696
Show file tree
Hide file tree
Showing 4 changed files with 221 additions and 124 deletions.
10 changes: 8 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,16 @@ dist: setup

.PHONY: dist-minimal
dist-minimal: setup
mv -f setup.cfg setup.cfg.orig
cp setup.minimal.cfg setup.cfg
# backup original files
mv -f setup.cfg .setup.cfg.orig
mv -f pyroute2/__init__.py .init.py.orig
# replace with the minimal package
cp -f setup.minimal.cfg setup.cfg
cp -f pyroute2/minimal.py pyroute2/__init__.py
$(call nox,-e build)
# restore the original files
mv -f setup.cfg.orig setup.cfg
mv -f .init.py.orig pyroute2/__init__.py

.PHONY: install
install: setup
Expand Down
219 changes: 97 additions & 122 deletions pyroute2/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@
#
# This module contains all the public symbols from the library.
#
import importlib
import struct
import sys

##
#
Expand All @@ -15,124 +12,102 @@
except ImportError:
__version__ = 'unknown'

##
#
# Windows platform specific: socket module monkey patching
#
# To use the library on Windows, run::
# pip install win-inet-pton
#
if sys.platform.startswith('win'): # noqa: E402
import win_inet_pton # noqa: F401

##
##
#
#
# Logging setup
#
# See the history:
# * https://github.com/svinota/pyroute2/issues/246
# * https://github.com/svinota/pyroute2/issues/255
# * https://github.com/svinota/pyroute2/issues/270
# * https://github.com/svinota/pyroute2/issues/573
# * https://github.com/svinota/pyroute2/issues/601
#
from pyroute2.config import entry_points_aliases, log

#
#
try:
from importlib import metadata
except ImportError:
import importlib_metadata as metadata


try:
# probe, if the bytearray can be used in struct.unpack_from()
struct.unpack_from('I', bytearray((1, 0, 0, 0)), 0)
except Exception:
if sys.version_info[0] < 3:
# monkeypatch for old Python versions
log.warning('patching struct.unpack_from()')

def wrapped(fmt, buf, offset=0):
return struct._u_f_orig(fmt, str(buf), offset)

struct._u_f_orig = struct.unpack_from
struct.unpack_from = wrapped
else:
raise


# load entry_points
modules = []
namespace_inject = {}
groups = metadata.entry_points()
if hasattr(groups, 'select'):
pyroute2_group = groups.select(group='pyroute2')
else:
pyroute2_group = groups.get('pyroute2', [])
for entry_point in pyroute2_group:
try:
loaded = entry_point.load()
except ImportError:
if not sys.platform.startswith('win'):
raise
continue
modules.append(entry_point.name)
if len(entry_point.value.split(':')) == 1:
key = 'pyroute2.%s' % entry_point.name
namespace_inject[key] = loaded
else:
globals()[entry_point.name] = loaded

from pyroute2 import loader
from pyroute2.cli.console import Console
from pyroute2.cli.server import Server
from pyroute2.conntrack import Conntrack, ConntrackEntry
from pyroute2.devlink import DL
from pyroute2.ethtool.ethtool import Ethtool
from pyroute2.ipdb.exceptions import (
CommitException,
CreateException,
DeprecationException,
PartialCommitException,
)
from pyroute2.ipdb.main import IPDB
from pyroute2.iproute import ChaoticIPRoute, IPBatch, IPRoute, RawIPRoute
from pyroute2.iproute.ipmock import IPRoute as IPMock
from pyroute2.ipset import IPSet
from pyroute2.iwutil import IW
from pyroute2.ndb.main import NDB
from pyroute2.ndb.noipdb import NoIPDB
from pyroute2.netlink.connector.cn_proc import ProcEventSocket
from pyroute2.netlink.devlink import DevlinkSocket
from pyroute2.netlink.diag import DiagSocket, ss2
from pyroute2.netlink.event.acpi_event import AcpiEventSocket
from pyroute2.netlink.event.dquot import DQuotSocket
from pyroute2.netlink.exceptions import (
ChaoticException,
NetlinkDecodeError,
NetlinkDumpInterrupted,
NetlinkError,
)
from pyroute2.netlink.generic import GenericNetlinkSocket
from pyroute2.netlink.generic.l2tp import L2tp
from pyroute2.netlink.generic.mptcp import MPTCP
from pyroute2.netlink.generic.wireguard import WireGuard
from pyroute2.netlink.ipq import IPQSocket
from pyroute2.netlink.nfnetlink.nfctsocket import NFCTSocket
from pyroute2.netlink.nfnetlink.nftsocket import NFTSocket
from pyroute2.netlink.nl80211 import NL80211
from pyroute2.netlink.rtnl.iprsocket import IPRSocket
from pyroute2.netlink.taskstats import TaskStats
from pyroute2.netlink.uevent import UeventSocket
from pyroute2.nslink.nslink import NetNS
from pyroute2.nslink.nspopen import NSPopen
from pyroute2.remote import RemoteIPRoute
from pyroute2.remote.transport import RemoteSocket
from pyroute2.wiset import WiSet

modules = [
AcpiEventSocket,
ChaoticException,
ChaoticIPRoute,
CommitException,
Conntrack,
ConntrackEntry,
Console,
CreateException,
DeprecationException,
DevlinkSocket,
DiagSocket,
DL,
DQuotSocket,
Ethtool,
IPBatch,
IPDB,
IPMock,
IPQSocket,
IPRoute,
IPRSocket,
IPSet,
IW,
GenericNetlinkSocket,
L2tp,
MPTCP,
NDB,
NetlinkError,
NetlinkDecodeError,
NetlinkDumpInterrupted,
NetNS,
NFCTSocket,
NFTSocket,
NL80211,
NoIPDB,
NSPopen,
PartialCommitException,
ProcEventSocket,
RawIPRoute,
RemoteIPRoute,
RemoteSocket,
Server,
ss2,
TaskStats,
UeventSocket,
WireGuard,
WiSet,
]

loader.init()
__all__ = []
__all__.extend(modules)

# alias exceptions
for key, value in entry_points_aliases.items():
if key in sys.modules:
sys.modules[value] = sys.modules[key]


class PyRoute2ModuleSpec(importlib.machinery.ModuleSpec):
def __init__(
self,
name,
loader,
*argv,
origin=None,
loader_state=None,
is_package=None
):
self.name = name
self.loader = loader
self.origin = None
self.submodule_search_locations = None
self.loader_state = None
self.cached = None
self.has_location = False


class PyRoute2ModuleFinder(importlib.abc.MetaPathFinder):
@staticmethod
def find_spec(fullname, path, target=None):
if target is not None:
return None
if fullname not in namespace_inject:
return None
return PyRoute2ModuleSpec(fullname, PyRoute2ModuleFinder)

@staticmethod
def create_module(spec):
if spec.name not in namespace_inject:
return None
return namespace_inject[spec.name]

@staticmethod
def exec_module(spec):
pass


sys.meta_path.append(PyRoute2ModuleFinder())
43 changes: 43 additions & 0 deletions pyroute2/loader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import struct
import sys

##
#
# Logging setup
#
# See the history:
# * https://github.com/svinota/pyroute2/issues/246
# * https://github.com/svinota/pyroute2/issues/255
# * https://github.com/svinota/pyroute2/issues/270
# * https://github.com/svinota/pyroute2/issues/573
# * https://github.com/svinota/pyroute2/issues/601
#
from pyroute2.config import log

##
#
# Windows platform specific: socket module monkey patching
#
# To use the library on Windows, run::
# pip install win-inet-pton
#
if sys.platform.startswith('win'): # noqa: E402
import win_inet_pton # noqa: F401


def init():
try:
# probe, if the bytearray can be used in struct.unpack_from()
struct.unpack_from('I', bytearray((1, 0, 0, 0)), 0)
except Exception:
if sys.version_info[0] < 3:
# monkeypatch for old Python versions
log.warning('patching struct.unpack_from()')

def wrapped(fmt, buf, offset=0):
return struct._u_f_orig(fmt, str(buf), offset)

struct._u_f_orig = struct.unpack_from
struct.unpack_from = wrapped
else:
raise
73 changes: 73 additions & 0 deletions pyroute2/minimal.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
##
#
# This module contains all the public symbols from the library.
#

##
#
# Version
#
try:
from pyroute2.config.version import __version__
except ImportError:
__version__ = 'unknown'


from pyroute2.conntrack import Conntrack, ConntrackEntry
from pyroute2.iproute import ChaoticIPRoute, IPBatch, IPRoute, RawIPRoute
from pyroute2.iproute.ipmock import IPRoute as IPMock
from pyroute2.iwutil import IW
from pyroute2.netlink.devlink import DevlinkSocket
from pyroute2.netlink.diag import DiagSocket
from pyroute2.netlink.event.acpi_event import AcpiEventSocket
from pyroute2.netlink.event.dquot import DQuotSocket
from pyroute2.netlink.exceptions import (
ChaoticException,
NetlinkDecodeError,
NetlinkDumpInterrupted,
NetlinkError,
)
from pyroute2.netlink.generic import GenericNetlinkSocket
from pyroute2.netlink.generic.l2tp import L2tp
from pyroute2.netlink.generic.mptcp import MPTCP
from pyroute2.netlink.generic.wireguard import WireGuard
from pyroute2.netlink.ipq import IPQSocket
from pyroute2.netlink.nfnetlink.nfctsocket import NFCTSocket
from pyroute2.netlink.nfnetlink.nftsocket import NFTSocket
from pyroute2.netlink.nl80211 import NL80211
from pyroute2.netlink.rtnl.iprsocket import IPRSocket
from pyroute2.netlink.taskstats import TaskStats
from pyroute2.netlink.uevent import UeventSocket

modules = [
AcpiEventSocket,
ChaoticException,
ChaoticIPRoute,
Conntrack,
ConntrackEntry,
DevlinkSocket,
DiagSocket,
DQuotSocket,
IPBatch,
IPMock,
IPQSocket,
IPRoute,
IPRSocket,
IW,
GenericNetlinkSocket,
L2tp,
MPTCP,
NetlinkError,
NetlinkDecodeError,
NetlinkDumpInterrupted,
NFCTSocket,
NFTSocket,
NL80211,
RawIPRoute,
TaskStats,
UeventSocket,
WireGuard,
]

__all__ = []
__all__.extend(modules)

0 comments on commit a012696

Please sign in to comment.