Skip to content

Commit ebeb8a7

Browse files
authored
Merge pull request #79 from oremanj/packagify
Make netfilterqueue a package and add type hints
2 parents a935aad + e1e20d4 commit ebeb8a7

13 files changed

+148
-49
lines changed

CHANGES.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
v1.0.0, unreleased
22
Propagate exceptions raised by the user's packet callback
3-
Warn about exceptions raised by the packet callback during queue unbinding
3+
Avoid calls to the packet callback during queue unbinding
44
Raise an error if a packet verdict is set after its parent queue is closed
55
set_payload() now affects the result of later get_payload()
66
Handle signals received when run() is blocked in recv()
77
Accept packets in COPY_META mode, only failing on an attempt to access the payload
88
Add a parameter NetfilterQueue(sockfd=N) that uses an already-opened Netlink socket
9+
Add type hints
10+
Remove the Packet.payload attribute; it was never safe (treated as a char* but not NUL-terminated) nor documented, but was exposed in the API (perhaps inadvertently).
911

1012
v0.9.0, 12 Jan 2021
1113
Improve usability when Packet objects are retained past the callback

MANIFEST.in

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
include *.txt
2-
include *.rst
3-
include *.c
4-
include *.pyx
5-
include *.pxd
6-
recursive-include tests/ *.py
1+
include LICENSE.txt README.rst CHANGES.txt
2+
recursive-include netfilterqueue *.py *.pyx *.pxd *.c *.pyi py.typed
3+
recursive-include tests *.py

ci.sh

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,34 +11,42 @@ python setup.py sdist --formats=zip
1111

