diff --git a/.flake8 b/.flake8
index ec589f6d9..c96c5a826 100644
--- a/.flake8
+++ b/.flake8
@@ -1,3 +1,5 @@
+# flake8 no longer used,
+# ruff config in pyproject.toml
[flake8]
exclude = .git,dist,docs,zmq/eventloop/minitornado,buildutils/templates
ignore = E,W
diff --git a/.gitignore b/.gitignore
index d44b6204f..33da4cf2c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -48,3 +48,4 @@ _deps
/Makefile
_src
licenses
+.virtual_documents
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index ba675be60..5e7460c17 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -13,7 +13,7 @@ repos:
language: python
pass_filenames: false
additional_dependencies:
- - black
+ - ruff
- repo: https://github.com/executablebooks/mdformat
rev: 0.7.17 # Use the ref you want to point at
hooks:
@@ -24,19 +24,24 @@ repos:
- mdformat-myst
exclude: LICENSE.md
- - repo: https://github.com/PyCQA/autoflake
- rev: v2.3.1
- hooks:
- - id: autoflake
- args:
- - --in-place
- exclude: zmq/tests/test_imports.py
+ # autoformat and lint Python code
+ - repo: https://github.com/astral-sh/ruff-pre-commit
+ rev: v0.3.2
+ hooks:
+ - id: ruff
+ types_or:
+ - python
+ - jupyter
+ - pyi
+ args: ["--fix", "--show-fixes"]
+ - id: ruff-format
+ types_or:
+ - python
+ - jupyter
+ - pyi
+ # don't format zmq/constants.py twice
+ exclude: zmq/constants.py
- - repo: https://github.com/PyCQA/flake8
- rev: 7.0.0
- hooks:
- - id: flake8
- exclude: ^buildutils/templates/
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.9.0
hooks:
@@ -49,29 +54,6 @@ repos:
args: [zmq]
additional_dependencies:
- types-paramiko
- - repo: https://github.com/asottile/pyupgrade
- rev: v3.15.2
- hooks:
- - id: pyupgrade
- args:
- - --py36-plus
- - repo: https://github.com/pycqa/isort
- rev: 5.13.2
- hooks:
- - id: isort
- name: isort (python)
- - id: isort
- name: isort (cython)
- types: [cython]
- - id: isort
- name: isort (pyi)
- types: [pyi]
- - repo: https://github.com/psf/black
- rev: 24.3.0
- hooks:
- - id: black
- # don't run black twice on constants.py
- exclude: zmq/constants.py
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
diff --git a/RELICENSE/authors.py b/RELICENSE/authors.py
index 21e4c531c..492922d96 100644
--- a/RELICENSE/authors.py
+++ b/RELICENSE/authors.py
@@ -82,15 +82,5 @@ def sort_key(email_commits):
commits[0].authored_datetime.year,
)
else:
- msg = "{commits} commits ({start}-{end})".format(
- commits=len(commits),
- start=commits[-1].authored_datetime.year,
- end=commits[0].authored_datetime.year,
- )
- print(
- "- [ ] {name} {email}: {msg}".format(
- name=email_names[email],
- email=email,
- msg=msg,
- )
- )
+ msg = f"{len(commits)} commits ({commits[-1].authored_datetime.year}-{commits[0].authored_datetime.year})"
+ print(f"- [ ] {email_names[email]} {email}: {msg}")
diff --git a/buildutils/constants.py b/buildutils/constants.py
index f2594c5ee..59d8b0308 100644
--- a/buildutils/constants.py
+++ b/buildutils/constants.py
@@ -25,7 +25,7 @@
root = pjoin(buildutils, os.path.pardir)
sys.path.insert(0, pjoin(root, 'zmq'))
-import constants
+import constants # noqa: E402
all_names = []
for name in constants.__all__:
@@ -49,7 +49,7 @@ def cython_enums():
lines = []
for name in all_names:
if no_prefix(name):
- lines.append('enum: ZMQ_{0} "{0}"'.format(name))
+ lines.append(f'enum: ZMQ_{name} "{name}"')
else:
lines.append(f'enum: ZMQ_{name}')
@@ -112,7 +112,7 @@ def generate_file(fname, ns_func, dest_dir="."):
with open(dest, 'w') as f:
f.write(out)
if fname.endswith(".py"):
- run([sys.executable, "-m", "black", dest])
+ run(["ruff", "format", dest])
def render_constants():
diff --git a/docs/source/conf.py b/docs/source/conf.py
index 494f466df..d4b657097 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -19,7 +19,7 @@
sys.path.append(str(repo_root))
# set target libzmq version
-from buildutils.bundle import bundled_version
+from buildutils.bundle import bundled_version # noqa
# remove repo root from sys.path
sys.path = sys.path[:-1]
diff --git a/examples/asyncio/helloworld_pubsub_dealerrouter.py b/examples/asyncio/helloworld_pubsub_dealerrouter.py
index 543a20533..c0ce104fa 100644
--- a/examples/asyncio/helloworld_pubsub_dealerrouter.py
+++ b/examples/asyncio/helloworld_pubsub_dealerrouter.py
@@ -195,11 +195,7 @@ async def lang_changer_router(self) -> None:
)
self.hello_world.change_language()
- print(
- "Changed language! New language is: {}\n".format(
- self.hello_world.lang
- )
- )
+ print(f"Changed language! New language is: {self.hello_world.lang}\n")
except Exception as e:
print("Error with sub world")
diff --git a/examples/device/device.py b/examples/device/device.py
index 77ebd3963..241723bb0 100644
--- a/examples/device/device.py
+++ b/examples/device/device.py
@@ -3,7 +3,6 @@
# This example is placed in the Public Domain
# It may also be used under the Creative Commons CC-0 License, (C) PyZMQ Developers
-
import time
from threading import Thread
diff --git a/examples/eventloop/echostream.py b/examples/eventloop/echostream.py
index 28e31844c..daec9f50f 100644
--- a/examples/eventloop/echostream.py
+++ b/examples/eventloop/echostream.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
-"""Adapted echo.py to put the send in the event loop using a ZMQStream.
-"""
+"""Adapted echo.py to put the send in the event loop using a ZMQStream."""
+
from typing import List
from tornado import ioloop
diff --git a/examples/pubsub/subscriber.py b/examples/pubsub/subscriber.py
index a1d8d4a5b..0e890d924 100644
--- a/examples/pubsub/subscriber.py
+++ b/examples/pubsub/subscriber.py
@@ -10,7 +10,6 @@
# the file LICENSE.BSD, distributed as part of this software.
# -----------------------------------------------------------------------------
-
import sys
import time
diff --git a/examples/security/asyncio-ironhouse.py b/examples/security/asyncio-ironhouse.py
index ce8ef46e7..9041c3e1c 100644
--- a/examples/security/asyncio-ironhouse.py
+++ b/examples/security/asyncio-ironhouse.py
@@ -98,9 +98,7 @@ async def run() -> None:
if __name__ == '__main__':
if zmq.zmq_version_info() < (4, 0):
raise RuntimeError(
- "Security is not supported in libzmq version < 4.0. libzmq version {}".format(
- zmq.zmq_version()
- )
+ f"Security is not supported in libzmq version < 4.0. libzmq version {zmq.zmq_version()}"
)
if '-v' in sys.argv:
diff --git a/examples/security/generate_certificates.py b/examples/security/generate_certificates.py
index 2b1511989..f890ac272 100644
--- a/examples/security/generate_certificates.py
+++ b/examples/security/generate_certificates.py
@@ -55,9 +55,7 @@ def generate_certificates(base_dir: Union[str, os.PathLike]) -> None:
if __name__ == '__main__':
if zmq.zmq_version_info() < (4, 0):
raise RuntimeError(
- "Security is not supported in libzmq version < 4.0. libzmq version {}".format(
- zmq.zmq_version()
- )
+ f"Security is not supported in libzmq version < 4.0. libzmq version {zmq.zmq_version()}"
)
generate_certificates(os.path.dirname(__file__))
diff --git a/examples/security/grasslands.py b/examples/security/grasslands.py
index fda56b2ed..deaa28b96 100644
--- a/examples/security/grasslands.py
+++ b/examples/security/grasslands.py
@@ -3,10 +3,10 @@
'''
No protection at all.
-All connections are accepted, there is no authentication, and no privacy.
+All connections are accepted, there is no authentication, and no privacy.
-This is how ZeroMQ always worked until we built security into the wire
-protocol in early 2013. Internally, it uses a security mechanism called
+This is how ZeroMQ always worked until we built security into the wire
+protocol in early 2013. Internally, it uses a security mechanism called
"NULL".
Author: Chris Laws
diff --git a/examples/security/ioloop-ironhouse.py b/examples/security/ioloop-ironhouse.py
index 383814c21..26d78d00c 100644
--- a/examples/security/ioloop-ironhouse.py
+++ b/examples/security/ioloop-ironhouse.py
@@ -121,9 +121,7 @@ async def run() -> None:
if __name__ == '__main__':
if zmq.zmq_version_info() < (4, 0):
raise RuntimeError(
- "Security is not supported in libzmq version < 4.0. libzmq version {}".format(
- zmq.zmq_version()
- )
+ f"Security is not supported in libzmq version < 4.0. libzmq version {zmq.zmq_version()}"
)
if '-v' in sys.argv:
diff --git a/examples/security/ironhouse.py b/examples/security/ironhouse.py
index 02912b117..4722b6de4 100644
--- a/examples/security/ironhouse.py
+++ b/examples/security/ironhouse.py
@@ -89,9 +89,7 @@ def run() -> None:
if __name__ == '__main__':
if zmq.zmq_version_info() < (4, 0):
raise RuntimeError(
- "Security is not supported in libzmq version < 4.0. libzmq version {}".format(
- zmq.zmq_version()
- )
+ f"Security is not supported in libzmq version < 4.0. libzmq version {zmq.zmq_version()}"
)
if '-v' in sys.argv:
diff --git a/examples/security/stonehouse.py b/examples/security/stonehouse.py
index 962d04d84..eec6dafd7 100644
--- a/examples/security/stonehouse.py
+++ b/examples/security/stonehouse.py
@@ -88,9 +88,7 @@ def run() -> None:
if __name__ == '__main__':
if zmq.zmq_version_info() < (4, 0):
raise RuntimeError(
- "Security is not supported in libzmq version < 4.0. libzmq version {}".format(
- zmq.zmq_version()
- )
+ f"Security is not supported in libzmq version < 4.0. libzmq version {zmq.zmq_version()}"
)
if '-v' in sys.argv:
diff --git a/examples/security/strawhouse.py b/examples/security/strawhouse.py
index 93d62a6ba..1e6ade8fe 100644
--- a/examples/security/strawhouse.py
+++ b/examples/security/strawhouse.py
@@ -83,9 +83,7 @@ def run() -> None:
if __name__ == '__main__':
if zmq.zmq_version_info() < (4, 0):
raise RuntimeError(
- "Security is not supported in libzmq version < 4.0. libzmq version {}".format(
- zmq.zmq_version()
- )
+ f"Security is not supported in libzmq version < 4.0. libzmq version {zmq.zmq_version()}"
)
if '-v' in sys.argv:
diff --git a/examples/security/woodhouse.py b/examples/security/woodhouse.py
index 2a5f6599d..b1c8372b2 100644
--- a/examples/security/woodhouse.py
+++ b/examples/security/woodhouse.py
@@ -79,9 +79,7 @@ def run() -> None:
if __name__ == '__main__':
if zmq.zmq_version_info() < (4, 0):
raise RuntimeError(
- "Security is not supported in libzmq version < 4.0. libzmq version {}".format(
- zmq.zmq_version()
- )
+ f"Security is not supported in libzmq version < 4.0. libzmq version {zmq.zmq_version()}"
)
if '-v' in sys.argv:
diff --git a/perf/Dockerfile b/perf/Dockerfile
index 2a83d934e..e80565dcd 100644
--- a/perf/Dockerfile
+++ b/perf/Dockerfile
@@ -1,9 +1,9 @@
-FROM python:3.6
-RUN pip install pandas cython
-RUN pip install -vv https://github.com/zeromq/pyzmq/archive/master.tar.gz --install-option=--zmq=bundled
+FROM python:3.11
+RUN pip install pandas
+RUN pip install --pre pyzmq
RUN mkdir /data && mkdir /perf
ADD *.py /perf/
WORKDIR /data
-ENTRYPOINT ["python", "/perf/collect.py"]
+ENTRYPOINT ["python3", "/perf/collect.py"]
CMD ["thr"]
diff --git a/perf/Makefile b/perf/Makefile
index 2de297c99..78c784432 100644
--- a/perf/Makefile
+++ b/perf/Makefile
@@ -1,8 +1,8 @@
-BASE_IMAGE=python:3.6
+BASE_IMAGE=python:3.11
IMAGE=pyzmq-perf
VOLUME=pyzmq-perf
-ifeq ($(DOCKER_MACHINE_NAME), "")
+ifeq ("$(DOCKER_MACHINE_NAME)", "")
OUT_PATH=$(PWD)
FETCH=true
else
diff --git a/perf/perf.ipynb b/perf/perf.ipynb
index e94b2d9aa..1e3774468 100644
--- a/perf/perf.ipynb
+++ b/perf/perf.ipynb
@@ -25,28 +25,45 @@
"metadata": {},
"outputs": [],
"source": [
- "import matplotlib.pyplot as plt\n",
"import pickle\n",
"\n",
- "plt.ion()\n",
+ "import altair as alt\n",
+ "import pandas as pd\n",
"\n",
- "def crossover(data, column):\n",
+ "\n",
+ "def crossover(data, column, ylabel=\"msgs/sec\"):\n",
" \"\"\"Plot the crossover for copy=True|False\"\"\"\n",
- " for copy, df in data.groupby('copy'):\n",
- " plt.loglog(df['size'], df[column], 'v', label='copy' if copy else 'nocopy')\n",
- " plt.xlabel('size (B)')\n",
- " plt.ylabel('msgs/sec')\n",
- " plt.legend(loc=0)\n",
+ " return (\n",
+ " alt.Chart(data)\n",
+ " .mark_point()\n",
+ " .encode(\n",
+ " color=\"copy\",\n",
+ " x=alt.X(\"size\", title=\"size (B)\").scale(type=\"log\"),\n",
+ " y=alt.Y(column, title=ylabel).scale(type=\"log\"),\n",
+ " )\n",
+ " )\n",
"\n",
"\n",
- "def relative(data, column, scale='semilogx'):\n",
+ "def relative(data, column, yscale=\"linear\"):\n",
" \"\"\"Plot a normalized value showing relative performance\"\"\"\n",
- " copy_mean = data[data['copy']].groupby('size')[column].mean()\n",
- " no_copy = data[data['copy'] == False]\n",
- " reference = copy_mean[no_copy['size']]\n",
- " plot = getattr(plt, scale)\n",
- " plot(no_copy['size'], (no_copy[column] / reference.data), 'v')\n",
- " plt.xlabel(\"size (B)\")\n"
+ " copy_mean = data[data[\"copy\"]].groupby(\"size\")[column].mean()\n",
+ " no_copy = data[~data[\"copy\"]]\n",
+ " reference = copy_mean[no_copy[\"size\"]]\n",
+ " return (\n",
+ " alt.Chart(\n",
+ " pd.DataFrame(\n",
+ " {\n",
+ " \"size\": no_copy[\"size\"],\n",
+ " \"no-copy speedup\": no_copy[column] / reference.array,\n",
+ " }\n",
+ " )\n",
+ " )\n",
+ " .mark_point()\n",
+ " .encode(\n",
+ " x=alt.X(\"size\", title=\"size (B)\").scale(type=\"log\"),\n",
+ " y=alt.Y(\"no-copy speedup\", title=\"\").scale(type=yscale),\n",
+ " )\n",
+ " )"
]
},
{
@@ -64,7 +81,7 @@
"metadata": {},
"outputs": [],
"source": [
- "with open('thr.pickle', 'rb') as f:\n",
+ "with open(\"thr.pickle\", \"rb\") as f:\n",
" thr = pickle.load(f)"
]
},
@@ -77,18 +94,18 @@
"data": {
"text/html": [
"
\n",
- "\n",
"
\n",
" \n",
@@ -107,64 +124,64 @@
" \n",
" 0 | \n",
" 100 | \n",
- " 327680 | \n",
+ " 655360 | \n",
" True | \n",
" False | \n",
" ipc | \n",
- " 475760.295347 | \n",
- " 264266.363135 | \n",
+ " 1.618701e+06 | \n",
+ " 412531.609473 | \n",
"
\n",
" \n",
" 1 | \n",
" 100 | \n",
- " 655360 | \n",
+ " 1310720 | \n",
" True | \n",
" False | \n",
" ipc | \n",
- " 367704.492809 | \n",
- " 259478.511243 | \n",
+ " 1.636403e+06 | \n",
+ " 415309.020795 | \n",
"
\n",
" \n",
" 2 | \n",
" 100 | \n",
- " 1310720 | \n",
- " True | \n",
+ " 262144 | \n",
+ " False | \n",
" False | \n",
" ipc | \n",
- " 426573.892233 | \n",
- " 258967.498492 | \n",
+ " 1.781225e+05 | \n",
+ " 178051.290985 | \n",
"
\n",
" \n",
" 3 | \n",
" 100 | \n",
- " 51200 | \n",
+ " 524288 | \n",
" False | \n",
" False | \n",
" ipc | \n",
- " 34390.097183 | \n",
- " 34388.754455 | \n",
+ " 1.817957e+05 | \n",
+ " 181758.942987 | \n",
"
\n",
" \n",
" 4 | \n",
- " 100 | \n",
- " 102400 | \n",
- " False | \n",
+ " 215 | \n",
+ " 524288 | \n",
+ " True | \n",
" False | \n",
" ipc | \n",
- " 37725.643364 | \n",
- " 37723.441428 | \n",
+ " 1.599087e+06 | \n",
+ " 408223.469186 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
- " size count copy poll transport sends throughput\n",
- "0 100 327680 True False ipc 475760.295347 264266.363135\n",
- "1 100 655360 True False ipc 367704.492809 259478.511243\n",
- "2 100 1310720 True False ipc 426573.892233 258967.498492\n",
- "3 100 51200 False False ipc 34390.097183 34388.754455\n",
- "4 100 102400 False False ipc 37725.643364 37723.441428"
+ " size count copy poll transport sends throughput\n",
+ "0 100 655360 True False ipc 1.618701e+06 412531.609473\n",
+ "1 100 1310720 True False ipc 1.636403e+06 415309.020795\n",
+ "2 100 262144 False False ipc 1.781225e+05 178051.290985\n",
+ "3 100 524288 False False ipc 1.817957e+05 181758.942987\n",
+ "4 215 524288 True False ipc 1.599087e+06 408223.469186"
]
},
"execution_count": 3,
@@ -191,23 +208,87 @@
"outputs": [
{
"data": {
- "image/png": "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2mOBQP7GRPl7ywEAJ3PYIqM9BgAAANekaZF5oT0mSUeOHAlI0mmnndbvgQXa2toCklRTU9Pn6+uxY8fGJOnQoUMn5TiVlZWxYLD37ayuru6KX+5JgdoXv/jFY8FgUI888siJy9m6deuIUCik5cuXux4ouomADABwQqYtMtpjAAAAcFuqFplX2mOSVFFREZOkN998s9/10srLy2OSlOoIkgcPHgxI0siRI08K0FpbWwOdnb1mburtt98uiF+u7Xn66aefHps3b1745ZdfNvv27TuxOP9ll10WToRw+YqADADwgQxbZLTHAAAA4LoULTKvtMck6fzzz49I0o9//OOi/rabOnVqVJJeeOGFXtvt27ev4J133ik4/fTTuyorK08KvDo7O7Vz587C5H1eeOGFwp6X29OXvvSlY5L0yCOPFPRYnP9Y5rdqeCIgAwCcJF2LjPYYAAAAvCK5Real9pgkrVix4ngwGNR9991Xvnfv3l6pXeIolsuWLTsuSRs2bChLtMWk7gBs1apVFbFYTEuXLu3zCJN33313eTgcPvH7+++/bzZs2FAuSdddd12vfT75yU9GJk+erMcffzywffv24jPOOKNr3rx5vdYxyzfeiFQBAN4Rb5EV7X5gUV9n0x4DAACAZ8RbZMU/uX2k5K32mCRNnTq1c/369Ydvv/32U+bMmTNm/vz54cmTJ3e2trYGmpqaQqWlpfbZZ599f9asWdFbbrnl6P3331/2iU98YsyCBQvCpaWldseOHUX79u0LzpgxI/K1r33taPLljx07NtbR0WFmzJgx9tJLLw1Ho1E9+eSTJQcPHgwsW7bs+Ny5c3sFX4FAQNddd13X3XffXSDJLFu2LO/bYxIBGQCgD5G6+uZQ86OzA+HWqp6n0x4DAACA10SnXt1uwt2L13upPZawYsWK4+ecc05048aNZbt27Sp89tlniysrK2NTpkyJJppjkrR+/fq2c889N/ov//IvpU888URJNBo1EydO7Pz617/edttttx0tKuo9SzMUCtknn3zy/W984xsVP/zhD0taWloCEyZM6Fy5cuXRlStXpgy+lixZEvvmN79ZEAwGdf311/fZTMs3BGQAgN5StMhoj2WusGHttFQtvHQ6Zty8LTJ7dVO2xwQAADAsBYKKfPwWT7egZs6cGZ05c2Zruu2WLl0aXrp0aTjddj2NHDnSbtq0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\n",
+ "text/html": [
+ "\n",
+ "\n",
+ "\n",
+ ""
+ ],
"text/plain": [
- ""
+ "alt.Chart(...)"
]
},
- "metadata": {
- "image/png": {
- "height": 397,
- "width": 612
- }
- },
- "output_type": "display_data"
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
}
],
"source": [
- "crossover(thr, 'throughput')\n",
- "plt.title(\"Throughput\");"
+ "chart = crossover(thr, \"throughput\")\n",
+ "chart.title = \"Throughput\"\n",
+ "chart"
]
},
{
@@ -226,14 +307,16 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "zero-copy max msgs/sec: ~4.4e+04\n",
- " copy max msgs/sec: ~2.6e+05\n"
+ "zero-copy max msgs/sec: ~2.1e+05\n",
+ " copy max msgs/sec: ~4.2e+05\n"
]
}
],
"source": [
- "print(\"zero-copy max msgs/sec: ~%.1e\" % thr.where(thr['copy'] == False).throughput.max())\n",
- "print(\" copy max msgs/sec: ~%.1e\" % thr.where(thr['copy']).throughput.max())"
+ "zero_copy_max = thr.where(~thr[\"copy\"]).throughput.max()\n",
+ "copy_max = thr.where(thr[\"copy\"]).throughput.max()\n",
+ "print(f\"zero-copy max msgs/sec: ~{zero_copy_max:.1e}\")\n",
+ "print(f\" copy max msgs/sec: ~{copy_max:.1e}\")"
]
},
{
@@ -255,25 +338,22 @@
"metadata": {},
"outputs": [
{
- "data": {
- "image/png": "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\n",
- "text/plain": [
- ""
- ]
- },
- "metadata": {
- "image/png": {
- "height": 397,
- "width": 597
- }
- },
- "output_type": "display_data"
+ "ename": "NameError",
+ "evalue": "name 'pd' is not defined",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
+ "Cell \u001b[0;32mIn[6], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m chart \u001b[38;5;241m=\u001b[39m \u001b[43mrelative\u001b[49m\u001b[43m(\u001b[49m\u001b[43mthr\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mthroughput\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m 2\u001b[0m chart\u001b[38;5;241m.\u001b[39mtitle \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mZero-copy Throughput (relative)\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 3\u001b[0m chart\n",
+ "Cell \u001b[0;32mIn[1], line 24\u001b[0m, in \u001b[0;36mrelative\u001b[0;34m(data, column, yscale)\u001b[0m\n\u001b[1;32m 20\u001b[0m no_copy \u001b[38;5;241m=\u001b[39m data[\u001b[38;5;241m~\u001b[39mdata[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcopy\u001b[39m\u001b[38;5;124m\"\u001b[39m]]\n\u001b[1;32m 21\u001b[0m reference \u001b[38;5;241m=\u001b[39m copy_mean[no_copy[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124msize\u001b[39m\u001b[38;5;124m\"\u001b[39m]]\n\u001b[1;32m 22\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m (\n\u001b[1;32m 23\u001b[0m alt\u001b[38;5;241m.\u001b[39mChart(\n\u001b[0;32m---> 24\u001b[0m \u001b[43mpd\u001b[49m\u001b[38;5;241m.\u001b[39mDataFrame(\n\u001b[1;32m 25\u001b[0m {\n\u001b[1;32m 26\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124msize\u001b[39m\u001b[38;5;124m\"\u001b[39m: no_copy[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124msize\u001b[39m\u001b[38;5;124m\"\u001b[39m],\n\u001b[1;32m 27\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mno-copy speedup\u001b[39m\u001b[38;5;124m\"\u001b[39m: no_copy[column] \u001b[38;5;241m/\u001b[39m reference\u001b[38;5;241m.\u001b[39marray,\n\u001b[1;32m 28\u001b[0m }\n\u001b[1;32m 29\u001b[0m )\n\u001b[1;32m 30\u001b[0m )\n\u001b[1;32m 31\u001b[0m \u001b[38;5;241m.\u001b[39mmark_point()\n\u001b[1;32m 32\u001b[0m \u001b[38;5;241m.\u001b[39mencode(\n\u001b[1;32m 33\u001b[0m x\u001b[38;5;241m=\u001b[39malt\u001b[38;5;241m.\u001b[39mX(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124msize\u001b[39m\u001b[38;5;124m\"\u001b[39m, title\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124msize (B)\u001b[39m\u001b[38;5;124m\"\u001b[39m)\u001b[38;5;241m.\u001b[39mscale(\u001b[38;5;28mtype\u001b[39m\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mlog\u001b[39m\u001b[38;5;124m\"\u001b[39m),\n\u001b[1;32m 34\u001b[0m y\u001b[38;5;241m=\u001b[39malt\u001b[38;5;241m.\u001b[39mY(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mno-copy speedup\u001b[39m\u001b[38;5;124m\"\u001b[39m, title\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m\"\u001b[39m)\u001b[38;5;241m.\u001b[39mscale(\u001b[38;5;28mtype\u001b[39m\u001b[38;5;241m=\u001b[39myscale),\n\u001b[1;32m 35\u001b[0m )\n\u001b[1;32m 36\u001b[0m )\n",
+ "\u001b[0;31mNameError\u001b[0m: name 'pd' is not defined"
+ ]
}
],
"source": [
- "relative(thr, 'throughput')\n",
- "plt.ylim(0, None)\n",
- "plt.title(\"Zero-copy Throughput (normalized to with-copy performance for same size)\");"
+ "chart = relative(thr, \"throughput\")\n",
+ "chart.title = \"Zero-copy Throughput (relative)\"\n",
+ "chart"
]
},
{
@@ -311,28 +391,13 @@
},
{
"cell_type": "code",
- "execution_count": 7,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "data": {
- "image/png": "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\n",
- "text/plain": [
- ""
- ]
- },
- "metadata": {
- "image/png": {
- "height": 397,
- "width": 612
- }
- },
- "output_type": "display_data"
- }
- ],
+ "outputs": [],
"source": [
- "crossover(thr, 'sends')\n",
- "plt.title(\"Messages sent/sec\");"
+ "chart = crossover(thr, \"sends\")\n",
+ "chart.title = \"Messages sent/sec\"\n",
+ "chart"
]
},
{
@@ -344,28 +409,13 @@
},
{
"cell_type": "code",
- "execution_count": 8,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "data": {
- "image/png": "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\n",
- "text/plain": [
- ""
- ]
- },
- "metadata": {
- "image/png": {
- "height": 397,
- "width": 604
- }
- },
- "output_type": "display_data"
- }
- ],
+ "outputs": [],
"source": [
- "relative(thr, 'sends', scale='loglog')\n",
- "plt.title(\"Zero-copy Throughput (normalized to with-copy performance for same size)\");"
+ "chart = relative(thr, \"sends\", yscale=\"log\")\n",
+ "chart.title = \"Zero-copy sends/sec (relative speedup)\"\n",
+ "chart"
]
},
{
@@ -380,28 +430,16 @@
},
{
"cell_type": "code",
- "execution_count": 9,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "ename": "NameError",
- "evalue": "name 'copy_per_send' is not defined",
- "output_type": "error",
- "traceback": [
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
- "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0mnocopy\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m1e6\u001b[0m \u001b[0;34m/\u001b[0m \u001b[0mthr\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mthr\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'copy'\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;32mFalse\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'sends'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mpenalty\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnocopy\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0mcopy_small\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Small copying send : %.2fµs\"\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0mcopy_per_send\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 5\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Small zero-copy send: %.2fµs ± %.2fµs\"\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mnocopy\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmean\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnocopy\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstd\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Penalty : [%.2fµs - %.2fµs]\"\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mpenalty\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mpenalty\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmax\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;31mNameError\u001b[0m: name 'copy_per_send' is not defined"
- ]
- }
- ],
+ "outputs": [],
"source": [
- "copy_small = 1e6 / thr[thr['copy'] * thr['size'] == thr['size'].min()]['sends'].mean()\n",
- "nocopy = 1e6 / thr[thr['copy'] == False]['sends']\n",
+ "copy_small = 1e6 / thr[thr[\"copy\"] * (thr[\"size\"] == thr[\"size\"].min())][\"sends\"].mean()\n",
+ "nocopy = 1e6 / thr[~thr[\"copy\"]][\"sends\"]\n",
"penalty = nocopy - copy_small\n",
- "print(\"Small copying send : %.2fµs\" % copy_per_send)\n",
- "print(\"Small zero-copy send: %.2fµs ± %.2fµs\" % (nocopy.mean(), nocopy.std()))\n",
- "print(\"Penalty : [%.2fµs - %.2fµs]\" % (penalty.min(), penalty.max()))"
+ "print(f\"Small copying send : {copy_small:.2f}µs\")\n",
+ "print(f\"Small zero-copy send: {nocopy.mean():.2f}µs ± {nocopy.std():.2f}µs\")\n",
+ "print(f\"Penalty : [{penalty.min():.2f}µs - {penalty.max():.2f}µs]\")"
]
},
{
@@ -417,8 +455,8 @@
"metadata": {},
"outputs": [],
"source": [
- "copy_big = 1e6 / thr[thr['copy'] * thr['size'] == thr['size'].max()]['sends'].mean()\n",
- "print(\"Big copying send (%i MB): %.2fµs\" % (thr['size'].max() / 1e6, copy_big))"
+ "copy_big = 1e6 / thr[thr[\"copy\"] * (thr[\"size\"] == thr[\"size\"].max())][\"sends\"].mean()\n",
+ "print(f\"Big copying send ({thr['size'].max() / 1e6:.0f} MB): {copy_big:.2f}µs\")"
]
},
{
@@ -444,7 +482,7 @@
"metadata": {},
"outputs": [],
"source": [
- "with open('lat.pickle', 'rb') as f:\n",
+ "with open(\"lat.pickle\", \"rb\") as f:\n",
" lat = pickle.load(f)"
]
},
@@ -454,9 +492,9 @@
"metadata": {},
"outputs": [],
"source": [
- "crossover(lat, 'latency')\n",
- "plt.ylabel(\"µs\")\n",
- "plt.title(\"Latency (µs)\");"
+ "chart = crossover(lat, \"latency\", ylabel=\"µs\")\n",
+ "chart.title = \"Latency (µs)\"\n",
+ "chart"
]
},
{
@@ -465,9 +503,9 @@
"metadata": {},
"outputs": [],
"source": [
- "relative(lat, 'latency')\n",
- "plt.title(\"Relative increase in latency zero-copy / copy\")\n",
- "plt.ylim(0, None);"
+ "chart = relative(lat, \"latency\")\n",
+ "chart.title = \"Relative increase in latency zero-copy / copy\"\n",
+ "chart"
]
},
{
@@ -477,14 +515,13 @@
"For the latency test, we see that there is much lower overhead to the zero-copy machinery when there are few messages in flight.\n",
"This is expected, because much of the performance cost comes from thread contention when the gc thread is working hard to keep up with the freeing of messages that zmq is done with.\n",
"\n",
- "The result is a much lower penalty for zero-copy of small messages (~10%)\n",
- "and earlier crossover (~5kB)."
+ "The result is a much lower penalty for zero-copy of small messages."
]
}
],
"metadata": {
"kernelspec": {
- "display_name": "Python 3",
+ "display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
@@ -498,9 +535,16 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.6.0"
+ "version": "3.10.13"
+ },
+ "widgets": {
+ "application/vnd.jupyter.widget-state+json": {
+ "state": {},
+ "version_major": 2,
+ "version_minor": 0
+ }
}
},
"nbformat": 4,
- "nbformat_minor": 2
+ "nbformat_minor": 4
}
diff --git a/pyproject.toml b/pyproject.toml
index e17501f18..57dd279a9 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -62,12 +62,47 @@ cmake.version = ">=3.14"
cmake.targets = ["pyzmq"]
install.components = ["pyzmq"]
+[tool.ruff]
+
+[tool.ruff.format]
+exclude = [
+ "buildutils/templates/*",
+ "zmq/eventloop/minitornado/*",
+]
+quote-style = "preserve"
+
+[tool.ruff.lint]
+select = [
+ "E",
+ "F",
+ "UP",
+ "I",
+]
+ignore = [
+ "E501", # line length (formatter is responsible)
+ "E721", # compare types
+ "F841", # unused variables
+]
+ignore-init-module-imports = true
+exclude = ["buildutils/templates/*"]
+
+[tool.ruff.lint.per-file-ignores]
+"__init__.py" = ["F4", "E4"]
+"__init__.pyi" = ["F4", "E4"]
+"zmq/tests/*" = ["E4", "F4"]
+"docs/source/conf.py" = ["E4"]
+"zmq/eventloop/*" = ["E402"]
+"zmq/ssh/forward.py" = ["E"]
+
+# no longer used autoformatters, linters:
+
[tool.autoflake]
ignore-init-module-imports = true
remove-all-unused-imports = true
remove-duplicate-keys = true
# remove-unused-variables = true
+
[tool.black]
skip-string-normalization = true
exclude = "zmq/eventloop/minitornado|docs/source/conf.py"
diff --git a/zmq/__init__.pyi b/zmq/__init__.pyi
index c9bc245d3..45a83d730 100644
--- a/zmq/__init__.pyi
+++ b/zmq/__init__.pyi
@@ -25,5 +25,5 @@ from .constants import *
from .error import *
from .sugar import *
-def get_includes() -> List[str]: ...
-def get_library_dirs() -> List[str]: ...
+def get_includes() -> list[str]: ...
+def get_library_dirs() -> list[str]: ...
diff --git a/zmq/_future.py b/zmq/_future.py
index b3b8053a1..59aafbfb6 100644
--- a/zmq/_future.py
+++ b/zmq/_future.py
@@ -431,7 +431,9 @@ def cancel_poll(future):
def recv_string(self, *args, **kwargs) -> Awaitable[str]: # type: ignore
return super().recv_string(*args, **kwargs) # type: ignore
- def send_string(self, s: str, flags: int = 0, encoding: str = 'utf-8') -> Awaitable[None]: # type: ignore
+ def send_string( # type: ignore
+ self, s: str, flags: int = 0, encoding: str = 'utf-8'
+ ) -> Awaitable[None]:
return super().send_string(s, flags=flags, encoding=encoding) # type: ignore
def _add_timeout(self, future, timeout):
diff --git a/zmq/asyncio.py b/zmq/asyncio.py
index d1effb8a5..e74084701 100644
--- a/zmq/asyncio.py
+++ b/zmq/asyncio.py
@@ -44,7 +44,8 @@ def _get_selector_windows(
# detect add_reader instead of checking for proactor?
if hasattr(asyncio, "ProactorEventLoop") and isinstance(
- asyncio_loop, asyncio.ProactorEventLoop # type: ignore
+ asyncio_loop,
+ asyncio.ProactorEventLoop, # type: ignore
):
try:
from tornado.platform.asyncio import AddThreadSelectorEventLoop
@@ -66,7 +67,9 @@ def _get_selector_windows(
stacklevel=5,
)
- selector_loop = _selectors[asyncio_loop] = AddThreadSelectorEventLoop(asyncio_loop) # type: ignore
+ selector_loop = _selectors[asyncio_loop] = AddThreadSelectorEventLoop(
+ asyncio_loop
+ ) # type: ignore
# patch loop.close to also close the selector thread
loop_close = asyncio_loop.close
@@ -101,15 +104,14 @@ class _AsyncIO:
_READ = selectors.EVENT_READ
def _default_loop(self):
- if sys.version_info >= (3, 7):
- try:
- return asyncio.get_running_loop()
- except RuntimeError:
- warnings.warn(
- "No running event loop. zmq.asyncio should be used from within an asyncio loop.",
- RuntimeWarning,
- stacklevel=4,
- )
+ try:
+ return asyncio.get_running_loop()
+ except RuntimeError:
+ warnings.warn(
+ "No running event loop. zmq.asyncio should be used from within an asyncio loop.",
+ RuntimeWarning,
+ stacklevel=4,
+ )
# get_event_loop deprecated in 3.10:
return asyncio.get_event_loop()
diff --git a/zmq/auth/__init__.py b/zmq/auth/__init__.py
index c30ae8838..ebacab712 100644
--- a/zmq/auth/__init__.py
+++ b/zmq/auth/__init__.py
@@ -3,7 +3,7 @@
To run authentication in a background thread, see :mod:`zmq.auth.thread`.
For integration with the asyncio event loop, see :mod:`zmq.auth.asyncio`.
-Authentication examples are provided in the pyzmq codebase, under
+Authentication examples are provided in the pyzmq codebase, under
`/examples/security/`.
.. versionadded:: 14.1
diff --git a/zmq/auth/certs.py b/zmq/auth/certs.py
index 091066215..7db1b55c5 100644
--- a/zmq/auth/certs.py
+++ b/zmq/auth/certs.py
@@ -3,7 +3,6 @@
# Copyright (C) PyZMQ Developers
# Distributed under the terms of the Modified BSD License.
-
import datetime
import glob
import os
@@ -88,7 +87,7 @@ def create_certificates(
def load_certificate(
- filename: Union[str, os.PathLike]
+ filename: Union[str, os.PathLike],
) -> Tuple[bytes, Optional[bytes]]:
"""Load public and secret key from a zmq certificate.
diff --git a/zmq/backend/__init__.py b/zmq/backend/__init__.py
index 107b23b2a..39640819e 100644
--- a/zmq/backend/__init__.py
+++ b/zmq/backend/__init__.py
@@ -3,7 +3,6 @@
# Copyright (C) PyZMQ Developers
# Distributed under the terms of the Modified BSD License.
-
import os
import platform
diff --git a/zmq/backend/__init__.pyi b/zmq/backend/__init__.pyi
index 1db208f62..5982bbf64 100644
--- a/zmq/backend/__init__.pyi
+++ b/zmq/backend/__init__.pyi
@@ -20,16 +20,16 @@ class Frame:
self,
data: Any = None,
track: bool = False,
- copy: Optional[bool] = None,
- copy_threshold: Optional[int] = None,
+ copy: bool | None = None,
+ copy_threshold: int | None = None,
): ...
def copy_fast(self: T) -> T: ...
- def get(self, option: int) -> Union[int, _bytestr, str]: ...
- def set(self, option: int, value: Union[int, _bytestr, str]) -> None: ...
+ def get(self, option: int) -> int | _bytestr | str: ...
+ def set(self, option: int, value: int | _bytestr | str) -> None: ...
class Socket:
underlying: int
- context: "zmq.Context"
+ context: zmq.Context
copy_threshold: int
# specific option types
@@ -37,14 +37,14 @@ class Socket:
def __init__(
self,
- context: Optional[Context] = None,
+ context: Context | None = None,
socket_type: int = 0,
shadow: int = 0,
- copy_threshold: Optional[int] = zmq.COPY_THRESHOLD,
+ copy_threshold: int | None = zmq.COPY_THRESHOLD,
) -> None: ...
- def close(self, linger: Optional[int] = ...) -> None: ...
- def get(self, option: int) -> Union[int, bytes, str]: ...
- def set(self, option: int, value: Union[int, bytes, str]) -> None: ...
+ def close(self, linger: int | None = ...) -> None: ...
+ def get(self, option: int) -> int | bytes | str: ...
+ def set(self, option: int, value: int | bytes | str) -> None: ...
def connect(self, url: str): ...
def disconnect(self, url: str) -> None: ...
def bind(self, url: str): ...
@@ -55,7 +55,7 @@ class Socket:
flags: int = ...,
copy: bool = ...,
track: bool = ...,
- ) -> Optional["zmq.MessageTracker"]: ...
+ ) -> zmq.MessageTracker | None: ...
@overload
def recv(
self,
@@ -63,7 +63,7 @@ class Socket:
*,
copy: Literal[False],
track: bool = ...,
- ) -> "zmq.Frame": ...
+ ) -> zmq.Frame: ...
@overload
def recv(
self,
@@ -81,11 +81,11 @@ class Socket:
@overload
def recv(
self,
- flags: Optional[int] = ...,
+ flags: int | None = ...,
copy: bool = ...,
- track: Optional[bool] = False,
- ) -> Union["zmq.Frame", bytes]: ...
- def monitor(self, addr: Optional[str], events: int) -> None: ...
+ track: bool | None = False,
+ ) -> zmq.Frame | bytes: ...
+ def monitor(self, addr: str | None, events: int) -> None: ...
# draft methods
def join(self, group: str) -> None: ...
def leave(self, group: str) -> None: ...
@@ -93,34 +93,30 @@ class Socket:
class Context:
underlying: int
def __init__(self, io_threads: int = 1, shadow: int = 0): ...
- def get(self, option: int) -> Union[int, bytes, str]: ...
- def set(self, option: int, value: Union[int, bytes, str]) -> None: ...
+ def get(self, option: int) -> int | bytes | str: ...
+ def set(self, option: int, value: int | bytes | str) -> None: ...
def socket(self, socket_type: int) -> Socket: ...
def term(self) -> None: ...
IPC_PATH_MAX_LEN: int
def has(capability: str) -> bool: ...
-def curve_keypair() -> Tuple[bytes, bytes]: ...
+def curve_keypair() -> tuple[bytes, bytes]: ...
def curve_public(secret_key: bytes) -> bytes: ...
-def strerror(errno: Optional[int] = ...) -> str: ...
+def strerror(errno: int | None = ...) -> str: ...
def zmq_errno() -> int: ...
def zmq_version() -> str: ...
-def zmq_version_info() -> Tuple[int, int, int]: ...
+def zmq_version_info() -> tuple[int, int, int]: ...
def zmq_poll(
- sockets: List[Any], timeout: Optional[int] = ...
-) -> List[Tuple[Socket, int]]: ...
-def device(
- device_type: int, frontend: Socket, backend: Optional[Socket] = ...
-) -> int: ...
-def proxy(
- frontend: Socket, backend: Socket, capture: Optional[Socket] = None
-) -> int: ...
+ sockets: list[Any], timeout: int | None = ...
+) -> list[tuple[Socket, int]]: ...
+def device(device_type: int, frontend: Socket, backend: Socket | None = ...) -> int: ...
+def proxy(frontend: Socket, backend: Socket, capture: Socket | None = None) -> int: ...
def proxy_steerable(
frontend: Socket,
backend: Socket,
- capture: Optional[Socket] = ...,
- control: Optional[Socket] = ...,
+ capture: Socket | None = ...,
+ control: Socket | None = ...,
) -> int: ...
-monitored_queue = Optional[Callable]
+monitored_queue = Callable | None
diff --git a/zmq/backend/cffi/socket.py b/zmq/backend/cffi/socket.py
index 8d8a3cff4..4b998d300 100644
--- a/zmq/backend/cffi/socket.py
+++ b/zmq/backend/cffi/socket.py
@@ -5,37 +5,53 @@
import errno as errno_mod
+import zmq
+from zmq.constants import SocketOption, _OptType
+from zmq.error import ZMQError, _check_rc, _check_version
+
from ._cffi import ffi
from ._cffi import lib as C
+from .message import Frame
+from .utils import _retry_sys_call
nsp = new_sizet_pointer = lambda length: ffi.new('size_t*', length)
-new_uint64_pointer = lambda: (ffi.new('uint64_t*'), nsp(ffi.sizeof('uint64_t')))
-new_int64_pointer = lambda: (ffi.new('int64_t*'), nsp(ffi.sizeof('int64_t')))
-new_int_pointer = lambda: (ffi.new('int*'), nsp(ffi.sizeof('int')))
-new_binary_data = lambda length: (
- ffi.new('char[%d]' % (length)),
- nsp(ffi.sizeof('char') * length),
-)
-
-value_uint64_pointer = lambda val: (ffi.new('uint64_t*', val), ffi.sizeof('uint64_t'))
-value_int64_pointer = lambda val: (ffi.new('int64_t*', val), ffi.sizeof('int64_t'))
-value_int_pointer = lambda val: (ffi.new('int*', val), ffi.sizeof('int'))
-value_binary_data = lambda val, length: (
- ffi.new('char[%d]' % (length + 1), val),
- ffi.sizeof('char') * length,
-)
-ZMQ_FD_64BIT = ffi.sizeof('ZMQ_FD_T') == 8
+def new_uint64_pointer():
+ return ffi.new('uint64_t*'), nsp(ffi.sizeof('uint64_t'))
-IPC_PATH_MAX_LEN = C.get_ipc_path_max_len()
-import zmq
-from zmq.constants import SocketOption, _OptType
-from zmq.error import ZMQError, _check_rc, _check_version
+def new_int64_pointer():
+ return ffi.new('int64_t*'), nsp(ffi.sizeof('int64_t'))
-from .message import Frame
-from .utils import _retry_sys_call
+
+def new_int_pointer():
+ return ffi.new('int*'), nsp(ffi.sizeof('int'))
+
+
+def new_binary_data(length):
+ return ffi.new('char[%d]' % length), nsp(ffi.sizeof('char') * length)
+
+
+def value_uint64_pointer(val):
+ return ffi.new('uint64_t*', val), ffi.sizeof('uint64_t')
+
+
+def value_int64_pointer(val):
+ return ffi.new('int64_t*', val), ffi.sizeof('int64_t')
+
+
+def value_int_pointer(val):
+ return ffi.new('int*', val), ffi.sizeof('int')
+
+
+def value_binary_data(val, length):
+ return ffi.new('char[%d]' % (length + 1), val), ffi.sizeof('char') * length
+
+
+ZMQ_FD_64BIT = ffi.sizeof('ZMQ_FD_T') == 8
+
+IPC_PATH_MAX_LEN = C.get_ipc_path_max_len()
def new_pointer_from_opt(option, length=0):
@@ -156,10 +172,8 @@ def bind(self, address):
if IPC_PATH_MAX_LEN and C.zmq_errno() == errno_mod.ENAMETOOLONG:
path = address.split('://', 1)[-1]
msg = (
- 'ipc path "{}" is longer than {} '
- 'characters (sizeof(sockaddr_un.sun_path)).'.format(
- path, IPC_PATH_MAX_LEN
- )
+ f'ipc path "{path}" is longer than {IPC_PATH_MAX_LEN} '
+ 'characters (sizeof(sockaddr_un.sun_path)).'
)
raise ZMQError(C.zmq_errno(), msg=msg)
elif C.zmq_errno() == errno_mod.ENOENT:
diff --git a/zmq/backend/cython/_zmq.py b/zmq/backend/cython/_zmq.py
index bd97837a1..fb6f3b6f3 100644
--- a/zmq/backend/cython/_zmq.py
+++ b/zmq/backend/cython/_zmq.py
@@ -86,9 +86,6 @@
zmq_curve_public,
zmq_device,
zmq_disconnect,
-)
-from cython.cimports.zmq.backend.cython.libzmq import zmq_errno as _zmq_errno
-from cython.cimports.zmq.backend.cython.libzmq import (
zmq_free_fn,
zmq_getsockopt,
zmq_has,
@@ -112,9 +109,6 @@
zmq_msg_set_routing_id,
zmq_msg_size,
zmq_msg_t,
-)
-from cython.cimports.zmq.backend.cython.libzmq import zmq_poll as zmq_poll_c
-from cython.cimports.zmq.backend.cython.libzmq import (
zmq_pollitem_t,
zmq_proxy,
zmq_proxy_steerable,
@@ -124,6 +118,8 @@
zmq_strerror,
zmq_unbind,
)
+from cython.cimports.zmq.backend.cython.libzmq import zmq_errno as _zmq_errno
+from cython.cimports.zmq.backend.cython.libzmq import zmq_poll as zmq_poll_c
from cython.cimports.zmq.utils.buffers import asbuffer_r
import zmq
@@ -887,12 +883,10 @@ def bind(self, addr):
if IPC_PATH_MAX_LEN and zmq_errno() == ENAMETOOLONG:
path = addr.split('://', 1)[-1]
msg = (
- 'ipc path "{}" is longer than {} '
+ f'ipc path "{path}" is longer than {IPC_PATH_MAX_LEN} '
'characters (sizeof(sockaddr_un.sun_path)). '
'zmq.IPC_PATH_MAX_LEN constant can be used '
- 'to check addr length (if it is defined).'.format(
- path, IPC_PATH_MAX_LEN
- )
+ 'to check addr length (if it is defined).'
)
raise ZMQError(msg=msg)
elif zmq_errno() == ENOENT:
@@ -1517,7 +1511,7 @@ def zmq_poll(sockets, timeout: C.int = -1):
elif hasattr(s, 'fileno'):
try:
fileno = int(s.fileno())
- except:
+ except Exception:
free(pollitems)
raise ValueError('fileno() must return a valid integer fd')
else:
diff --git a/zmq/decorators.py b/zmq/decorators.py
index 7d4832a6a..7cd80ebc7 100644
--- a/zmq/decorators.py
+++ b/zmq/decorators.py
@@ -8,7 +8,7 @@
For example::
from zmq.decorators import context, socket
-
+
@context()
@socket(zmq.PUSH)
def work(ctx, push):
@@ -69,8 +69,8 @@ def wrapper(*args, **kwargs):
kwargs[kw_name] = obj
elif kw_name and kw_name in kwargs:
raise TypeError(
- "{}() got multiple values for"
- " argument '{}'".format(func.__name__, kw_name)
+ f"{func.__name__}() got multiple values for"
+ f" argument '{kw_name}'"
)
else:
args = args + (obj,)
diff --git a/zmq/devices/basedevice.py b/zmq/devices/basedevice.py
index 9e8013428..bd4d78290 100644
--- a/zmq/devices/basedevice.py
+++ b/zmq/devices/basedevice.py
@@ -3,7 +3,6 @@
# Copyright (C) PyZMQ Developers
# Distributed under the terms of the Modified BSD License.
-
import time
from multiprocessing import Process
from threading import Thread
diff --git a/zmq/devices/monitoredqueuedevice.py b/zmq/devices/monitoredqueuedevice.py
index edcdc0d99..7bcc56299 100644
--- a/zmq/devices/monitoredqueuedevice.py
+++ b/zmq/devices/monitoredqueuedevice.py
@@ -3,7 +3,6 @@
# Copyright (C) PyZMQ Developers
# Distributed under the terms of the Modified BSD License.
-
from zmq import PUB
from zmq.devices.monitoredqueue import monitored_queue
from zmq.devices.proxydevice import ProcessProxy, Proxy, ProxyBase, ThreadProxy
diff --git a/zmq/error.py b/zmq/error.py
index 8023bc195..6e85b8704 100644
--- a/zmq/error.py
+++ b/zmq/error.py
@@ -175,11 +175,7 @@ def __repr__(self):
return "ZMQVersionError('%s')" % str(self)
def __str__(self):
- return "{} requires libzmq >= {}, have {}".format(
- self.msg,
- self.min_version,
- self.version,
- )
+ return f"{self.msg} requires libzmq >= {self.min_version}, have {self.version}"
def _check_version(
diff --git a/zmq/eventloop/_deprecated.py b/zmq/eventloop/_deprecated.py
index e9dda5391..628900509 100644
--- a/zmq/eventloop/_deprecated.py
+++ b/zmq/eventloop/_deprecated.py
@@ -11,7 +11,6 @@
# Copyright (C) PyZMQ Developers
# Distributed under the terms of the Modified BSD License.
-
import time
import warnings
from typing import Tuple
@@ -200,10 +199,9 @@ def install():
# check if tornado's IOLoop is already initialized to something other
# than the pyzmq IOLoop instance:
assert (
- not ioloop.IOLoop.initialized()
- ) or ioloop.IOLoop.instance() is IOLoop.instance(), (
- "tornado IOLoop already initialized"
- )
+ (not ioloop.IOLoop.initialized())
+ or ioloop.IOLoop.instance() is IOLoop.instance()
+ ), "tornado IOLoop already initialized"
if tornado_version >= (3,):
# tornado 3 has an official API for registering new defaults, yay!
diff --git a/zmq/eventloop/ioloop.py b/zmq/eventloop/ioloop.py
index f1451cd77..dccb92a14 100644
--- a/zmq/eventloop/ioloop.py
+++ b/zmq/eventloop/ioloop.py
@@ -9,7 +9,6 @@
# Copyright (C) PyZMQ Developers
# Distributed under the terms of the Modified BSD License.
-
import warnings
diff --git a/zmq/eventloop/zmqstream.py b/zmq/eventloop/zmqstream.py
index 720fd2bf9..36ce14109 100644
--- a/zmq/eventloop/zmqstream.py
+++ b/zmq/eventloop/zmqstream.py
@@ -12,8 +12,6 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
-from __future__ import annotations
-
"""A utility class for event-based messaging on a zmq socket using tornado.
.. seealso::
@@ -22,6 +20,8 @@
- :mod:`zmq.eventloop.future`
"""
+from __future__ import annotations
+
import asyncio
import pickle
import warnings
diff --git a/zmq/green/__init__.py b/zmq/green/__init__.py
index 08820b8a9..8543864b0 100644
--- a/zmq/green/__init__.py
+++ b/zmq/green/__init__.py
@@ -27,6 +27,7 @@
before any blocking operation and the ØMQ file descriptor is polled internally
to trigger needed events.
"""
+
from __future__ import annotations
from typing import List
diff --git a/zmq/green/core.py b/zmq/green/core.py
index 22b6d00fe..c104a9331 100644
--- a/zmq/green/core.py
+++ b/zmq/green/core.py
@@ -8,8 +8,8 @@
# the file LICENSE.BSD, distributed as part of this software.
# -----------------------------------------------------------------------------
-"""This module wraps the :class:`Socket` and :class:`Context` found in :mod:`pyzmq ` to be non blocking
-"""
+"""This module wraps the :class:`Socket` and :class:`Context` found in :mod:`pyzmq ` to be non blocking"""
+
from __future__ import annotations
import sys
@@ -218,9 +218,7 @@ def send(self, data, flags=0, copy=True, track=False, **kwargs):
return msg
# ensure the zmq.NOBLOCK flag is part of flags
flags |= zmq.NOBLOCK
- while (
- True
- ): # Attempt to complete this operation indefinitely, blocking the current greenlet
+ while True: # Attempt to complete this operation indefinitely, blocking the current greenlet
try:
# attempt the actual call
msg = super().send(data, flags, copy, track)
diff --git a/zmq/green/poll.py b/zmq/green/poll.py
index 6443a9c47..5060740ae 100644
--- a/zmq/green/poll.py
+++ b/zmq/green/poll.py
@@ -33,7 +33,7 @@ def _get_descriptors(self):
elif hasattr(socket, 'fileno'):
try:
fd = int(socket.fileno())
- except:
+ except Exception:
raise ValueError('fileno() must return an valid integer fd')
else:
raise TypeError(
diff --git a/zmq/log/__main__.py b/zmq/log/__main__.py
index 15a11e4d0..98c6b97c4 100644
--- a/zmq/log/__main__.py
+++ b/zmq/log/__main__.py
@@ -6,13 +6,13 @@
python -m zmq.log -h
Subscribes to the '' (empty string) topic by default which means it will work
-out-of-the-box with a PUBHandler object instantiated with default settings.
-If you change the root topic with PUBHandler.setRootTopic() you must pass
+out-of-the-box with a PUBHandler object instantiated with default settings.
+If you change the root topic with PUBHandler.setRootTopic() you must pass
the value to this script with the --topic argument.
Note that the default formats for the PUBHandler object selectively include
the log level in the message. This creates redundancy in this script as it
-always prints the topic of the message, which includes the log level.
+always prints the topic of the message, which includes the log level.
Consider overriding the default formats with PUBHandler.setFormat() to
avoid this issue.
diff --git a/zmq/log/handlers.py b/zmq/log/handlers.py
index 88fe571ca..8138d2eed 100644
--- a/zmq/log/handlers.py
+++ b/zmq/log/handlers.py
@@ -11,7 +11,7 @@
>>> logger = logging.getLogger('foobar')
>>> logger.setLevel(logging.DEBUG)
>>> logger.addHandler(handler)
-
+
Or using ``dictConfig``, as in::
>>> from logging.config import dictConfig
@@ -32,7 +32,7 @@
>>> 'handlers': ['zmq'],
>>> }
>>> })
-
+
After this point, all messages logged by ``logger`` will be published on the
PUB socket.
diff --git a/zmq/ssh/forward.py b/zmq/ssh/forward.py
index b7c2186b2..5e9a7fd45 100644
--- a/zmq/ssh/forward.py
+++ b/zmq/ssh/forward.py
@@ -25,7 +25,6 @@
connection to a destination reachable from the SSH server machine.
"""
-
import logging
import select
import socketserver
@@ -60,12 +59,7 @@ def handle(self):
return
logger.debug(
- 'Connected! Tunnel open %r -> %r -> %r'
- % (
- self.request.getpeername(),
- chan.getpeername(),
- (self.chain_host, self.chain_port),
- )
+ f'Connected! Tunnel open {self.request.getpeername()!r} -> {chan.getpeername()!r} -> {(self.chain_host, self.chain_port)!r}'
)
while True:
r, w, x = select.select([self.request, chan], [], [])
diff --git a/zmq/ssh/tunnel.py b/zmq/ssh/tunnel.py
index 69de44b53..4645f9797 100644
--- a/zmq/ssh/tunnel.py
+++ b/zmq/ssh/tunnel.py
@@ -7,7 +7,6 @@
#
# Redistributed from IPython under the terms of the BSD License.
-
import atexit
import os
import re
diff --git a/zmq/sugar/__init__.py b/zmq/sugar/__init__.py
index 7866ce89f..a4b8cf332 100644
--- a/zmq/sugar/__init__.py
+++ b/zmq/sugar/__init__.py
@@ -3,7 +3,6 @@
# Copyright (C) PyZMQ Developers
# Distributed under the terms of the Modified BSD License.
-
from zmq import error
from zmq.sugar import context, frame, poll, socket, tracker, version
diff --git a/zmq/tests/__init__.py b/zmq/tests/__init__.py
index d8d391c5d..fbe4d718f 100644
--- a/zmq/tests/__init__.py
+++ b/zmq/tests/__init__.py
@@ -33,7 +33,10 @@
# skip decorators (directly from unittest)
# -----------------------------------------------------------------------------
-_id = lambda x: x
+
+def _id(x):
+ return x
+
skip_pypy = mark.skipif(PYPY, reason="Doesn't work on PyPy")
require_zmq_4 = mark.skipif(zmq.zmq_version_info() < (4,), reason="requires zmq >= 4")
@@ -172,9 +175,8 @@ def assertRaisesErrno(self, errno, func, *args, **kwargs):
self.assertEqual(
e.errno,
errno,
- "wrong error raised, expected '%s' \
-got '%s'"
- % (zmq.ZMQError(errno), zmq.ZMQError(e.errno)),
+ f"wrong error raised, expected '{zmq.ZMQError(errno)}' \
+got '{zmq.ZMQError(e.errno)}'",
)
else:
self.fail("Function did not raise any error")
@@ -223,9 +225,8 @@ def assertRaisesErrno(self, errno, func, *args, **kwargs):
self.assertEqual(
e.errno,
errno,
- "wrong error raised, expected '%s' \
-got '%s'"
- % (zmq.ZMQError(errno), zmq.ZMQError(e.errno)),
+ f"wrong error raised, expected '{zmq.ZMQError(errno)}' \
+got '{zmq.ZMQError(e.errno)}'",
)
else:
self.fail("Function did not raise any error")
diff --git a/zmq/tests/test_context.py b/zmq/tests/test_context.py
index 2d704de94..718add3f3 100644
--- a/zmq/tests/test_context.py
+++ b/zmq/tests/test_context.py
@@ -96,7 +96,7 @@ def test_instance(self):
c2.term()
c3 = self.Context.instance()
c4 = self.Context.instance()
- assert not c3 is c2
+ assert c3 is not c2
assert not c3.closed
assert c3 is c4
diff --git a/zmq/tests/test_device.py b/zmq/tests/test_device.py
index 2ac3e8418..343d51dd7 100644
--- a/zmq/tests/test_device.py
+++ b/zmq/tests/test_device.py
@@ -24,7 +24,7 @@ def test_device_attributes(self):
assert dev.in_type == zmq.SUB
assert dev.out_type == zmq.PUB
assert dev.device_type == zmq.QUEUE
- assert dev.daemon == True
+ assert dev.daemon is True
del dev
def test_single_socket_forwarder_connect(self):
diff --git a/zmq/tests/test_log.py b/zmq/tests/test_log.py
index 429b18c4f..855c17d9c 100644
--- a/zmq/tests/test_log.py
+++ b/zmq/tests/test_log.py
@@ -37,7 +37,7 @@ def test_init_iface(self):
logger = self.logger
ctx = self.context
handler = handlers.PUBHandler(self.iface)
- assert not handler.ctx is ctx
+ assert handler.ctx is not ctx
self.sockets.append(handler.socket)
# handler.ctx.term()
handler = handlers.PUBHandler(self.iface, self.context)
diff --git a/zmq/tests/test_message.py b/zmq/tests/test_message.py
index ea2ba0861..6020c87e1 100644
--- a/zmq/tests/test_message.py
+++ b/zmq/tests/test_message.py
@@ -188,9 +188,9 @@ def test_tracker(self):
def test_no_tracker(self):
m = zmq.Frame(b'asdf', track=False)
- assert m.tracker == None
+ assert m.tracker is None
m2 = copy.copy(m)
- assert m2.tracker == None
+ assert m2.tracker is None
self.assertRaises(ValueError, zmq.MessageTracker, m)
def test_multi_tracker(self):
diff --git a/zmq/tests/test_multipart.py b/zmq/tests/test_multipart.py
index d0ff1f128..b1fa6be04 100644
--- a/zmq/tests/test_multipart.py
+++ b/zmq/tests/test_multipart.py
@@ -14,11 +14,10 @@ def test_router_dealer(self):
dealer.send(msg1)
self.recv(router)
more = router.rcvmore
- assert more == True
+ assert more
msg2 = self.recv(router)
assert msg1 == msg2
- more = router.rcvmore
- assert more == False
+ assert not router.rcvmore
def test_basic_multipart(self):
a, b = self.create_bound_pair(zmq.PAIR, zmq.PAIR)
diff --git a/zmq/tests/test_security.py b/zmq/tests/test_security.py
index f8882e4fe..684451c00 100644
--- a/zmq/tests/test_security.py
+++ b/zmq/tests/test_security.py
@@ -228,8 +228,8 @@ def test_curve(self):
assert server.mechanism == zmq.CURVE
assert client.mechanism == zmq.CURVE
- assert server.get(zmq.CURVE_SERVER) == True
- assert client.get(zmq.CURVE_SERVER) == False
+ assert server.get(zmq.CURVE_SERVER)
+ assert not client.get(zmq.CURVE_SERVER)
with self.zap():
iface = 'tcp://127.0.0.1'
diff --git a/zmq/tests/test_socket.py b/zmq/tests/test_socket.py
index 20e1f0a03..598799731 100644
--- a/zmq/tests/test_socket.py
+++ b/zmq/tests/test_socket.py
@@ -48,9 +48,9 @@ def test_context_manager(self):
a.send(msg)
rcvd = self.recv(b)
assert rcvd == msg
- assert b.closed == True
- assert a.closed == True
- assert ctx.closed == True
+ assert b.closed is True
+ assert a.closed is True
+ assert ctx.closed is True
def test_connectbind_context_managers(self):
url = 'inproc://a'
@@ -356,38 +356,38 @@ def test_tracker(self):
if p1.done:
break
time.sleep(0.1)
- assert p1.done == True
+ assert p1.done is True
assert msg == [b'something']
msg = self.recv_multipart(b)
for i in range(10):
if p2.done:
break
time.sleep(0.1)
- assert p2.done == True
+ assert p2.done is True
assert msg == [b'something', b'else']
m = zmq.Frame(b"again", copy=False, track=True)
- assert m.tracker.done == False
+ assert m.tracker.done is False
p1 = a.send(m, copy=False)
p2 = a.send(m, copy=False)
- assert m.tracker.done == False
- assert p1.done == False
- assert p2.done == False
+ assert m.tracker.done is False
+ assert p1.done is False
+ assert p2.done is False
msg = self.recv_multipart(b)
- assert m.tracker.done == False
+ assert m.tracker.done is False
assert msg == [b'again']
msg = self.recv_multipart(b)
- assert m.tracker.done == False
+ assert m.tracker.done is False
assert msg == [b'again']
- assert p1.done == False
- assert p2.done == False
+ assert p1.done is False
+ assert p2.done is False
m.tracker
del m
for i in range(10):
if p1.done:
break
time.sleep(0.1)
- assert p1.done == True
- assert p2.done == True
+ assert p1.done is True
+ assert p2.done is True
m = zmq.Frame(b'something', track=False)
self.assertRaises(ValueError, a.send, m, copy=False, track=True)
diff --git a/zmq/tests/test_z85.py b/zmq/tests/test_z85.py
index 85594f627..a96c3f67a 100644
--- a/zmq/tests/test_z85.py
+++ b/zmq/tests/test_z85.py
@@ -14,10 +14,10 @@
class TestZ85(TestCase):
def test_client_public(self):
client_public = (
- b"\xBB\x88\x47\x1D\x65\xE2\x65\x9B"
- b"\x30\xC5\x5A\x53\x21\xCE\xBB\x5A"
- b"\xAB\x2B\x70\xA3\x98\x64\x5C\x26"
- b"\xDC\xA2\xB2\xFC\xB4\x3F\xC5\x18"
+ b"\xbb\x88\x47\x1d\x65\xe2\x65\x9b"
+ b"\x30\xc5\x5a\x53\x21\xce\xbb\x5a"
+ b"\xab\x2b\x70\xa3\x98\x64\x5c\x26"
+ b"\xdc\xa2\xb2\xfc\xb4\x3f\xc5\x18"
)
encoded = z85.encode(client_public)
@@ -27,10 +27,10 @@ def test_client_public(self):
def test_client_secret(self):
client_secret = (
- b"\x7B\xB8\x64\xB4\x89\xAF\xA3\x67"
- b"\x1F\xBE\x69\x10\x1F\x94\xB3\x89"
- b"\x72\xF2\x48\x16\xDF\xB0\x1B\x51"
- b"\x65\x6B\x3F\xEC\x8D\xFD\x08\x88"
+ b"\x7b\xb8\x64\xb4\x89\xaf\xa3\x67"
+ b"\x1f\xbe\x69\x10\x1f\x94\xb3\x89"
+ b"\x72\xf2\x48\x16\xdf\xb0\x1b\x51"
+ b"\x65\x6b\x3f\xec\x8d\xfd\x08\x88"
)
encoded = z85.encode(client_secret)
@@ -40,10 +40,10 @@ def test_client_secret(self):
def test_server_public(self):
server_public = (
- b"\x54\xFC\xBA\x24\xE9\x32\x49\x96"
- b"\x93\x16\xFB\x61\x7C\x87\x2B\xB0"
- b"\xC1\xD1\xFF\x14\x80\x04\x27\xC5"
- b"\x94\xCB\xFA\xCF\x1B\xC2\xD6\x52"
+ b"\x54\xfc\xba\x24\xe9\x32\x49\x96"
+ b"\x93\x16\xfb\x61\x7c\x87\x2b\xb0"
+ b"\xc1\xd1\xff\x14\x80\x04\x27\xc5"
+ b"\x94\xcb\xfa\xcf\x1b\xc2\xd6\x52"
)
encoded = z85.encode(server_public)
@@ -53,10 +53,10 @@ def test_server_public(self):
def test_server_secret(self):
server_secret = (
- b"\x8E\x0B\xDD\x69\x76\x28\xB9\x1D"
- b"\x8F\x24\x55\x87\xEE\x95\xC5\xB0"
- b"\x4D\x48\x96\x3F\x79\x25\x98\x77"
- b"\xB4\x9C\xD9\x06\x3A\xEA\xD3\xB7"
+ b"\x8e\x0b\xdd\x69\x76\x28\xb9\x1d"
+ b"\x8f\x24\x55\x87\xee\x95\xc5\xb0"
+ b"\x4d\x48\x96\x3f\x79\x25\x98\x77"
+ b"\xb4\x9c\xd9\x06\x3a\xea\xd3\xb7"
)
encoded = z85.encode(server_secret)
diff --git a/zmq/utils/garbage.py b/zmq/utils/garbage.py
index 39d817591..2c700313d 100644
--- a/zmq/utils/garbage.py
+++ b/zmq/utils/garbage.py
@@ -5,7 +5,6 @@
# Copyright (C) PyZMQ Developers
# Distributed under the terms of the Modified BSD License.
-
import atexit
import struct
import warnings
diff --git a/zmq/utils/win32.py b/zmq/utils/win32.py
index 1d6724dd5..019d42971 100644
--- a/zmq/utils/win32.py
+++ b/zmq/utils/win32.py
@@ -89,7 +89,10 @@ def _init_action(self, action):
SetConsoleCtrlHandler.restype = BOOL
if action is None:
- action = lambda: None
+
+ def action():
+ return None
+
self.action = action
@PHANDLER_ROUTINE
diff --git a/zmqversion.py b/zmqversion.py
index 55c176b29..a74894bd7 100644
--- a/zmqversion.py
+++ b/zmqversion.py
@@ -6,18 +6,13 @@
# Copyright (c) PyZMQ Developers
# Distributed under the terms of the Modified BSD License.
-
import os
import re
import sys
import traceback
+from configparser import ConfigParser
from warnings import warn
-try:
- from configparser import ConfigParser
-except:
- from ConfigParser import ConfigParser
-
pjoin = os.path.join
MAJOR_PAT = '^#define +ZMQ_VERSION_MAJOR +[0-9]+$'