Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-queuelib for openSUSE:Factory checked in at 2025-05-30 14:34:51 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-queuelib (Old) and /work/SRC/openSUSE:Factory/.python-queuelib.new.25440 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-queuelib" Fri May 30 14:34:51 2025 rev:7 rq:1280954 version:1.8.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-queuelib/python-queuelib.changes 2024-06-10 17:38:42.085323857 +0200 +++ /work/SRC/openSUSE:Factory/.python-queuelib.new.25440/python-queuelib.changes 2025-05-30 17:26:27.058045983 +0200 @@ -1,0 +2,19 @@ +Wed May 28 08:41:24 UTC 2025 - John Paul Adrian Glaubitz <adrian.glaub...@suse.com> + +- Update to 1.8.0 + * Added support for Python 3.13 and PyPy 3.11 + * Removed support for Python 3.8 + * Queue classes now accept ``os.PathLike`` paths + * Fixed test failures on Windows + * Switched the build system to ``hatchling`` + * Improved linting and CI configuration +- Switch package to modern Python Stack on SLE-15 + * Use Python 3.11 on SLE-15 by default + * Drop support for older Python versions +- Switch build system from setuptools to pyproject.toml + * Add python-pip and python-wheel to BuildRequires + * Replace %python_build with %pyproject_wheel + * Replace %python_install with %pyproject_install +- Update BuildRequires from pyproject.toml + +------------------------------------------------------------------- Old: ---- queuelib-1.7.0.tar.gz New: ---- queuelib-1.8.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-queuelib.spec ++++++ --- /var/tmp/diff_new_pack.vhhbON/_old 2025-05-30 17:26:27.506064594 +0200 +++ /var/tmp/diff_new_pack.vhhbON/_new 2025-05-30 17:26:27.506064594 +0200 @@ -1,7 +1,7 @@ # # spec file for package python-queuelib # -# Copyright (c) 2024 SUSE LLC +# Copyright (c) 2025 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -16,15 +16,18 @@ # -%{?!python_module:%define python_module() python-%{**} python3-%{**}} +%{?sle15_python_module_pythons} Name: python-queuelib -Version: 1.7.0 +Version: 1.8.0 Release: 0 Summary: Collection of Persistent (Disk-Based) Queues License: BSD-2-Clause URL: https://github.com/scrapy/queuelib Source: https://files.pythonhosted.org/packages/source/q/queuelib/queuelib-%{version}.tar.gz +BuildRequires: %{python_module hatchling} +BuildRequires: %{python_module pip} BuildRequires: %{python_module setuptools} +BuildRequires: %{python_module wheel} BuildRequires: %{pythons} BuildRequires: fdupes BuildRequires: python-rpm-macros @@ -45,10 +48,10 @@ %setup -q -n queuelib-%{version} %build -%python_build +%pyproject_wheel %install -%python_install +%pyproject_install %python_expand %fdupes %{buildroot}%{$python_sitelib} %check ++++++ queuelib-1.7.0.tar.gz -> queuelib-1.8.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/queuelib-1.7.0/.gitignore new/queuelib-1.8.0/.gitignore --- old/queuelib-1.7.0/.gitignore 1970-01-01 01:00:00.000000000 +0100 +++ new/queuelib-1.8.0/.gitignore 2020-02-02 01:00:00.000000000 +0100 @@ -0,0 +1,10 @@ +htmlcov/ +coverage.xml +.coverage +.tox +*egg-info +*.pyc +/.tox/ +build/ +dist/ +.idea/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/queuelib-1.7.0/MANIFEST.in new/queuelib-1.8.0/MANIFEST.in --- old/queuelib-1.7.0/MANIFEST.in 2024-05-04 08:02:38.000000000 +0200 +++ new/queuelib-1.8.0/MANIFEST.in 1970-01-01 01:00:00.000000000 +0100 @@ -1,3 +0,0 @@ -include README.rst -include LICENSE -include NEWS diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/queuelib-1.7.0/NEWS new/queuelib-1.8.0/NEWS --- old/queuelib-1.7.0/NEWS 2024-05-04 08:02:38.000000000 +0200 +++ new/queuelib-1.8.0/NEWS 2020-02-02 01:00:00.000000000 +0100 @@ -1,6 +1,18 @@ Queuelib release notes ====================== +Version 1.8.0 +------------- +(released on March 31st, 2025) + +* Added support for Python 3.13 and PyPy 3.11 +* Removed support for Python 3.8 +* Queue classes now accept ``os.PathLike`` paths +* Fixed test failures on Windows +* Switched the build system to ``hatchling`` +* Improved linting and CI configuration + + Version 1.7.0 ------------- (released on May 4th, 2024) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/queuelib-1.7.0/PKG-INFO new/queuelib-1.8.0/PKG-INFO --- old/queuelib-1.7.0/PKG-INFO 2024-05-04 08:02:51.436710800 +0200 +++ new/queuelib-1.8.0/PKG-INFO 2020-02-02 01:00:00.000000000 +0100 @@ -1,27 +1,29 @@ -Metadata-Version: 2.1 +Metadata-Version: 2.4 Name: queuelib -Version: 1.7.0 +Version: 1.8.0 Summary: Collection of persistent (disk-based) and non-persistent (memory-based) queues -Home-page: https://github.com/scrapy/queuelib -Author: Scrapy project -Author-email: i...@scrapy.org -License: BSD -Platform: Any +Project-URL: Homepage, https://github.com/scrapy/queuelib +Project-URL: Source, https://github.com/scrapy/queuelib +Project-URL: Issues, https://github.com/scrapy/queuelib/issues +Project-URL: Docs, https://github.com/scrapy/queuelib/blob/master/README.rst +Project-URL: ReleaseNotes, https://github.com/scrapy/queuelib/blob/master/NEWS +Project-URL: Changelog, https://github.com/scrapy/queuelib/commits/master/ +Author-email: Scrapy project <i...@scrapy.org> +License-Expression: BSD-3-Clause +License-File: LICENSE Classifier: Development Status :: 5 - Production/Stable -Classifier: License :: OSI Approved :: BSD License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 Classifier: Programming Language :: Python :: 3.12 +Classifier: Programming Language :: Python :: 3.13 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy -Requires-Python: >=3.8 +Requires-Python: >=3.9 Description-Content-Type: text/x-rst -License-File: LICENSE ======== queuelib @@ -33,8 +35,8 @@ .. image:: https://img.shields.io/pypi/pyversions/queuelib.svg :target: https://pypi.python.org/pypi/queuelib -.. image:: https://github.com/scrapy/queuelib/actions/workflows/tests.yml/badge.svg - :target: https://github.com/scrapy/queuelib/actions/workflows/tests.yml +.. image:: https://github.com/scrapy/queuelib/actions/workflows/tests-ubuntu.yml/badge.svg + :target: https://github.com/scrapy/queuelib/actions/workflows/tests-ubuntu.yml .. image:: https://img.shields.io/codecov/c/github/scrapy/queuelib/master.svg :target: http://codecov.io/github/scrapy/queuelib?branch=master @@ -49,7 +51,7 @@ .. note:: Queuelib collections are not thread-safe. -Queuelib supports Python 3.5+ and has no dependencies. +Queuelib supports Python 3.9+ and has no dependencies. .. _queues: https://en.wikipedia.org/wiki/FIFO_(computing_and_electronics) .. _round-robin: https://en.wikipedia.org/wiki/Round-robin_scheduling diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/queuelib-1.7.0/README.rst new/queuelib-1.8.0/README.rst --- old/queuelib-1.7.0/README.rst 2024-05-04 08:02:38.000000000 +0200 +++ new/queuelib-1.8.0/README.rst 2020-02-02 01:00:00.000000000 +0100 @@ -8,8 +8,8 @@ .. image:: https://img.shields.io/pypi/pyversions/queuelib.svg :target: https://pypi.python.org/pypi/queuelib -.. image:: https://github.com/scrapy/queuelib/actions/workflows/tests.yml/badge.svg - :target: https://github.com/scrapy/queuelib/actions/workflows/tests.yml +.. image:: https://github.com/scrapy/queuelib/actions/workflows/tests-ubuntu.yml/badge.svg + :target: https://github.com/scrapy/queuelib/actions/workflows/tests-ubuntu.yml .. image:: https://img.shields.io/codecov/c/github/scrapy/queuelib/master.svg :target: http://codecov.io/github/scrapy/queuelib?branch=master @@ -24,7 +24,7 @@ .. note:: Queuelib collections are not thread-safe. -Queuelib supports Python 3.5+ and has no dependencies. +Queuelib supports Python 3.9+ and has no dependencies. .. _queues: https://en.wikipedia.org/wiki/FIFO_(computing_and_electronics) .. _round-robin: https://en.wikipedia.org/wiki/Round-robin_scheduling diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/queuelib-1.7.0/pyproject.toml new/queuelib-1.8.0/pyproject.toml --- old/queuelib-1.7.0/pyproject.toml 2024-05-04 08:02:38.000000000 +0200 +++ new/queuelib-1.8.0/pyproject.toml 2020-02-02 01:00:00.000000000 +0100 @@ -1,17 +1,202 @@ -[tool.isort] -profile = "black" -multi_line_output = 3 - -[tool.mypy] -check_untyped_defs = true -ignore_missing_imports = true -no_warn_no_return = true +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[project] +name = "queuelib" +description = "Collection of persistent (disk-based) and non-persistent (memory-based) queues" +readme = "README.rst" +license = "BSD-3-Clause" +license-files = ["LICENSE"] +authors = [{ name = "Scrapy project", email = "i...@scrapy.org" }] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: Implementation :: CPython", + "Programming Language :: Python :: Implementation :: PyPy", +] +requires-python = ">=3.9" +dynamic = ["version"] + +[project.urls] +Homepage = "https://github.com/scrapy/queuelib" +Source = "https://github.com/scrapy/queuelib" +Issues = "https://github.com/scrapy/queuelib/issues" +Docs = "https://github.com/scrapy/queuelib/blob/master/README.rst" +ReleaseNotes = "https://github.com/scrapy/queuelib/blob/master/NEWS" +Changelog = "https://github.com/scrapy/queuelib/commits/master/" + +[tool.hatch.version] +path = "queuelib/__init__.py" + +[tool.hatch.build.targets.sdist] +include = [ + "/queuelib", + "/NEWS", +] + +[tool.bumpversion] +current_version = "1.8.0" +commit = true +tag = true +tag_name = "v{new_version}" + +[[tool.bumpversion.files]] +filename = "queuelib/__init__.py" + +[tool.coverage.run] +branch = true +omit = [ + "queuelib/tests/*", +] + +[tool.coverage.report] +exclude_also = [ + "if TYPE_CHECKING:", +] [[tool.mypy.overrides]] module = "queuelib.tests.*" allow_untyped_defs = true -allow_untyped_calls = true check_untyped_defs = false -[tool.black] -target-version = ["py38", "py39", "py310", "py311", "py312"] \ No newline at end of file +[tool.pylint.MASTER] +persistent = "no" + +[tool.pylint."MESSAGES CONTROL"] +enable = [ + "useless-suppression", +] +disable = [ + "consider-using-with", + "duplicate-code", + "invalid-name", + "line-too-long", + "missing-class-docstring", + "missing-function-docstring", + "missing-module-docstring", + "too-few-public-methods", + "unspecified-encoding", +] + +[tool.ruff.lint] +extend-select = [ + # flake8-bugbear + "B", + # flake8-comprehensions + "C4", + # pydocstyle + "D", + # flake8-future-annotations + "FA", + # flynt + "FLY", + # refurb + "FURB", + # isort + "I", + # flake8-implicit-str-concat + "ISC", + # flake8-logging + "LOG", + # Perflint + "PERF", + # pygrep-hooks + "PGH", + # flake8-pie + "PIE", + # pylint + "PL", + # flake8-use-pathlib + "PTH", + # flake8-pyi + "PYI", + # flake8-quotes + "Q", + # flake8-return + "RET", + # flake8-raise + "RSE", + # Ruff-specific rules + "RUF", + # flake8-bandit + "S", + # flake8-simplify + "SIM", + # flake8-slots + "SLOT", + # flake8-debugger + "T10", + # flake8-type-checking + "TC", + # pyupgrade + "UP", + # pycodestyle warnings + "W", + # flake8-2020 + "YTT", +] +ignore = [ + # Missing docstring in public module + "D100", + # Missing docstring in public class + "D101", + # Missing docstring in public method + "D102", + # Missing docstring in public function + "D103", + # Missing docstring in public package + "D104", + # Missing docstring in magic method + "D105", + # Missing docstring in public nested class + "D106", + # Missing docstring in __init__ + "D107", + # One-line docstring should fit on one line with quotes + "D200", + # No blank lines allowed after function docstring + "D202", + # 1 blank line required between summary line and description + "D205", + # Multi-line docstring closing quotes should be on a separate line + "D209", + # First line should end with a period + "D400", + # First line should be in imperative mood; try rephrasing + "D401", + # First line should not be the function's "signature" + "D402", + # First word of the first line should be properly capitalized + "D403", + # Too many return statements + "PLR0911", + # Too many branches + "PLR0912", + # Too many arguments in function definition + "PLR0913", + # Too many statements + "PLR0915", + # Magic value used in comparison + "PLR2004", + # String contains ambiguous {}. + "RUF001", + # Docstring contains ambiguous {}. + "RUF002", + # Comment contains ambiguous {}. + "RUF003", + # Mutable class attributes should be annotated with `typing.ClassVar` + "RUF012", + # Use of `assert` detected + "S101", +] + +[tool.ruff.lint.pydocstyle] +convention = "pep257" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/queuelib-1.7.0/queuelib/__init__.py new/queuelib-1.8.0/queuelib/__init__.py --- old/queuelib-1.7.0/queuelib/__init__.py 2024-05-04 08:02:38.000000000 +0200 +++ new/queuelib-1.8.0/queuelib/__init__.py 2020-02-02 01:00:00.000000000 +0100 @@ -1,5 +1,12 @@ -__version__ = "1.7.0" +__version__ = "1.8.0" from queuelib.pqueue import PriorityQueue from queuelib.queue import FifoDiskQueue, LifoDiskQueue from queuelib.rrqueue import RoundRobinQueue + +__all__ = [ + "FifoDiskQueue", + "LifoDiskQueue", + "PriorityQueue", + "RoundRobinQueue", +] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/queuelib-1.7.0/queuelib/pqueue.py new/queuelib-1.8.0/queuelib/pqueue.py --- old/queuelib-1.7.0/queuelib/pqueue.py 2024-05-04 08:02:38.000000000 +0200 +++ new/queuelib-1.8.0/queuelib/pqueue.py 2020-02-02 01:00:00.000000000 +0100 @@ -1,6 +1,11 @@ -from typing import Any, Callable, Iterable, List, Optional +from __future__ import annotations -from queuelib.queue import BaseQueue +from typing import TYPE_CHECKING, Any, Callable + +if TYPE_CHECKING: + from collections.abc import Iterable + + from queuelib.queue import BaseQueue class PriorityQueue: @@ -44,7 +49,7 @@ if self.curprio is None or priority < self.curprio: self.curprio = priority - def pop(self) -> Optional[Any]: + def pop(self) -> Any | None: if self.curprio is None: return None q = self.queues[self.curprio] @@ -56,12 +61,12 @@ self.curprio = min(prios) if prios else None return m - def peek(self) -> Optional[Any]: + def peek(self) -> Any | None: if self.curprio is None: return None return self.queues[self.curprio].peek() - def close(self) -> List[int]: + def close(self) -> list[int]: active = [] for p, q in self.queues.items(): if len(q): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/queuelib-1.7.0/queuelib/queue.py new/queuelib-1.8.0/queuelib/queue.py --- old/queuelib-1.7.0/queuelib/queue.py 2024-05-04 08:02:38.000000000 +0200 +++ new/queuelib-1.8.0/queuelib/queue.py 2020-02-02 01:00:00.000000000 +0100 @@ -1,4 +1,5 @@ -import glob +from __future__ import annotations + import json import os import sqlite3 @@ -6,7 +7,8 @@ from abc import abstractmethod from collections import deque from contextlib import suppress -from typing import Any, BinaryIO, Deque, Dict, Literal, Optional, cast +from pathlib import Path +from typing import Any, BinaryIO, Literal, cast class _BaseQueueMeta(type): @@ -37,19 +39,19 @@ class BaseQueue(metaclass=_BaseQueueMeta): @abstractmethod def push(self, obj: Any) -> None: - raise NotImplementedError() + raise NotImplementedError @abstractmethod - def pop(self) -> Optional[Any]: - raise NotImplementedError() + def pop(self) -> Any | None: + raise NotImplementedError @abstractmethod - def peek(self) -> Optional[Any]: - raise NotImplementedError() + def peek(self) -> Any | None: + raise NotImplementedError @abstractmethod def __len__(self) -> int: - raise NotImplementedError() + raise NotImplementedError def close(self) -> None: pass @@ -59,15 +61,15 @@ """In-memory FIFO queue, API compliant with FifoDiskQueue.""" def __init__(self) -> None: - self.q: Deque[Any] = deque() + self.q: deque[Any] = deque() def push(self, obj: Any) -> None: self.q.append(obj) - def pop(self) -> Optional[Any]: + def pop(self) -> Any | None: return self.q.popleft() if self.q else None - def peek(self) -> Optional[Any]: + def peek(self) -> Any | None: return self.q[0] if self.q else None def close(self) -> None: @@ -80,10 +82,10 @@ class LifoMemoryQueue(FifoMemoryQueue): """In-memory LIFO queue, API compliant with LifoDiskQueue.""" - def pop(self) -> Optional[Any]: + def pop(self) -> Any | None: return self.q.pop() if self.q else None - def peek(self) -> Optional[Any]: + def peek(self) -> Any | None: return self.q[-1] if self.q else None @@ -93,10 +95,10 @@ szhdr_format = ">L" szhdr_size = struct.calcsize(szhdr_format) - def __init__(self, path: str, chunksize: int = 100000) -> None: - self.path = path - if not os.path.exists(path): - os.makedirs(path) + def __init__(self, path: str | os.PathLike[str], chunksize: int = 100000) -> None: + self.path = str(path) + if not Path(path).exists(): + Path(path).mkdir(parents=True) self.info = self._loadinfo(chunksize) self.chunksize = self.info["chunksize"] self.headf = self._openchunk(self.info["head"][0], "ab+") @@ -119,9 +121,9 @@ self.info["head"] = [hnum, hpos] def _openchunk(self, number: int, mode: Literal["rb", "ab+"] = "rb") -> BinaryIO: - return open(os.path.join(self.path, f"q{number:05d}"), mode) + return Path(self.path, f"q{number:05d}").open(mode) - def pop(self) -> Optional[bytes]: + def pop(self) -> bytes | None: tnum, tcnt, toffset = self.info["tail"] if [tnum, tcnt] >= self.info["head"]: return None @@ -137,13 +139,13 @@ tcnt = toffset = 0 tnum += 1 self.tailf.close() - os.remove(self.tailf.name) + Path(self.tailf.name).unlink() self.tailf = self._openchunk(tnum) self.info["size"] -= 1 self.info["tail"] = [tnum, tcnt, toffset] return data - def peek(self) -> Optional[bytes]: + def peek(self) -> bytes | None: tnum, tcnt, _ = self.info["tail"] if [tnum, tcnt] >= self.info["head"]: return None @@ -167,11 +169,10 @@ def __len__(self) -> int: return cast(int, self.info["size"]) - def _loadinfo(self, chunksize: int) -> Dict[str, Any]: + def _loadinfo(self, chunksize: int) -> dict[str, Any]: infopath = self._infopath() - if os.path.exists(infopath): - with open(infopath) as f: - info = cast(Dict[str, Any], json.load(f)) + if infopath.exists(): + info = cast(dict[str, Any], json.loads(infopath.read_text())) else: info = { "chunksize": chunksize, @@ -181,19 +182,18 @@ } return info - def _saveinfo(self, info: Dict[str, Any]) -> None: - with open(self._infopath(), "w") as f: - json.dump(info, f) + def _saveinfo(self, info: dict[str, Any]) -> None: + self._infopath().write_text(json.dumps(info)) - def _infopath(self) -> str: - return os.path.join(self.path, "info.json") + def _infopath(self) -> Path: + return Path(self.path, "info.json") def _cleanup(self) -> None: - for x in glob.glob(os.path.join(self.path, "q*")): - os.remove(x) - os.remove(os.path.join(self.path, "info.json")) + for x in Path(self.path).glob("q*"): + x.unlink() + Path(self.path, "info.json").unlink() with suppress(OSError): - os.rmdir(self.path) + Path(self.path).rmdir() class LifoDiskQueue: @@ -202,16 +202,16 @@ SIZE_FORMAT = ">L" SIZE_SIZE = struct.calcsize(SIZE_FORMAT) - def __init__(self, path: str) -> None: + def __init__(self, path: str | os.PathLike[str]) -> None: self.size: int - self.path = path - if os.path.exists(path): - self.f = open(path, "rb+") + self.path = str(path) + if Path(path).exists(): + self.f = Path(path).open("rb+") # noqa: SIM115 qsize = self.f.read(self.SIZE_SIZE) (self.size,) = struct.unpack(self.SIZE_FORMAT, qsize) self.f.seek(0, os.SEEK_END) else: - self.f = open(path, "wb+") + self.f = Path(path).open("wb+") # noqa: SIM115 self.f.write(struct.pack(self.SIZE_FORMAT, 0)) self.size = 0 @@ -223,7 +223,7 @@ self.f.write(ssize) self.size += 1 - def pop(self) -> Optional[bytes]: + def pop(self) -> bytes | None: if not self.size: return None self.f.seek(-self.SIZE_SIZE, os.SEEK_END) @@ -235,14 +235,13 @@ self.size -= 1 return data - def peek(self) -> Optional[bytes]: + def peek(self) -> bytes | None: if not self.size: return None self.f.seek(-self.SIZE_SIZE, os.SEEK_END) (size,) = struct.unpack(self.SIZE_FORMAT, self.f.read()) self.f.seek(-size - self.SIZE_SIZE, os.SEEK_END) - data = self.f.read(size) - return data + return self.f.read(size) def close(self) -> None: if self.size: @@ -250,7 +249,7 @@ self.f.write(struct.pack(self.SIZE_FORMAT, self.size)) self.f.close() if not self.size: - os.remove(self.path) + Path(self.path).unlink() def __len__(self) -> int: return self.size @@ -263,8 +262,8 @@ _sql_pop = "SELECT id, item FROM queue ORDER BY id LIMIT 1" _sql_del = "DELETE FROM queue WHERE id = ?" - def __init__(self, path: str) -> None: - self._path = os.path.abspath(path) + def __init__(self, path: str | os.PathLike[str]) -> None: + self._path = Path(path).resolve() self._db = sqlite3.Connection(self._path, timeout=60) self._db.text_factory = bytes with self._db as conn: @@ -276,14 +275,14 @@ with self._db as conn: conn.execute(self._sql_push, (item,)) - def pop(self) -> Optional[bytes]: + def pop(self) -> bytes | None: with self._db as conn: for id_, item in conn.execute(self._sql_pop): conn.execute(self._sql_del, (id_,)) return cast(bytes, item) return None - def peek(self) -> Optional[bytes]: + def peek(self) -> bytes | None: with self._db as conn: for _, item in conn.execute(self._sql_pop): return cast(bytes, item) @@ -293,7 +292,7 @@ size = len(self) self._db.close() if not size: - os.remove(self._path) + self._path.unlink() def __len__(self) -> int: with self._db as conn: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/queuelib-1.7.0/queuelib/rrqueue.py new/queuelib-1.8.0/queuelib/rrqueue.py --- old/queuelib-1.7.0/queuelib/rrqueue.py 2024-05-04 08:02:38.000000000 +0200 +++ new/queuelib-1.8.0/queuelib/rrqueue.py 2020-02-02 01:00:00.000000000 +0100 @@ -1,8 +1,12 @@ +from __future__ import annotations + from collections import deque -from collections.abc import Hashable -from typing import Any, Callable, Iterable, List, Optional +from typing import TYPE_CHECKING, Any, Callable + +if TYPE_CHECKING: + from collections.abc import Hashable, Iterable -from queuelib.queue import BaseQueue + from queuelib.queue import BaseQueue class RoundRobinQueue: @@ -42,14 +46,14 @@ q = self.queues[key] q.push(obj) # this may fail (eg. serialization error) - def peek(self) -> Optional[Any]: + def peek(self) -> Any | None: try: key = self.key_queue[-1] except IndexError: return None return self.queues[key].peek() - def pop(self) -> Optional[Any]: + def pop(self) -> Any | None: # pop until we find a valid object, closing necessary queues while True: try: @@ -69,7 +73,7 @@ if m: return m - def close(self) -> List[Hashable]: + def close(self) -> list[Hashable]: active = [] for k, q in self.queues.items(): if len(q): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/queuelib-1.7.0/queuelib/tests/__init__.py new/queuelib-1.8.0/queuelib/tests/__init__.py --- old/queuelib-1.7.0/queuelib/tests/__init__.py 2024-05-04 08:02:38.000000000 +0200 +++ new/queuelib-1.8.0/queuelib/tests/__init__.py 2020-02-02 01:00:00.000000000 +0100 @@ -1,22 +1,24 @@ import shutil import tempfile import unittest +from pathlib import Path class QueuelibTestCase(unittest.TestCase): - def setUp(self): + def setUp(self) -> None: self.tmpdir = tempfile.mkdtemp(prefix="queuelib-tests-") - self.qpath = self.tempfilename() + self.qpath: Path = self.tempfilename() self.qdir = self.mkdtemp() - def tearDown(self): + def tearDown(self) -> None: + shutil.rmtree(self.qdir) shutil.rmtree(self.tmpdir) - def tempfilename(self): + def tempfilename(self) -> Path: with tempfile.NamedTemporaryFile(dir=self.tmpdir) as nf: - return nf.name + return Path(nf.name) - def mkdtemp(self): + def mkdtemp(self) -> str: return tempfile.mkdtemp(dir=self.tmpdir) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/queuelib-1.7.0/queuelib/tests/test_pqueue.py new/queuelib-1.8.0/queuelib/tests/test_pqueue.py --- old/queuelib-1.7.0/queuelib/tests/test_pqueue.py 2024-05-04 08:02:38.000000000 +0200 +++ new/queuelib-1.8.0/queuelib/tests/test_pqueue.py 2020-02-02 01:00:00.000000000 +0100 @@ -1,4 +1,4 @@ -import os +from pathlib import Path from queuelib.pqueue import PriorityQueue from queuelib.queue import ( @@ -179,7 +179,7 @@ PQueueTestMixin, FifoTestMixin, DiskTestMixin, QueuelibTestCase ): def qfactory(self, prio): - path = os.path.join(self.qdir, str(prio)) + path = Path(self.qdir, str(prio)) return track_closed(FifoDiskQueue)(path) @@ -187,7 +187,7 @@ PQueueTestMixin, LifoTestMixin, DiskTestMixin, QueuelibTestCase ): def qfactory(self, prio): - path = os.path.join(self.qdir, str(prio)) + path = Path(self.qdir, str(prio)) return track_closed(LifoDiskQueue)(path) @@ -195,7 +195,7 @@ PQueueTestMixin, FifoTestMixin, DiskTestMixin, QueuelibTestCase ): def qfactory(self, prio): - path = os.path.join(self.qdir, str(prio)) + path = Path(self.qdir, str(prio)) return track_closed(FifoSQLiteQueue)(path) @@ -203,5 +203,5 @@ PQueueTestMixin, LifoTestMixin, DiskTestMixin, QueuelibTestCase ): def qfactory(self, prio): - path = os.path.join(self.qdir, str(prio)) + path = Path(self.qdir, str(prio)) return track_closed(LifoSQLiteQueue)(path) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/queuelib-1.7.0/queuelib/tests/test_queue.py new/queuelib-1.8.0/queuelib/tests/test_queue.py --- old/queuelib-1.7.0/queuelib/tests/test_queue.py 2024-05-04 08:02:38.000000000 +0200 +++ new/queuelib-1.8.0/queuelib/tests/test_queue.py 2020-02-02 01:00:00.000000000 +0100 @@ -1,7 +1,7 @@ -import glob -import os +from __future__ import annotations + from abc import abstractmethod -from typing import Any, List, Optional +from typing import Any from unittest import mock import pytest @@ -20,15 +20,15 @@ class DummyQueue: def __init__(self) -> None: - self.q: List[Any] = [] + self.q: list[Any] = [] def push(self, obj: Any) -> None: self.q.append(obj) - def pop(self) -> Optional[Any]: + def pop(self) -> Any | None: return self.q.pop() if self.q else None - def peek(self) -> Optional[Any]: + def peek(self) -> Any | None: return self.q[-1] if self.q else None def close(self) -> None: @@ -78,17 +78,19 @@ class QueueTestMixin: @abstractmethod def queue(self) -> BaseQueue: - raise NotImplementedError() + raise NotImplementedError def test_empty(self): """Empty queue test""" q = self.queue() assert q.pop() is None + q.close() def test_single_pushpop(self): q = self.queue() q.push(b"a") assert q.pop() == b"a" + q.close() def test_binary_element(self): elem = ( @@ -101,6 +103,7 @@ q = self.queue() q.push(elem) assert q.pop() == elem + q.close() def test_len(self): q = self.queue() @@ -114,6 +117,7 @@ q.pop() q.pop() self.assertEqual(len(q), 0) + q.close() def test_peek_one_element(self): q = self.queue() @@ -122,6 +126,7 @@ self.assertEqual(q.peek(), b"a") self.assertEqual(q.pop(), b"a") self.assertIsNone(q.peek()) + q.close() class FifoTestMixin: @@ -135,6 +140,7 @@ self.assertEqual(q.pop(), b"b") self.assertEqual(q.pop(), b"c") self.assertEqual(q.pop(), None) + q.close() def test_push_pop2(self): """Test interleaved push and pops""" @@ -149,6 +155,7 @@ self.assertEqual(q.pop(), b"c") self.assertEqual(q.pop(), b"d") self.assertEqual(q.pop(), b"e") + q.close() def test_peek_fifo(self): q = self.queue() @@ -166,6 +173,7 @@ self.assertEqual(q.peek(), b"c") self.assertEqual(q.pop(), b"c") self.assertIsNone(q.peek()) + q.close() class LifoTestMixin: @@ -179,6 +187,7 @@ self.assertEqual(q.pop(), b"b") self.assertEqual(q.pop(), b"a") self.assertEqual(q.pop(), None) + q.close() def test_push_pop2(self): """Test interleaved push and pops""" @@ -193,6 +202,7 @@ self.assertEqual(q.pop(), b"e") self.assertEqual(q.pop(), b"b") self.assertEqual(q.pop(), b"a") + q.close() def test_peek_lifo(self): q = self.queue() @@ -210,6 +220,7 @@ self.assertEqual(q.peek(), b"a") self.assertEqual(q.pop(), b"a") self.assertIsNone(q.peek()) + q.close() class PersistentTestMixin: @@ -224,6 +235,7 @@ self.assertRaises(TypeError, q.push, "") self.assertRaises(TypeError, q.push, None) self.assertRaises(TypeError, q.push, lambda x: x) + q.close() def test_text_in_windows(self): e1 = b"\r\n" @@ -233,6 +245,7 @@ q = self.queue() e2 = q.pop() self.assertEqual(e1, e2) + q.close() def test_close_open(self): """Test closing and re-opening keeps state""" @@ -257,19 +270,20 @@ q = self.queue() assert q.pop() is not None self.assertEqual(len(q), 0) + q.close() def test_cleanup(self): """Test queue dir is removed if queue is empty""" q = self.queue() values = [b"0", b"1", b"2", b"3", b"4"] - assert os.path.exists(self.qpath) + assert self.qpath.exists() for x in values: q.push(x) - for x in values: + for _ in values: q.pop() q.close() - assert not os.path.exists(self.qpath) + assert not self.qpath.exists() class FifoMemoryQueueTest(FifoTestMixin, QueueTestMixin, QueuelibTestCase): @@ -291,11 +305,13 @@ def test_not_szhdr(self): q = self.queue() q.push(b"something") - empty_file = open(self.tempfilename(), "w+") - with mock.patch.object(q, "tailf", empty_file): + with ( + self.tempfilename().open("w+") as empty_file, + mock.patch.object(q, "tailf", empty_file), + ): assert q.peek() is None assert q.pop() is None - empty_file.close() + q.close() def test_chunks(self): """Test chunks are created and removed""" @@ -304,13 +320,14 @@ for x in values: q.push(x) - chunks = glob.glob(os.path.join(self.qpath, "q*")) + chunks = list(self.qpath.glob("q*")) self.assertEqual(len(chunks), 5 // self.chunksize + 1) - for x in values: + for _ in values: q.pop() - chunks = glob.glob(os.path.join(self.qpath, "q*")) + chunks = list(self.qpath.glob("q*")) self.assertEqual(len(chunks), 1) + q.close() class ChunkSize1FifoDiskQueueTest(FifoDiskQueueTest): @@ -341,11 +358,11 @@ q.push(b"a") q.push(b"b") q.close() - size = os.path.getsize(self.qpath) + size = self.qpath.stat().st_size q = self.queue() q.pop() q.close() - assert os.path.getsize(self.qpath), size + assert self.qpath.stat().st_size, size class FifoSQLiteQueueTest( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/queuelib-1.7.0/queuelib/tests/test_rrqueue.py new/queuelib-1.8.0/queuelib/tests/test_rrqueue.py --- old/queuelib-1.7.0/queuelib/tests/test_rrqueue.py 2024-05-04 08:02:38.000000000 +0200 +++ new/queuelib-1.8.0/queuelib/tests/test_rrqueue.py 2020-02-02 01:00:00.000000000 +0100 @@ -1,4 +1,4 @@ -import os +from pathlib import Path from queuelib.queue import ( FifoDiskQueue, @@ -130,7 +130,7 @@ RRQueueTestMixin, FifoTestMixin, DiskTestMixin, QueuelibTestCase ): def qfactory(self, key): - path = os.path.join(self.qdir, str(key)) + path = Path(self.qdir, str(key)) return track_closed(FifoDiskQueue)(path) @@ -138,7 +138,7 @@ RRQueueTestMixin, LifoTestMixin, DiskTestMixin, QueuelibTestCase ): def qfactory(self, key): - path = os.path.join(self.qdir, str(key)) + path = Path(self.qdir, str(key)) return track_closed(LifoDiskQueue)(path) @@ -146,7 +146,7 @@ RRQueueTestMixin, FifoTestMixin, DiskTestMixin, QueuelibTestCase ): def qfactory(self, key): - path = os.path.join(self.qdir, str(key)) + path = Path(self.qdir, str(key)) return track_closed(FifoSQLiteQueue)(path) @@ -154,7 +154,7 @@ RRQueueTestMixin, LifoTestMixin, DiskTestMixin, QueuelibTestCase ): def qfactory(self, key): - path = os.path.join(self.qdir, str(key)) + path = Path(self.qdir, str(key)) return track_closed(LifoSQLiteQueue)(path) @@ -199,23 +199,23 @@ class FifoDiskRRQueueStartDomainsTest(RRQueueStartDomainsTestMixin, QueuelibTestCase): def qfactory(self, key): - path = os.path.join(self.qdir, str(key)) + path = Path(self.qdir, str(key)) return track_closed(FifoDiskQueue)(path) class LifoDiskRRQueueStartDomainsTest(RRQueueStartDomainsTestMixin, QueuelibTestCase): def qfactory(self, key): - path = os.path.join(self.qdir, str(key)) + path = Path(self.qdir, str(key)) return track_closed(LifoDiskQueue)(path) class FifoSQLiteRRQueueStartDomainsTest(RRQueueStartDomainsTestMixin, QueuelibTestCase): def qfactory(self, key): - path = os.path.join(self.qdir, str(key)) + path = Path(self.qdir, str(key)) return track_closed(FifoSQLiteQueue)(path) class LifoSQLiteRRQueueStartDomainsTest(RRQueueStartDomainsTestMixin, QueuelibTestCase): def qfactory(self, key): - path = os.path.join(self.qdir, str(key)) + path = Path(self.qdir, str(key)) return track_closed(LifoSQLiteQueue)(path) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/queuelib-1.7.0/queuelib.egg-info/PKG-INFO new/queuelib-1.8.0/queuelib.egg-info/PKG-INFO --- old/queuelib-1.7.0/queuelib.egg-info/PKG-INFO 2024-05-04 08:02:51.000000000 +0200 +++ new/queuelib-1.8.0/queuelib.egg-info/PKG-INFO 1970-01-01 01:00:00.000000000 +0100 @@ -1,214 +0,0 @@ -Metadata-Version: 2.1 -Name: queuelib -Version: 1.7.0 -Summary: Collection of persistent (disk-based) and non-persistent (memory-based) queues -Home-page: https://github.com/scrapy/queuelib -Author: Scrapy project -Author-email: i...@scrapy.org -License: BSD -Platform: Any -Classifier: Development Status :: 5 - Production/Stable -Classifier: License :: OSI Approved :: BSD License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.8 -Classifier: Programming Language :: Python :: 3.9 -Classifier: Programming Language :: Python :: 3.10 -Classifier: Programming Language :: Python :: 3.11 -Classifier: Programming Language :: Python :: 3.12 -Classifier: Programming Language :: Python :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Requires-Python: >=3.8 -Description-Content-Type: text/x-rst -License-File: LICENSE - -======== -queuelib -======== - -.. image:: https://img.shields.io/pypi/v/queuelib.svg - :target: https://pypi.python.org/pypi/queuelib - -.. image:: https://img.shields.io/pypi/pyversions/queuelib.svg - :target: https://pypi.python.org/pypi/queuelib - -.. image:: https://github.com/scrapy/queuelib/actions/workflows/tests.yml/badge.svg - :target: https://github.com/scrapy/queuelib/actions/workflows/tests.yml - -.. image:: https://img.shields.io/codecov/c/github/scrapy/queuelib/master.svg - :target: http://codecov.io/github/scrapy/queuelib?branch=master - :alt: Coverage report - - -Queuelib is a Python library that implements object collections which are stored -in memory or persisted to disk, provide a simple API, and run fast. - -Queuelib provides collections for queues_ (FIFO), stacks_ (LIFO), queues -sorted by priority and queues that are emptied in a round-robin_ fashion. - -.. note:: Queuelib collections are not thread-safe. - -Queuelib supports Python 3.5+ and has no dependencies. - -.. _queues: https://en.wikipedia.org/wiki/FIFO_(computing_and_electronics) -.. _round-robin: https://en.wikipedia.org/wiki/Round-robin_scheduling -.. _stacks: https://en.wikipedia.org/wiki/Stack_(abstract_data_type) - -Installation -============ - -You can install Queuelib either via the Python Package Index (PyPI) or from -source. - -To install using pip:: - - $ pip install queuelib - -To install using easy_install:: - - $ easy_install queuelib - -If you have downloaded a source tarball you can install it by running the -following (as root):: - - # python setup.py install - -FIFO/LIFO disk queues -===================== - -Queuelib provides FIFO and LIFO queue implementations. - -Here is an example usage of the FIFO queue:: - - >>> from queuelib import FifoDiskQueue - >>> q = FifoDiskQueue("queuefile") - >>> q.push(b'a') - >>> q.push(b'b') - >>> q.push(b'c') - >>> q.pop() - b'a' - >>> q.close() - >>> q = FifoDiskQueue("queuefile") - >>> q.pop() - b'b' - >>> q.pop() - b'c' - >>> q.pop() - >>> - -The LIFO queue is identical (API-wise), but importing ``LifoDiskQueue`` -instead. - -PriorityQueue -============= - -A discrete-priority queue implemented by combining multiple FIFO/LIFO queues -(one per priority). - -First, select the type of queue to be used per priority (FIFO or LIFO):: - - >>> from queuelib import FifoDiskQueue - >>> qfactory = lambda priority: FifoDiskQueue('queue-dir-%s' % priority) - -Then instantiate the Priority Queue with it:: - - >>> from queuelib import PriorityQueue - >>> pq = PriorityQueue(qfactory) - -And use it:: - - >>> pq.push(b'a', 3) - >>> pq.push(b'b', 1) - >>> pq.push(b'c', 2) - >>> pq.push(b'd', 2) - >>> pq.pop() - b'b' - >>> pq.pop() - b'c' - >>> pq.pop() - b'd' - >>> pq.pop() - b'a' - -RoundRobinQueue -=============== - -Has nearly the same interface and implementation as a Priority Queue except -that each element must be pushed with a (mandatory) key. Popping from the -queue cycles through the keys "round robin". - -Instantiate the Round Robin Queue similarly to the Priority Queue:: - - >>> from queuelib import RoundRobinQueue - >>> rr = RoundRobinQueue(qfactory) - -And use it:: - - >>> rr.push(b'a', '1') - >>> rr.push(b'b', '1') - >>> rr.push(b'c', '2') - >>> rr.push(b'd', '2') - >>> rr.pop() - b'a' - >>> rr.pop() - b'c' - >>> rr.pop() - b'b' - >>> rr.pop() - b'd' - - -Mailing list -============ - -Use the `scrapy-users`_ mailing list for questions about Queuelib. - -Bug tracker -=========== - -If you have any suggestions, bug reports or annoyances please report them to -our issue tracker at: http://github.com/scrapy/queuelib/issues/ - -Contributing -============ - -Development of Queuelib happens at GitHub: http://github.com/scrapy/queuelib - -You are highly encouraged to participate in the development. If you don't like -GitHub (for some reason) you're welcome to send regular patches. - -All changes require tests to be merged. - -Tests -===== - -Tests are located in `queuelib/tests` directory. They can be run using -`nosetests`_ with the following command:: - - nosetests - -The output should be something like the following:: - - $ nosetests - ............................................................................. - ---------------------------------------------------------------------- - Ran 77 tests in 0.145s - - OK - -License -======= - -This software is licensed under the BSD License. See the LICENSE file in the -top distribution directory for the full license text. - -Versioning -========== - -This software follows `Semantic Versioning`_ - -.. _Scrapy framework: http://scrapy.org -.. _scrapy-users: http://groups.google.com/group/scrapy-users -.. _Semantic Versioning: http://semver.org/ -.. _nosetests: https://nose.readthedocs.org/en/latest/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/queuelib-1.7.0/queuelib.egg-info/SOURCES.txt new/queuelib-1.8.0/queuelib.egg-info/SOURCES.txt --- old/queuelib-1.7.0/queuelib.egg-info/SOURCES.txt 2024-05-04 08:02:51.000000000 +0200 +++ new/queuelib-1.8.0/queuelib.egg-info/SOURCES.txt 1970-01-01 01:00:00.000000000 +0100 @@ -1,20 +0,0 @@ -LICENSE -MANIFEST.in -NEWS -README.rst -pyproject.toml -setup.cfg -setup.py -queuelib/__init__.py -queuelib/pqueue.py -queuelib/py.typed -queuelib/queue.py -queuelib/rrqueue.py -queuelib.egg-info/PKG-INFO -queuelib.egg-info/SOURCES.txt -queuelib.egg-info/dependency_links.txt -queuelib.egg-info/top_level.txt -queuelib/tests/__init__.py -queuelib/tests/test_pqueue.py -queuelib/tests/test_queue.py -queuelib/tests/test_rrqueue.py \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/queuelib-1.7.0/queuelib.egg-info/dependency_links.txt new/queuelib-1.8.0/queuelib.egg-info/dependency_links.txt --- old/queuelib-1.7.0/queuelib.egg-info/dependency_links.txt 2024-05-04 08:02:51.000000000 +0200 +++ new/queuelib-1.8.0/queuelib.egg-info/dependency_links.txt 1970-01-01 01:00:00.000000000 +0100 @@ -1 +0,0 @@ - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/queuelib-1.7.0/queuelib.egg-info/top_level.txt new/queuelib-1.8.0/queuelib.egg-info/top_level.txt --- old/queuelib-1.7.0/queuelib.egg-info/top_level.txt 2024-05-04 08:02:51.000000000 +0200 +++ new/queuelib-1.8.0/queuelib.egg-info/top_level.txt 1970-01-01 01:00:00.000000000 +0100 @@ -1 +0,0 @@ -queuelib diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/queuelib-1.7.0/setup.cfg new/queuelib-1.8.0/setup.cfg --- old/queuelib-1.7.0/setup.cfg 2024-05-04 08:02:51.436710800 +0200 +++ new/queuelib-1.8.0/setup.cfg 1970-01-01 01:00:00.000000000 +0100 @@ -1,12 +0,0 @@ -[bdist_wheel] -universal = 1 - -[flake8] -max-line-length = 119 -per-file-ignores = - queuelib/__init__.py: F401 - -[egg_info] -tag_build = -tag_date = 0 - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/queuelib-1.7.0/setup.py new/queuelib-1.8.0/setup.py --- old/queuelib-1.7.0/setup.py 2024-05-04 08:02:38.000000000 +0200 +++ new/queuelib-1.8.0/setup.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,33 +0,0 @@ -from setuptools import find_packages, setup - -setup( - name="queuelib", - version="1.7.0", - license="BSD", - description="Collection of persistent (disk-based) and non-persistent (memory-based) queues", - long_description=open("README.rst").read(), - long_description_content_type="text/x-rst", - author="Scrapy project", - author_email="i...@scrapy.org", - url="https://github.com/scrapy/queuelib", - packages=find_packages(), - package_data={ - "queuelib": ["py.typed"], - }, - platforms=["Any"], - python_requires=">=3.8", - classifiers=[ - "Development Status :: 5 - Production/Stable", - "License :: OSI Approved :: BSD License", - "Operating System :: OS Independent", - "Programming Language :: Python", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: Implementation :: CPython", - "Programming Language :: Python :: Implementation :: PyPy", - ], -)