1212
# ... but not to install it
1313
pip uninstall -y cython
14+
python setup.py build_ext
1415
pip install dist/*.zip
1516

1617
pip install -Ur test-requirements.txt
1718

1819
if [ "$CHECK_LINT" = "1" ]; then
1920
error=0
20-
if ! black --check setup.py tests; then
21+
black_files="setup.py tests netfilterqueue"
22+
if ! black --check $black_files; then
23+
error=$?
24+
black --diff $black_files
25+
fi
26+
mypy --strict -p netfilterqueue || error=$?
27+
( mkdir empty; cd empty; python -m mypy.stubtest netfilterqueue ) || error=$?
28+
29+
if [ $error -ne 0 ]; then
2130
cat <<EOF
2231
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2332
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2433
25-
Formatting problems were found (listed above). To fix them, run
34+
Problems were found by static analysis (listed above).
35+
To fix formatting and see remaining errors, run:
2636
2737
pip install -r test-requirements.txt
28-
black setup.py tests
38+
black $black_files
39+
mypy --strict -p netfilterqueue
40+
( mkdir empty; cd empty; python -m mypy.stubtest netfilterqueue )
2941
3042
in your local checkout.
3143
32-
EOF
33-
error=1
34-
fi
35-
if [ "$error" = "1" ]; then
36-
cat <<EOF
3744
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3845
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3946
EOF
47+
exit 1
4048
fi
41-
exit $error
49+
exit 0
4250
fi
4351

4452
cd tests

netfilterqueue/__init__.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from ._impl import (
2+
COPY_NONE as COPY_NONE,
3+
COPY_META as COPY_META,
4+
COPY_PACKET as COPY_PACKET,
5+
Packet as Packet,
6+
NetfilterQueue as NetfilterQueue,
7+
PROTOCOLS as PROTOCOLS,
8+
)
9+
from ._version import (
10+
VERSION as VERSION,
11+
__version__ as __version__,
12+
)

netfilterqueue.pxd renamed to netfilterqueue/_impl.pxd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ cdef class Packet:
201201

202202
# Packet details:
203203
cdef Py_ssize_t payload_len
204-
cdef readonly unsigned char *payload
204+
cdef unsigned char *payload
205205
cdef timeval timestamp
206206
cdef u_int8_t hw_addr[8]
207207

netfilterqueue/_impl.pyi

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import socket
2+
from enum import IntEnum
3+
from typing import Callable, Dict, Optional, Tuple
4+
5+
COPY_NONE: int
6+
COPY_META: int
7+
COPY_PACKET: int
8+
9+
class Packet:
10+
hook: int
11+
hw_protocol: int
12+
id: int
13+
mark: int
14+
def get_hw(self) -> Optional[bytes]: ...
15+
def get_payload(self) -> bytes: ...
16+
def get_payload_len(self) -> int: ...
17+
def get_timestamp(self) -> float: ...
18+
def get_mark(self) -> int: ...
19+
def set_payload(self, payload: bytes) -> None: ...
20+
def set_mark(self, mark: int) -> None: ...
21+
def retain(self) -> None: ...
22+
def accept(self) -> None: ...
23+
def drop(self) -> None: ...
24+
def repeat(self) -> None: ...
25+
26+
class NetfilterQueue:
27+
def __new__(self, *, af: int = ..., sockfd: int = ...) -> NetfilterQueue: ...
28+
def bind(
29+
self,
30+
queue_num: int,
31+
user_callback: Callable[[Packet], None],
32+
max_len: int = ...,
33+
mode: int = COPY_PACKET,
34+
range: int = ...,
35+
sock_len: int = ...,
36+
) -> None: ...
37+
def unbind(self) -> None: ...
38+
def get_fd(self) -> int: ...
39+
def run(self, block: bool = ...) -> None: ...
40+
def run_socket(self, s: socket.socket) -> None: ...
41+
42+
PROTOCOLS: Dict[int, str]

netfilterqueue.pyx renamed to netfilterqueue/_impl.pyx

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ function.
55
Copyright: (c) 2011, Kerkhoff Technologies Inc.
66
License: MIT; see LICENSE.txt
77
"""
8-
VERSION = (0, 9, 0)
98

109
# Constants for module users
1110
COPY_NONE = 0
@@ -26,6 +25,10 @@ DEF SockRcvSize = DEFAULT_MAX_QUEUELEN * SockCopySize // 2
2625

2726
from cpython.exc cimport PyErr_CheckSignals
2827

28+
cdef extern from "Python.h":
29+
ctypedef struct PyTypeObject:
30+
const char* tp_name
31+
2932
# A negative return value from this callback will stop processing and
3033
# make nfq_handle_packet return -1, so we use that as the error flag.
3134
cdef int global_callback(nfq_q_handle *qh, nfgenmsg *nfmsg,
@@ -343,6 +346,17 @@ cdef class NetfilterQueue:
343346
else:
344347
nfq_handle_packet(self.h, buf, len(buf))
345348

349+
cdef void _fix_names():
350+
# Avoid ._impl showing up in reprs. This doesn't work on PyPy; there we would
351+
# need to modify the name before PyType_Ready(), but I can't find any way to
352+
# write Cython code that would execute at that time.
353+
cdef PyTypeObject* tp = <PyTypeObject*>Packet
354+
tp.tp_name = "netfilterqueue.Packet"
355+
tp = <PyTypeObject*>NetfilterQueue
356+
tp.tp_name = "netfilterqueue.NetfilterQueue"
357+
358+
_fix_names()
359+
346360
PROTOCOLS = {
347361
0: "HOPOPT",
348362
1: "ICMP",

netfilterqueue/_version.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# This file is imported from __init__.py and exec'd from setup.py
2+
3+
__version__ = "0.9.0+dev"
4+
VERSION = (0, 9, 0)

netfilterqueue/py.typed

Whitespace-only changes.

setup.py

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import os, sys
22
from setuptools import setup, Extension
33

4-
VERSION = "0.9.0" # Remember to change CHANGES.txt and netfilterqueue.pyx when version changes.
4+
exec(open("netfilterqueue/_version.py", encoding="utf-8").read())
55

66
setup_requires = []
77
try:
@@ -10,7 +10,9 @@
1010

1111
ext_modules = cythonize(
1212
Extension(
13-
"netfilterqueue", ["netfilterqueue.pyx"], libraries=["netfilter_queue"]
13+
"netfilterqueue._impl",
14+
["netfilterqueue/_impl.pyx"],
15+
libraries=["netfilter_queue"],
1416
),
1517
compiler_directives={"language_level": "3str"},
1618
)
@@ -21,7 +23,7 @@
2123
# setup_requires below.
2224
setup_requires = ["cython"]
2325
elif not os.path.exists(
24-
os.path.join(os.path.dirname(__file__), "netfilterqueue.c")
26+
os.path.join(os.path.dirname(__file__), "netfilterqueue/_impl.c")
2527
):
2628
sys.stderr.write(
2729
"You must have Cython installed (`pip install cython`) to build this "
@@ -31,21 +33,28 @@
3133
)
3234
sys.exit(1)
3335
ext_modules = [
34-
Extension("netfilterqueue", ["netfilterqueue.c"], libraries=["netfilter_queue"])
36+
Extension(
37+
"netfilterqueue._impl",
38+
["netfilterqueue/_impl.c"],
39+
libraries=["netfilter_queue"],
40+
)
3541
]
3642

3743
setup(
38-
ext_modules=ext_modules,
39-
setup_requires=setup_requires,
40-
python_requires=">=3.6",
4144
name="NetfilterQueue",
42-
version=VERSION,
45+
version=__version__,
4346
license="MIT",
4447
author="Matthew Fox",
4548
author_email="matt@tansen.ca",
4649
url="https://github.com/oremanj/python-netfilterqueue",
4750
description="Python bindings for libnetfilter_queue",
48-
long_description=open("README.rst").read(),
51+
long_description=open("README.rst", encoding="utf-8").read(),
52+
packages=["netfilterqueue"],
53+
ext_modules=ext_modules,
54+
include_package_data=True,
55+
exclude_package_data={"netfilterqueue": ["*.c"]},
56+
setup_requires=setup_requires,
57+
python_requires=">=3.6",
4958
classifiers=[
5059
"Development Status :: 5 - Production/Stable",
5160
"License :: OSI Approved :: MIT License",

test-requirements.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ pytest-trio
55
async_generator
66
black
77
platformdirs <= 2.4.0 # needed by black; 2.4.1+ don't support py3.6
8+
mypy; implementation_name == "cpython"

test-requirements.txt

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,12 @@ idna==3.3
2222
# via trio
2323
iniconfig==1.1.1
2424
# via pytest
25+
mypy==0.931 ; implementation_name == "cpython"
26+
# via -r test-requirements.in
2527
mypy-extensions==0.4.3
26-
# via black
28+
# via
29+
# black
30+
# mypy
2731
outcome==1.1.0
2832
# via
2933
# pytest-trio
@@ -57,10 +61,14 @@ sortedcontainers==2.4.0
5761
toml==0.10.2
5862
# via pytest
5963
tomli==1.2.3
60-
# via black
64+
# via
65+
# black
66+
# mypy
6167
trio==0.19.0
6268
# via
6369
# -r test-requirements.in
6470
# pytest-trio
6571
typing-extensions==4.0.1
66-
# via black
72+
# via
73+
# black
74+
# mypy

0 commit comments

Comments
 (0)