Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-pytest-localserver for openSUSE:Factory checked in at 2023-01-10 14:58:54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-pytest-localserver (Old) and /work/SRC/openSUSE:Factory/.python-pytest-localserver.new.32243 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-pytest-localserver" Tue Jan 10 14:58:54 2023 rev:5 rq:1057062 version:0.7.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-pytest-localserver/python-pytest-localserver.changes 2022-08-04 13:23:36.388523003 +0200 +++ /work/SRC/openSUSE:Factory/.python-pytest-localserver.new.32243/python-pytest-localserver.changes 2023-01-10 14:58:57.236931301 +0100 @@ -1,0 +2,10 @@ +Mon Jan 9 12:18:38 UTC 2023 - Dirk Müller <dmuel...@suse.com> + +- update to 0.7.0: + * Make smtp support an optional extra + * Update some obsolete syntax to drop support for Python 2 + * Add linting for code and workflow actions using pre-commit hooks + * Expand the range of pytest versions known to be compatible, with tests + * Add badges to README + +------------------------------------------------------------------- Old: ---- pytest-localserver-0.6.0.tar.gz New: ---- pytest-localserver-0.7.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-pytest-localserver.spec ++++++ --- /var/tmp/diff_new_pack.QiHb05/_old 2023-01-10 14:58:57.988935326 +0100 +++ /var/tmp/diff_new_pack.QiHb05/_new 2023-01-10 14:58:57.992935348 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-pytest-localserver # -# Copyright (c) 2022 SUSE LLC +# Copyright (c) 2023 SUSE LLC # Copyright (c) 2015 LISA GmbH, Bingen, Germany. # # All modifications and additions to the file contributed by third parties @@ -19,15 +19,18 @@ %{?!python_module:%define python_module() python3-%{**}} %define skip_python2 1 +%bcond_with extras Name: python-pytest-localserver -Version: 0.6.0 +Version: 0.7.0 Release: 0 Summary: Plugin for py.test to test server connections locally License: MIT URL: https://github.com/pytest-dev/pytest-localserver Source: https://files.pythonhosted.org/packages/source/p/pytest-localserver/pytest-localserver-%{version}.tar.gz BuildRequires: %{python_module Werkzeug >= 0.10} +%if %{with extras} BuildRequires: %{python_module aiosmtpd} +%endif BuildRequires: %{python_module pip} BuildRequires: %{python_module pytest >= 2.0.0} BuildRequires: %{python_module requests} ++++++ pytest-localserver-0.6.0.tar.gz -> pytest-localserver-0.7.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-localserver-0.6.0/.github/workflows/tests.yml new/pytest-localserver-0.7.0/.github/workflows/tests.yml --- old/pytest-localserver-0.6.0/.github/workflows/tests.yml 2022-05-05 21:38:00.000000000 +0200 +++ new/pytest-localserver-0.7.0/.github/workflows/tests.yml 2022-08-30 09:11:43.000000000 +0200 @@ -7,11 +7,25 @@ jobs: build: runs-on: ubuntu-latest + # https://wildwolf.name/github-actions-how-to-avoid-running-the-same-workflow-multiple-times/ + if: > + github.event_name != 'pull_request' + || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name strategy: matrix: # Not all Python versions are available for linux AND x64 # https://raw.githubusercontent.com/actions/python-versions/main/versions-manifest.json - python-version: [3.5, 3.6, 3.7, 3.8, 3.9, '3.10'] + python-version: [3.5, 3.6, 3.7, 3.8, 3.9, '3.10', '3.11.0-beta - 3.11', 'pypy-3.7', 'pypy-3.8', 'pypy-3.9'] + extra: ['', '-smtp'] + # The forced pytest versions correspond with the lower bounds in tox.ini + pytest-version: ['', '--force-dep pytest==4', '--force-dep pytest==6.2.4'] + exclude: + - python-version: '3.5' + pytest-version: '--force-dep pytest==6.2.4' + - python-version: '3.10' + pytest-version: '--force-dep pytest==4' + - python-version: '3.11.0-beta - 3.11' + pytest-version: '--force-dep pytest==4' fail-fast: false steps: @@ -23,6 +37,6 @@ - name: Install dependencies run: | python -m pip install --upgrade pip - pip install tox tox-gh-actions + pip install tox - name: Test with tox - run: tox -vv + run: tox -vv -e py${{ matrix.extra }} ${{ matrix.pytest-version }} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-localserver-0.6.0/.pre-commit-config.yaml new/pytest-localserver-0.7.0/.pre-commit-config.yaml --- old/pytest-localserver-0.6.0/.pre-commit-config.yaml 1970-01-01 01:00:00.000000000 +0100 +++ new/pytest-localserver-0.7.0/.pre-commit-config.yaml 2022-08-30 09:11:43.000000000 +0200 @@ -0,0 +1,48 @@ +repos: +- repo: https://github.com/psf/black + rev: 22.3.0 + hooks: + - id: black + args: [--safe, --quiet] + +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.2.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: fix-encoding-pragma + args: [--remove] + - id: check-yaml + language_version: python3 + +- repo: https://github.com/myint/autoflake + rev: v1.4 + hooks: + - id: autoflake + name: autoflake + args: ["--in-place", "--remove-unused-variables", "--remove-all-unused-imports"] + language: python + files: \.py$ + +- repo: https://github.com/PyCQA/flake8 + rev: 4.0.1 + hooks: + - id: flake8 + language_version: python3 + +- repo: https://github.com/asottile/reorder_python_imports + rev: v3.1.0 + hooks: + - id: reorder-python-imports + args: [--py3-plus] + +- repo: https://github.com/asottile/pyupgrade + rev: v2.32.1 + hooks: + - id: pyupgrade + args: [--py3-plus] + +- repo: https://github.com/rhysd/actionlint + rev: v1.6.15 + hooks: + - id: actionlint-docker diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-localserver-0.6.0/CHANGES new/pytest-localserver-0.7.0/CHANGES --- old/pytest-localserver-0.6.0/CHANGES 2022-05-05 21:38:00.000000000 +0200 +++ new/pytest-localserver-0.7.0/CHANGES 2022-08-30 09:11:43.000000000 +0200 @@ -1,3 +1,12 @@ +0.7.0 (2022-08-30) +------------------ + +Make smtp support an optional extra +Update some obsolete syntax to drop support for Python 2 +Add linting for code and workflow actions using pre-commit hooks +Expand the range of pytest versions known to be compatible, with tests +Add badges to README + 0.6.0 (2022-05-05) ------------------ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-localserver-0.6.0/PKG-INFO new/pytest-localserver-0.7.0/PKG-INFO --- old/pytest-localserver-0.6.0/PKG-INFO 2022-05-05 21:38:21.508000100 +0200 +++ new/pytest-localserver-0.7.0/PKG-INFO 2022-08-30 09:12:14.724795300 +0200 @@ -1,15 +1,14 @@ Metadata-Version: 2.1 Name: pytest-localserver -Version: 0.6.0 -Summary: py.test plugin to test server connections locally. +Version: 0.7.0 +Summary: pytest plugin to test server connections locally. Home-page: https://github.com/pytest-dev/pytest-localserver Author: Sebastian Rahlf Author-email: ba...@redtoad.de Maintainer: David Zaslavsky Maintainer-email: diaz...@ellipsix.net License: MIT License -Keywords: py.test pytest server localhost http smtp -Platform: UNKNOWN +Keywords: pytest server localhost http smtp Classifier: Framework :: Pytest Classifier: Operating System :: OS Independent Classifier: Development Status :: 4 - Beta @@ -25,9 +24,25 @@ Classifier: Programming Language :: Python :: 3.10 Classifier: Topic :: Software Development :: Testing Requires-Python: >=3.5 +Provides-Extra: smtp License-File: LICENSE License-File: AUTHORS +.. image:: https://img.shields.io/pypi/v/pytest-localserver.svg?style=flat + :alt: PyPI Version + :target: https://pypi.python.org/pypi/pytest-localserver + +.. image:: https://img.shields.io/pypi/pyversions/pytest-localserver.svg + :alt: Supported Python versions + :target: https://pypi.python.org/pypi/pytest-localserver + +.. image:: https://img.shields.io/badge/code%20style-black-000000.svg + :target: https://github.com/psf/black + +.. image:: https://results.pre-commit.ci/badge/github/pytest-dev/pytest-localserver/master.svg + :target: https://results.pre-commit.ci/latest/github/pytest-dev/pytest-localserver/master + :alt: pre-commit.ci status + ================== pytest-localserver ================== @@ -118,7 +133,7 @@ * ``Chunked.YES``, telling the server to always apply chunk encoding * ``Chunked.NO``, telling the server to never apply chunk encoding * ``Chunked.AUTO``, telling the server to apply chunk encoding only if - the ``Transfer-Encoding`` header includes ``chunked`` + the ``Transfer-Encoding`` header includes ``chunked`` If chunk encoding is applied, each str or bytes in ``content`` becomes one chunk in the response. @@ -269,5 +284,3 @@ .. _build: https://pypa-build.readthedocs.io/en/latest/ .. _twine: https://twine.readthedocs.io/en/stable/ .. _new release form on Github: https://github.com/pytest-dev/pytest-localserver/releases/new - - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-localserver-0.6.0/README.rst new/pytest-localserver-0.7.0/README.rst --- old/pytest-localserver-0.6.0/README.rst 2022-05-05 21:38:00.000000000 +0200 +++ new/pytest-localserver-0.7.0/README.rst 2022-08-30 09:11:43.000000000 +0200 @@ -1,3 +1,18 @@ +.. image:: https://img.shields.io/pypi/v/pytest-localserver.svg?style=flat + :alt: PyPI Version + :target: https://pypi.python.org/pypi/pytest-localserver + +.. image:: https://img.shields.io/pypi/pyversions/pytest-localserver.svg + :alt: Supported Python versions + :target: https://pypi.python.org/pypi/pytest-localserver + +.. image:: https://img.shields.io/badge/code%20style-black-000000.svg + :target: https://github.com/psf/black + +.. image:: https://results.pre-commit.ci/badge/github/pytest-dev/pytest-localserver/master.svg + :target: https://results.pre-commit.ci/latest/github/pytest-dev/pytest-localserver/master + :alt: pre-commit.ci status + ================== pytest-localserver ================== @@ -88,7 +103,7 @@ * ``Chunked.YES``, telling the server to always apply chunk encoding * ``Chunked.NO``, telling the server to never apply chunk encoding * ``Chunked.AUTO``, telling the server to apply chunk encoding only if - the ``Transfer-Encoding`` header includes ``chunked`` + the ``Transfer-Encoding`` header includes ``chunked`` If chunk encoding is applied, each str or bytes in ``content`` becomes one chunk in the response. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-localserver-0.6.0/pyproject.toml new/pytest-localserver-0.7.0/pyproject.toml --- old/pytest-localserver-0.6.0/pyproject.toml 2022-05-05 21:38:00.000000000 +0200 +++ new/pytest-localserver-0.7.0/pyproject.toml 2022-08-30 09:11:43.000000000 +0200 @@ -1,6 +1,10 @@ [build-system] -requires = ["setuptools >=42", "setuptools_scm[toml] >=3.4.1", "wheel"] +requires = ["setuptools >=42", "setuptools_scm[toml] >=3.4.1"] build-backend = "setuptools.build_meta" [tool.setuptools_scm] write_to = "pytest_localserver/_version.py" + +[tool.black] +target-version = ['py35'] +line-length = 120 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-localserver-0.6.0/pytest_localserver/__init__.py new/pytest-localserver-0.7.0/pytest_localserver/__init__.py --- old/pytest-localserver-0.6.0/pytest_localserver/__init__.py 2022-05-05 21:38:00.000000000 +0200 +++ new/pytest-localserver-0.7.0/pytest_localserver/__init__.py 2022-08-30 09:11:43.000000000 +0200 @@ -1 +1 @@ -from pytest_localserver._version import version as VERSION +from pytest_localserver._version import version as VERSION # noqa diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-localserver-0.6.0/pytest_localserver/_version.py new/pytest-localserver-0.7.0/pytest_localserver/_version.py --- old/pytest-localserver-0.6.0/pytest_localserver/_version.py 2022-05-05 21:38:19.000000000 +0200 +++ new/pytest-localserver-0.7.0/pytest_localserver/_version.py 2022-08-30 09:12:14.000000000 +0200 @@ -1,5 +1,5 @@ # coding: utf-8 # file generated by setuptools_scm # don't change, don't track in version control -version = '0.6.0' -version_tuple = (0, 6, 0) +__version__ = version = '0.7.0' +__version_tuple__ = version_tuple = (0, 7, 0) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-localserver-0.6.0/pytest_localserver/http.py new/pytest-localserver-0.7.0/pytest_localserver/http.py --- old/pytest-localserver-0.6.0/pytest_localserver/http.py 2022-05-05 21:38:00.000000000 +0200 +++ new/pytest-localserver-0.7.0/pytest_localserver/http.py 2022-08-30 09:11:43.000000000 +0200 @@ -2,7 +2,6 @@ # # This program is release under the MIT license. You can find the full text of # the license in the LICENSE file. - import enum import itertools import json @@ -11,7 +10,8 @@ from werkzeug.datastructures import Headers from werkzeug.serving import make_server -from werkzeug.wrappers import Response, Request +from werkzeug.wrappers import Request +from werkzeug.wrappers import Response class WSGIServer(threading.Thread): @@ -20,14 +20,12 @@ HTTP server running a WSGI application in its own thread. """ - def __init__(self, host='127.0.0.1', port=0, application=None, **kwargs): + def __init__(self, host="127.0.0.1", port=0, application=None, **kwargs): self.app = application self._server = make_server(host, port, self.app, **kwargs) self.server_address = self._server.server_address - super(WSGIServer, self).__init__( - name=self.__class__, - target=self._server.serve_forever) + super().__init__(name=self.__class__, target=self._server.serve_forever) def __del__(self): self.stop() @@ -38,8 +36,8 @@ @property def url(self): host, port = self.server_address - proto = 'http' if self._server.ssl_context is None else 'https' - return '%s://%s:%i' % (proto, host, port) + proto = "http" if self._server.ssl_context is None else "https" + return "%s://%s:%i" % (proto, host, port) class Chunked(enum.Enum): @@ -54,7 +52,7 @@ def _encode_chunk(chunk, charset): if isinstance(chunk, str): chunk = chunk.encode(charset) - return '{0:x}'.format(len(chunk)).encode(charset) + b'\r\n' + chunk + b'\r\n' + return "{:x}".format(len(chunk)).encode(charset) + b"\r\n" + chunk + b"\r\n" class ContentServer(WSGIServer): @@ -78,9 +76,9 @@ """ - def __init__(self, host='127.0.0.1', port=0, ssl_context=None): - super(ContentServer, self).__init__(host, port, self, ssl_context=ssl_context) - self.content, self.code = ('', 204) # HTTP 204: No Content + def __init__(self, host="127.0.0.1", port=0, ssl_context=None): + super().__init__(host, port, self, ssl_context=ssl_context) + self.content, self.code = ("", 204) # HTTP 204: No Content self.headers = {} self.show_post_vars = False self.compress = None @@ -93,25 +91,27 @@ """ request = Request(environ) self.requests.append(request) - if (request.content_type == 'application/x-www-form-urlencoded' - and request.method == 'POST' and self.show_post_vars): + if ( + request.content_type == "application/x-www-form-urlencoded" + and request.method == "POST" + and self.show_post_vars + ): content = json.dumps(request.form) else: content = self.content - if ( - self.chunked == Chunked.YES - or (self.chunked == Chunked.AUTO and 'chunked' in self.headers.get('Transfer-encoding', '')) + if self.chunked == Chunked.YES or ( + self.chunked == Chunked.AUTO and "chunked" in self.headers.get("Transfer-encoding", "") ): # If the code below ever changes to allow setting the charset of # the Response object, the charset used here should also be changed # to match. But until that happens, use UTF-8 since it is Werkzeug's # default. - charset = 'utf-8' + charset = "utf-8" if isinstance(content, (str, bytes)): - content = (_encode_chunk(content, charset), '0\r\n\r\n') + content = (_encode_chunk(content, charset), "0\r\n\r\n") else: - content = itertools.chain((_encode_chunk(item, charset) for item in content), ['0\r\n\r\n']) + content = itertools.chain((_encode_chunk(item, charset) for item in content), ["0\r\n\r\n"]) response = Response(response=content, status=self.code) response.headers.clear() @@ -152,7 +152,7 @@ self.headers = Headers(headers) -if __name__ == '__main__': # pragma: no cover +if __name__ == "__main__": # pragma: no cover import os.path import time @@ -160,14 +160,13 @@ server = WSGIServer(application=app) server.start() - print('HTTP server is running at %s' % server.url) - print('Type <Ctrl-C> to stop') + print("HTTP server is running at %s" % server.url) + print("Type <Ctrl-C> to stop") try: path = sys.argv[1] except IndexError: - path = os.path.join( - os.path.dirname(os.path.abspath(__file__)), '..', 'README.rst') + path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "README.rst") app.serve_content(open(path).read(), 302) @@ -175,5 +174,5 @@ while True: time.sleep(1) except KeyboardInterrupt: - print('\rstopping...') + print("\rstopping...") server.stop() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-localserver-0.6.0/pytest_localserver/https.py new/pytest-localserver-0.7.0/pytest_localserver/https.py --- old/pytest-localserver-0.6.0/pytest_localserver/https.py 2022-05-05 21:38:00.000000000 +0200 +++ new/pytest-localserver-0.7.0/pytest_localserver/https.py 2022-08-30 09:11:43.000000000 +0200 @@ -2,17 +2,15 @@ # # This program is release under the MIT license. You can find the full text of # the license in the LICENSE file. - import os.path from pytest_localserver.http import ContentServer #: default server certificate -DEFAULT_CERTIFICATE = os.path.join( - os.path.abspath(os.path.dirname(__file__)), 'server.pem') +DEFAULT_CERTIFICATE = os.path.join(os.path.abspath(os.path.dirname(__file__)), "server.pem") -class SecureContentServer (ContentServer): +class SecureContentServer(ContentServer): """ Small test server which works just like :class:`http.Server` over HTTP:: @@ -109,39 +107,37 @@ A more advanced tutorial can be found `here`_. - .. _pytest-localserver CA: https://raw.githubusercontent.com/pytest-dev/pytest-localserver/master/pytest_localserver/ca.crt + .. _pytest-localserver CA: https://raw.githubusercontent.com/pytest-dev/pytest-localserver/master/pytest_localserver/ca.crt # noqa: E501 .. _pyOpenSSH: https://launchpad.net/pyopenssl """ - def __init__(self, host='localhost', port=0, - key=DEFAULT_CERTIFICATE, cert=DEFAULT_CERTIFICATE): + def __init__(self, host="localhost", port=0, key=DEFAULT_CERTIFICATE, cert=DEFAULT_CERTIFICATE): """ :param key: location of file containing the server private key. :param cert: location of file containing server certificate. """ - super(SecureContentServer, self).__init__(host, port, ssl_context=(key, cert)) + super().__init__(host, port, ssl_context=(key, cert)) -if __name__ == '__main__': # pragma: no cover +if __name__ == "__main__": # pragma: no cover import sys import time - print('Using certificate %s.' % DEFAULT_CERTIFICATE) + print("Using certificate %s." % DEFAULT_CERTIFICATE) server = SecureContentServer() server.start() server.logging = True - print('HTTPS server is running at %s' % server.url) - print('Type <Ctrl-C> to stop') + print("HTTPS server is running at %s" % server.url) + print("Type <Ctrl-C> to stop") try: path = sys.argv[1] except IndexError: - path = os.path.join( - os.path.dirname(os.path.abspath(__file__)), '..', 'README.rst') + path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "README.rst") server.serve_content(open(path).read(), 302) @@ -149,5 +145,5 @@ while True: time.sleep(1) except KeyboardInterrupt: - print('\rstopping...') + print("\rstopping...") server.stop() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-localserver-0.6.0/pytest_localserver/plugin.py new/pytest-localserver-0.7.0/pytest_localserver/plugin.py --- old/pytest-localserver-0.6.0/pytest_localserver/plugin.py 2022-05-05 21:38:00.000000000 +0200 +++ new/pytest-localserver-0.7.0/pytest_localserver/plugin.py 2022-08-30 09:11:43.000000000 +0200 @@ -1,5 +1,4 @@ #!/usr/bin/env python -# -*- coding: utf8 -*- # # Copyright (C) 2011 Sebastian Rahlf <basti at redtoad dot de> # @@ -49,6 +48,7 @@ """ from pytest_localserver import http + server = http.ContentServer() server.start() request.addfinalizer(server.stop) @@ -62,6 +62,7 @@ SSL encryption. """ from pytest_localserver import https + server = https.SecureContentServer() server.start() request.addfinalizer(server.stop) @@ -77,6 +78,7 @@ * ``addr`` - server address as tuple (host as str, port as int) """ from pytest_localserver import smtp + server = smtp.Server() server.start() request.addfinalizer(server.stop) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-localserver-0.6.0/pytest_localserver/smtp.py new/pytest-localserver-0.7.0/pytest_localserver/smtp.py --- old/pytest-localserver-0.6.0/pytest_localserver/smtp.py 2022-05-05 21:38:00.000000000 +0200 +++ new/pytest-localserver-0.7.0/pytest_localserver/smtp.py 2022-08-30 09:11:43.000000000 +0200 @@ -1,15 +1,13 @@ #!/usr/bin/env python -# -*- coding: utf8 -*- # # Copyright (C) 2011 Sebastian Rahlf <basti at redtoad dot de> # with some ideas from http://code.activestate.com/recipes/440690/ # SmtpMailsink Copyright 2005 Aviarc Corporation # Written by Adam Feuer, Matt Branthwaite, and Troy Frever # which is Licensed under the PSF License +import email import aiosmtpd.controller -import email -import sys class MessageDetails: @@ -31,7 +29,7 @@ message = email.message_from_bytes(envelope.content) message.details = MessageDetails(session.peer, envelope.mail_from, envelope.rcpt_tos) self.outbox.append(message) - return '250 OK' + return "250 OK" class Server(aiosmtpd.controller.Controller): @@ -57,7 +55,7 @@ """ - def __init__(self, host='localhost', port=0): + def __init__(self, host="localhost", port=0): try: super().__init__(Handler(), hostname=host, port=port, server_hostname=host) except TypeError: @@ -80,8 +78,8 @@ # would fail when calling super()._trigger_server(). In the future, when # we can safely require aiosmtpd >=1.4, this method can be inlined # directly into _trigger_server(). - if hasattr(self, 'addr'): - assert hasattr(self, 'port') + if hasattr(self, "addr"): + assert hasattr(self, "port") return self.addr = self.server.sockets[0].getsockname()[:2] @@ -112,7 +110,8 @@ return self.loop.is_running() # for aiosmtpd <1.4 - if not hasattr(aiosmtpd.controller.Controller, '_trigger_server'): + if not hasattr(aiosmtpd.controller.Controller, "_trigger_server"): + def start(self): super().start() self._set_server_socket_attributes() @@ -150,7 +149,8 @@ self.stop() def __repr__(self): # pragma: no cover - return '<smtp.Server %s:%s>' % self.addr + return "<smtp.Server %s:%s>" % self.addr + if __name__ == "__main__": # pragma: no cover import time @@ -158,8 +158,8 @@ server = Server() server.start() - print('SMTP server is running on %s:%i' % server.addr) - print('Type <Ctrl-C> to stop') + print("SMTP server is running on %s:%i" % server.addr) + print("Type <Ctrl-C> to stop") try: @@ -167,7 +167,7 @@ while True: time.sleep(1) finally: - print('\rstopping...') + print("\rstopping...") server.stop() except KeyboardInterrupt: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-localserver-0.6.0/pytest_localserver.egg-info/PKG-INFO new/pytest-localserver-0.7.0/pytest_localserver.egg-info/PKG-INFO --- old/pytest-localserver-0.6.0/pytest_localserver.egg-info/PKG-INFO 2022-05-05 21:38:20.000000000 +0200 +++ new/pytest-localserver-0.7.0/pytest_localserver.egg-info/PKG-INFO 2022-08-30 09:12:14.000000000 +0200 @@ -1,15 +1,14 @@ Metadata-Version: 2.1 Name: pytest-localserver -Version: 0.6.0 -Summary: py.test plugin to test server connections locally. +Version: 0.7.0 +Summary: pytest plugin to test server connections locally. Home-page: https://github.com/pytest-dev/pytest-localserver Author: Sebastian Rahlf Author-email: ba...@redtoad.de Maintainer: David Zaslavsky Maintainer-email: diaz...@ellipsix.net License: MIT License -Keywords: py.test pytest server localhost http smtp -Platform: UNKNOWN +Keywords: pytest server localhost http smtp Classifier: Framework :: Pytest Classifier: Operating System :: OS Independent Classifier: Development Status :: 4 - Beta @@ -25,9 +24,25 @@ Classifier: Programming Language :: Python :: 3.10 Classifier: Topic :: Software Development :: Testing Requires-Python: >=3.5 +Provides-Extra: smtp License-File: LICENSE License-File: AUTHORS +.. image:: https://img.shields.io/pypi/v/pytest-localserver.svg?style=flat + :alt: PyPI Version + :target: https://pypi.python.org/pypi/pytest-localserver + +.. image:: https://img.shields.io/pypi/pyversions/pytest-localserver.svg + :alt: Supported Python versions + :target: https://pypi.python.org/pypi/pytest-localserver + +.. image:: https://img.shields.io/badge/code%20style-black-000000.svg + :target: https://github.com/psf/black + +.. image:: https://results.pre-commit.ci/badge/github/pytest-dev/pytest-localserver/master.svg + :target: https://results.pre-commit.ci/latest/github/pytest-dev/pytest-localserver/master + :alt: pre-commit.ci status + ================== pytest-localserver ================== @@ -118,7 +133,7 @@ * ``Chunked.YES``, telling the server to always apply chunk encoding * ``Chunked.NO``, telling the server to never apply chunk encoding * ``Chunked.AUTO``, telling the server to apply chunk encoding only if - the ``Transfer-Encoding`` header includes ``chunked`` + the ``Transfer-Encoding`` header includes ``chunked`` If chunk encoding is applied, each str or bytes in ``content`` becomes one chunk in the response. @@ -269,5 +284,3 @@ .. _build: https://pypa-build.readthedocs.io/en/latest/ .. _twine: https://twine.readthedocs.io/en/stable/ .. _new release form on Github: https://github.com/pytest-dev/pytest-localserver/releases/new - - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-localserver-0.6.0/pytest_localserver.egg-info/SOURCES.txt new/pytest-localserver-0.7.0/pytest_localserver.egg-info/SOURCES.txt --- old/pytest-localserver-0.6.0/pytest_localserver.egg-info/SOURCES.txt 2022-05-05 21:38:21.000000000 +0200 +++ new/pytest-localserver-0.7.0/pytest_localserver.egg-info/SOURCES.txt 2022-08-30 09:12:14.000000000 +0200 @@ -1,4 +1,5 @@ .gitignore +.pre-commit-config.yaml AUTHORS CHANGES LICENSE diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-localserver-0.6.0/pytest_localserver.egg-info/requires.txt new/pytest-localserver-0.7.0/pytest_localserver.egg-info/requires.txt --- old/pytest-localserver-0.6.0/pytest_localserver.egg-info/requires.txt 2022-05-05 21:38:21.000000000 +0200 +++ new/pytest-localserver-0.7.0/pytest_localserver.egg-info/requires.txt 2022-08-30 09:12:14.000000000 +0200 @@ -1,2 +1,4 @@ werkzeug>=0.10 + +[smtp] aiosmtpd diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-localserver-0.6.0/runtests.py new/pytest-localserver-0.7.0/runtests.py --- old/pytest-localserver-0.6.0/runtests.py 2022-05-05 21:38:00.000000000 +0200 +++ new/pytest-localserver-0.7.0/runtests.py 2022-08-30 09:11:43.000000000 +0200 @@ -2658,61 +2658,59 @@ p2dPWv10xmXLnHQLlQrVD1yYQwb9/yTK0Oq4oxv6j0jKNxLPbTMi6d3/e5X+FyKT7kc= """ -import sys -import base64 -import zlib -import imp +import sys # noqa: E402 +import base64 # noqa: E402 +import zlib # noqa: E402 -class DictImporter(object): + +class DictImporter: def __init__(self, sources): self.sources = sources def find_module(self, fullname, path=None): if fullname in self.sources: return self - if fullname + '.__init__' in self.sources: + if fullname + ".__init__" in self.sources: return self return None def load_module(self, fullname): # print "load_module:", fullname from types import ModuleType + try: s = self.sources[fullname] is_pkg = False except KeyError: - s = self.sources[fullname + '.__init__'] + s = self.sources[fullname + ".__init__"] is_pkg = True - co = compile(s, fullname, 'exec') + co = compile(s, fullname, "exec") module = sys.modules.setdefault(fullname, ModuleType(fullname)) - module.__file__ = "%s/%s" % (__file__, fullname) + module.__file__ = "{}/{}".format(__file__, fullname) module.__loader__ = self if is_pkg: module.__path__ = [fullname] - do_exec(co, module.__dict__) + do_exec(co, module.__dict__) # noqa: F821 return sys.modules[fullname] def get_source(self, name): res = self.sources.get(name) if res is None: - res = self.sources.get(name + '.__init__') + res = self.sources.get(name + ".__init__") return res + if __name__ == "__main__": - if sys.version_info >= (3, 0): - exec("def do_exec(co, loc): exec(co, loc)\n") - import pickle - sources = sources.encode("ascii") # ensure bytes - sources = pickle.loads(zlib.decompress(base64.decodebytes(sources))) - else: - import cPickle as pickle - exec("def do_exec(co, loc): exec co in loc\n") - sources = pickle.loads(zlib.decompress(base64.decodestring(sources))) + exec("def do_exec(co, loc): exec(co, loc)\n") + import pickle + + sources = sources.encode("ascii") # ensure bytes + sources = pickle.loads(zlib.decompress(base64.decodebytes(sources))) importer = DictImporter(sources) sys.meta_path.insert(0, importer) entry = "import py; raise SystemExit(py.test.cmdline.main())" - do_exec(entry, locals()) + do_exec(entry, locals()) # noqa: F821 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-localserver-0.6.0/setup.cfg new/pytest-localserver-0.7.0/setup.cfg --- old/pytest-localserver-0.6.0/setup.cfg 2022-05-05 21:38:21.508000100 +0200 +++ new/pytest-localserver-0.7.0/setup.cfg 2022-08-30 09:12:14.724795300 +0200 @@ -1,5 +1,5 @@ [metadata] -description-file = README.rst +description_file = README.rst [egg_info] tag_build = diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-localserver-0.6.0/setup.py new/pytest-localserver-0.7.0/setup.py --- old/pytest-localserver-0.6.0/setup.py 2022-05-05 21:38:00.000000000 +0200 +++ new/pytest-localserver-0.7.0/setup.py 2022-08-30 09:11:43.000000000 +0200 @@ -1,69 +1,70 @@ -from setuptools import setup, Command -import sys +from setuptools import Command +from setuptools import setup def read(fname): # makes sure that setup can be executed from a different location import os.path + _here = os.path.abspath(os.path.dirname(__file__)) return open(os.path.join(_here, fname)).read() class PyTest(Command): user_options = [] + def initialize_options(self): pass + def finalize_options(self): pass + def run(self): - import sys, subprocess - errno = subprocess.call([sys.executable, 'runtests.py']) + import subprocess + import sys + + errno = subprocess.call([sys.executable, "runtests.py"]) raise SystemExit(errno) + setup( - name='pytest-localserver', - author='Sebastian Rahlf', - author_email='ba...@redtoad.de', - maintainer='David Zaslavsky', - maintainer_email='diaz...@ellipsix.net', - license='MIT License', - description='py.test plugin to test server connections locally.', - long_description=read('README.rst'), - url='https://github.com/pytest-dev/pytest-localserver', - - packages=['pytest_localserver'], - python_requires='>=3.5', - install_requires=[ - 'werkzeug>=0.10', - 'aiosmtpd' - ], - cmdclass={'test': PyTest}, - tests_require=[ - 'pytest>=2.0.0', - 'requests' - ], - entry_points={ - 'pytest11': ['localserver = pytest_localserver.plugin'] + name="pytest-localserver", + author="Sebastian Rahlf", + author_email="ba...@redtoad.de", + maintainer="David Zaslavsky", + maintainer_email="diaz...@ellipsix.net", + license="MIT License", + description="pytest plugin to test server connections locally.", + long_description=read("README.rst"), + url="https://github.com/pytest-dev/pytest-localserver", + packages=["pytest_localserver"], + python_requires=">=3.5", + install_requires=["werkzeug>=0.10"], + extras_require={ + "smtp": [ + "aiosmtpd", + ], }, - + cmdclass={"test": PyTest}, + tests_require=["pytest>=2.0.0", "requests"], + entry_points={"pytest11": ["localserver = pytest_localserver.plugin"]}, zip_safe=False, include_package_data=True, - - keywords='py.test pytest server localhost http smtp', + keywords="pytest server localhost http smtp", classifiers=[ - 'Framework :: Pytest', - 'Operating System :: OS Independent', - 'Development Status :: 4 - Beta', - 'Intended Audience :: Developers', - 'License :: OSI Approved :: MIT License', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3 :: Only', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'Programming Language :: Python :: 3.10', - 'Topic :: Software Development :: Testing' - ] + "Framework :: Pytest", + "Operating System :: OS Independent", + "Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Topic :: Software Development :: Testing", + ], ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-localserver-0.6.0/tests/test_http.py new/pytest-localserver-0.7.0/tests/test_http.py --- old/pytest-localserver-0.6.0/tests/test_http.py 2022-05-05 21:38:00.000000000 +0200 +++ new/pytest-localserver-0.7.0/tests/test_http.py 2022-08-30 09:11:43.000000000 +0200 @@ -1,8 +1,10 @@ import itertools + import pytest import requests -from pytest_localserver import http, plugin +from pytest_localserver import http +from pytest_localserver import plugin # define test fixture here again in order to run tests without having to @@ -10,7 +12,9 @@ httpserver = plugin.httpserver -transfer_encoded = pytest.mark.parametrize('transfer_encoding_header', ['Transfer-encoding', 'Transfer-Encoding', 'transfer-encoding', 'TRANSFER-ENCODING']) +transfer_encoded = pytest.mark.parametrize( + "transfer_encoding_header", ["Transfer-encoding", "Transfer-Encoding", "transfer-encoding", "TRANSFER-ENCODING"] +) def test_httpserver_funcarg(httpserver): @@ -21,29 +25,29 @@ def test_server_does_not_serve_file_at_startup(httpserver): assert httpserver.code == 204 - assert httpserver.content == '' + assert httpserver.content == "" def test_some_content_retrieval(httpserver): - httpserver.serve_content('TEST!') + httpserver.serve_content("TEST!") resp = requests.get(httpserver.url) - assert resp.text == 'TEST!' + assert resp.text == "TEST!" assert resp.status_code == 200 def test_request_is_stored(httpserver): - httpserver.serve_content('TEST!') + httpserver.serve_content("TEST!") assert len(httpserver.requests) == 0 - resp = requests.get(httpserver.url) + requests.get(httpserver.url) assert len(httpserver.requests) == 1 def test_GET_request(httpserver): - httpserver.serve_content('TEST!', headers={'Content-type': 'text/plain'}) - resp = requests.get(httpserver.url, headers={'User-Agent': 'Test method'}) - assert resp.text == 'TEST!' + httpserver.serve_content("TEST!", headers={"Content-type": "text/plain"}) + resp = requests.get(httpserver.url, headers={"User-Agent": "Test method"}) + assert resp.text == "TEST!" assert resp.status_code == 200 - assert 'text/plain' in resp.headers['Content-type'] + assert "text/plain" in resp.headers["Content-type"] # FIXME get compression working! @@ -62,10 +66,10 @@ def test_HEAD_request(httpserver): - httpserver.serve_content('TEST!', headers={'Content-type': 'text/plain'}) + httpserver.serve_content("TEST!", headers={"Content-type": "text/plain"}) resp = requests.head(httpserver.url) assert resp.status_code == 200 - assert resp.headers['Content-type'] == 'text/plain' + assert resp.headers["Content-type"] == "text/plain" # def test_POST_request(httpserver): @@ -83,21 +87,17 @@ # assert resp.status_code == 200 -@pytest.mark.parametrize('chunked_flag', [http.Chunked.YES, http.Chunked.AUTO, http.Chunked.NO]) +@pytest.mark.parametrize("chunked_flag", [http.Chunked.YES, http.Chunked.AUTO, http.Chunked.NO]) def test_chunked_attribute_without_header(httpserver, chunked_flag): """ Test that passing the chunked attribute to serve_content() properly sets the chunked property of the server. """ - httpserver.serve_content( - ('TEST!', 'test'), - headers={'Content-type': 'text/plain'}, - chunked=chunked_flag - ) + httpserver.serve_content(("TEST!", "test"), headers={"Content-type": "text/plain"}, chunked=chunked_flag) assert httpserver.chunked == chunked_flag -@pytest.mark.parametrize('chunked_flag', [http.Chunked.YES, http.Chunked.AUTO, http.Chunked.NO]) +@pytest.mark.parametrize("chunked_flag", [http.Chunked.YES, http.Chunked.AUTO, http.Chunked.NO]) def test_chunked_attribute_with_header(httpserver, chunked_flag): """ Test that passing the chunked attribute to serve_content() properly sets @@ -105,15 +105,13 @@ also set. """ httpserver.serve_content( - ('TEST!', 'test'), - headers={'Content-type': 'text/plain', 'Transfer-encoding': 'chunked'}, - chunked=chunked_flag + ("TEST!", "test"), headers={"Content-type": "text/plain", "Transfer-encoding": "chunked"}, chunked=chunked_flag ) assert httpserver.chunked == chunked_flag @transfer_encoded -@pytest.mark.parametrize('chunked_flag', [http.Chunked.YES, http.Chunked.AUTO]) +@pytest.mark.parametrize("chunked_flag", [http.Chunked.YES, http.Chunked.AUTO]) def test_GET_request_chunked_parameter(httpserver, transfer_encoding_header, chunked_flag): """ Test that passing YES or AUTO as the chunked parameter to serve_content() @@ -121,19 +119,19 @@ header is also set. """ httpserver.serve_content( - ('TEST!', 'test'), - headers={'Content-type': 'text/plain', transfer_encoding_header: 'chunked'}, - chunked=chunked_flag + ("TEST!", "test"), + headers={"Content-type": "text/plain", transfer_encoding_header: "chunked"}, + chunked=chunked_flag, ) - resp = requests.get(httpserver.url, headers={'User-Agent': 'Test method'}) - assert resp.text == 'TEST!test' + resp = requests.get(httpserver.url, headers={"User-Agent": "Test method"}) + assert resp.text == "TEST!test" assert resp.status_code == 200 - assert 'text/plain' in resp.headers['Content-type'] - assert 'chunked' in resp.headers['Transfer-encoding'] + assert "text/plain" in resp.headers["Content-type"] + assert "chunked" in resp.headers["Transfer-encoding"] @transfer_encoded -@pytest.mark.parametrize('chunked_flag', [http.Chunked.YES, http.Chunked.AUTO]) +@pytest.mark.parametrize("chunked_flag", [http.Chunked.YES, http.Chunked.AUTO]) def test_GET_request_chunked_attribute(httpserver, transfer_encoding_header, chunked_flag): """ Test that setting the chunked attribute of httpserver to YES or AUTO @@ -141,15 +139,14 @@ header is also set. """ httpserver.serve_content( - ('TEST!', 'test'), - headers={'Content-type': 'text/plain', transfer_encoding_header: 'chunked'} + ("TEST!", "test"), headers={"Content-type": "text/plain", transfer_encoding_header: "chunked"} ) httpserver.chunked = chunked_flag - resp = requests.get(httpserver.url, headers={'User-Agent': 'Test method'}) - assert resp.text == 'TEST!test' + resp = requests.get(httpserver.url, headers={"User-Agent": "Test method"}) + assert resp.text == "TEST!test" assert resp.status_code == 200 - assert 'text/plain' in resp.headers['Content-type'] - assert 'chunked' in resp.headers['Transfer-encoding'] + assert "text/plain" in resp.headers["Content-type"] + assert "chunked" in resp.headers["Transfer-encoding"] @transfer_encoded @@ -160,50 +157,43 @@ header is set. """ httpserver.serve_content( - ('TEST!', 'test'), - headers={'Content-type': 'text/plain', transfer_encoding_header: 'chunked'}, - chunked=http.Chunked.NO + ("TEST!", "test"), + headers={"Content-type": "text/plain", transfer_encoding_header: "chunked"}, + chunked=http.Chunked.NO, ) with pytest.raises(requests.exceptions.ChunkedEncodingError): - resp = requests.get(httpserver.url, headers={'User-Agent': 'Test method'}) + requests.get(httpserver.url, headers={"User-Agent": "Test method"}) -@pytest.mark.parametrize('chunked_flag', [http.Chunked.NO, http.Chunked.AUTO]) +@pytest.mark.parametrize("chunked_flag", [http.Chunked.NO, http.Chunked.AUTO]) def test_GET_request_chunked_parameter_no_header(httpserver, chunked_flag): """ Test that passing NO or AUTO as the chunked parameter to serve_content() causes the response not to be sent using chunking when the Transfer-encoding header is not set. """ - httpserver.serve_content( - ('TEST!', 'test'), - headers={'Content-type': 'text/plain'}, - chunked=chunked_flag - ) - resp = requests.get(httpserver.url, headers={'User-Agent': 'Test method'}) - assert resp.text == 'TEST!test' + httpserver.serve_content(("TEST!", "test"), headers={"Content-type": "text/plain"}, chunked=chunked_flag) + resp = requests.get(httpserver.url, headers={"User-Agent": "Test method"}) + assert resp.text == "TEST!test" assert resp.status_code == 200 - assert 'text/plain' in resp.headers['Content-type'] - assert 'Transfer-encoding' not in resp.headers + assert "text/plain" in resp.headers["Content-type"] + assert "Transfer-encoding" not in resp.headers -@pytest.mark.parametrize('chunked_flag', [http.Chunked.NO, http.Chunked.AUTO]) +@pytest.mark.parametrize("chunked_flag", [http.Chunked.NO, http.Chunked.AUTO]) def test_GET_request_chunked_attribute_no_header(httpserver, chunked_flag): """ Test that setting the chunked attribute of httpserver to NO or AUTO causes the response not to be sent using chunking when the Transfer-encoding header is not set. """ - httpserver.serve_content( - ('TEST!', 'test'), - headers={'Content-type': 'text/plain'} - ) + httpserver.serve_content(("TEST!", "test"), headers={"Content-type": "text/plain"}) httpserver.chunked = chunked_flag - resp = requests.get(httpserver.url, headers={'User-Agent': 'Test method'}) - assert resp.text == 'TEST!test' + resp = requests.get(httpserver.url, headers={"User-Agent": "Test method"}) + assert resp.text == "TEST!test" assert resp.status_code == 200 - assert 'text/plain' in resp.headers['Content-type'] - assert 'Transfer-encoding' not in resp.headers + assert "text/plain" in resp.headers["Content-type"] + assert "Transfer-encoding" not in resp.headers def test_GET_request_chunked_no_header(httpserver): @@ -212,15 +202,11 @@ the response to be sent using chunking even if the Transfer-encoding header is not set. """ - httpserver.serve_content( - ('TEST!', 'test'), - headers={'Content-type': 'text/plain'}, - chunked=http.Chunked.YES - ) - resp = requests.get(httpserver.url, headers={'User-Agent': 'Test method'}) + httpserver.serve_content(("TEST!", "test"), headers={"Content-type": "text/plain"}, chunked=http.Chunked.YES) + resp = requests.get(httpserver.url, headers={"User-Agent": "Test method"}) # Without the Transfer-encoding header set, requests does not undo the chunk # encoding so it comes through as "raw" chunks - assert resp.text == '5\r\nTEST!\r\n4\r\ntest\r\n0\r\n\r\n' + assert resp.text == "5\r\nTEST!\r\n4\r\ntest\r\n0\r\n\r\n" def _format_chunk(chunk): @@ -228,59 +214,55 @@ if len(r) <= 40: return r else: - return r[:13] + '...' + r[-14:] + ' (length {0})'.format(len(chunk)) + return r[:13] + "..." + r[-14:] + " (length {})".format(len(chunk)) def _compare_chunks(expected, actual): __tracebackhide__ = True if expected != actual: - message = [_format_chunk(expected) + ' != ' + _format_chunk(actual)] + message = [_format_chunk(expected) + " != " + _format_chunk(actual)] if type(expected) == type(actual): - for i, (e, a) in enumerate(itertools.zip_longest(expected, actual, fillvalue='<end>')): + for i, (e, a) in enumerate(itertools.zip_longest(expected, actual, fillvalue="<end>")): if e != a: message += [ - ' Chunks differ at index {}:'.format(i), - ' Expected: ' + (repr(expected[i:i+5]) + '...' if e != '<end>' else '<end>'), - ' Found: ' + (repr(actual[i:i+5]) + '...' if a != '<end>' else '<end>') + " Chunks differ at index {}:".format(i), + " Expected: " + (repr(expected[i : i + 5]) + "..." if e != "<end>" else "<end>"), + " Found: " + (repr(actual[i : i + 5]) + "..." if a != "<end>" else "<end>"), ] break - pytest.fail('\n'.join(message)) + pytest.fail("\n".join(message)) -@pytest.mark.parametrize('chunk_size', [400, 499, 500, 512, 750, 1024, 4096, 8192]) +@pytest.mark.parametrize("chunk_size", [400, 499, 500, 512, 750, 1024, 4096, 8192]) def test_GET_request_large_chunks(httpserver, chunk_size): """ Test that a response with large chunks comes through correctly """ - body = b'0123456789abcdef' * 1024 # 16 kb total + body = b"0123456789abcdef" * 1024 # 16 kb total # Split body into fixed-size chunks, from https://stackoverflow.com/a/18854817/56541 - chunks = [body[0 + i:chunk_size + i] for i in range(0, len(body), chunk_size)] + chunks = [body[0 + i : chunk_size + i] for i in range(0, len(body), chunk_size)] httpserver.serve_content( - chunks, - headers={'Content-type': 'text/plain', 'Transfer-encoding': 'chunked'}, - chunked=http.Chunked.YES + chunks, headers={"Content-type": "text/plain", "Transfer-encoding": "chunked"}, chunked=http.Chunked.YES ) - resp = requests.get(httpserver.url, headers={'User-Agent': 'Test method'}, stream=True) + resp = requests.get(httpserver.url, headers={"User-Agent": "Test method"}, stream=True) assert resp.status_code == 200 - text = b'' + text = b"" for original_chunk, received_chunk in itertools.zip_longest(chunks, resp.iter_content(chunk_size=None)): _compare_chunks(original_chunk, received_chunk) text += received_chunk assert text == body - assert 'chunked' in resp.headers['Transfer-encoding'] + assert "chunked" in resp.headers["Transfer-encoding"] -@pytest.mark.parametrize('chunked_flag', [http.Chunked.YES, http.Chunked.AUTO]) +@pytest.mark.parametrize("chunked_flag", [http.Chunked.YES, http.Chunked.AUTO]) def test_GET_request_chunked_no_content_length(httpserver, chunked_flag): """ Test that a chunked response does not include a Content-length header """ httpserver.serve_content( - ('TEST!', 'test'), - headers={'Content-type': 'text/plain', 'Transfer-encoding': 'chunked'}, - chunked=chunked_flag + ("TEST!", "test"), headers={"Content-type": "text/plain", "Transfer-encoding": "chunked"}, chunked=chunked_flag ) - resp = requests.get(httpserver.url, headers={'User-Agent': 'Test method'}) + resp = requests.get(httpserver.url, headers={"User-Agent": "Test method"}) assert resp.status_code == 200 - assert 'Transfer-encoding' in resp.headers - assert 'Content-length' not in resp.headers + assert "Transfer-encoding" in resp.headers + assert "Content-length" not in resp.headers diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-localserver-0.6.0/tests/test_https.py new/pytest-localserver-0.7.0/tests/test_https.py --- old/pytest-localserver-0.6.0/tests/test_https.py 2022-05-05 21:38:00.000000000 +0200 +++ new/pytest-localserver-0.7.0/tests/test_https.py 2022-08-30 09:11:43.000000000 +0200 @@ -1,9 +1,7 @@ -import sys - -import pytest import requests -from pytest_localserver import https, plugin +from pytest_localserver import https +from pytest_localserver import plugin # define test fixture here again in order to run tests without having to @@ -19,27 +17,27 @@ def test_server_does_not_serve_file_at_startup(httpsserver): assert httpsserver.code == 204 - assert httpsserver.content == '' + assert httpsserver.content == "" def test_some_content_retrieval(httpsserver): - httpsserver.serve_content('TEST!') + httpsserver.serve_content("TEST!") resp = requests.get(httpsserver.url, verify=False) - assert resp.text == 'TEST!' + assert resp.text == "TEST!" assert resp.status_code == 200 def test_GET_request(httpsserver): - httpsserver.serve_content('TEST!', headers={'Content-type': 'text/plain'}) - resp = requests.get(httpsserver.url, headers={'User-Agent': 'Test method'}, verify=False) - assert resp.text == 'TEST!' + httpsserver.serve_content("TEST!", headers={"Content-type": "text/plain"}) + resp = requests.get(httpsserver.url, headers={"User-Agent": "Test method"}, verify=False) + assert resp.text == "TEST!" assert resp.status_code == 200 - assert 'text/plain' in resp.headers['Content-type'] + assert "text/plain" in resp.headers["Content-type"] def test_HEAD_request(httpsserver): - httpsserver.serve_content('TEST!', headers={'Content-type': 'text/plain'}) + httpsserver.serve_content("TEST!", headers={"Content-type": "text/plain"}) print(httpsserver.url) resp = requests.head(httpsserver.url, verify=False) assert resp.status_code == 200 - assert resp.headers['Content-type'] == 'text/plain' + assert resp.headers["Content-type"] == "text/plain" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-localserver-0.6.0/tests/test_smtp.py new/pytest-localserver-0.7.0/tests/test_smtp.py --- old/pytest-localserver-0.6.0/tests/test_smtp.py 2022-05-05 21:38:00.000000000 +0200 +++ new/pytest-localserver-0.7.0/tests/test_smtp.py 2022-08-30 09:11:43.000000000 +0200 @@ -1,25 +1,30 @@ import smtplib +import pytest + try: # python 3 from email.mime.text import MIMEText except ImportError: # python 2? from email.MIMEText import MIMEText -from pytest_localserver import plugin, smtp +from pytest_localserver import plugin + + +smtp = pytest.importorskip("pytest_localserver.smtp") -def send_plain_email(to, from_, subject, txt, server=('localhost', 25)): +def send_plain_email(to, from_, subject, txt, server=("localhost", 25)): """ Sends a simple plain text message via SMTP. """ if type(to) in (tuple, list): - to = ', '.join(to) + to = ", ".join(to) # Create a text/plain message msg = MIMEText(txt) - msg['Subject'] = subject - msg['From'] = from_ - msg['To'] = to + msg["Subject"] = subject + msg["From"] = from_ + msg["To"] = to host, port = server[:2] server = smtplib.SMTP(host, port) @@ -65,27 +70,33 @@ def test_send_email(smtpserver): # send one e-mail send_plain_email( - 'al...@example.com', 'webmas...@example.com', - 'Your e-mail is getting there', 'Seems like this test actually works!', - smtpserver.addr) + "al...@example.com", + "webmas...@example.com", + "Your e-mail is getting there", + "Seems like this test actually works!", + smtpserver.addr, + ) msg = smtpserver.outbox[-1] - assert msg['To'] == 'al...@example.com' - assert msg['From'] == 'webmas...@example.com' - assert msg['Subject'] == 'Your e-mail is getting there' - assert msg.details.rcpttos == ['al...@example.com'] + assert msg["To"] == "al...@example.com" + assert msg["From"] == "webmas...@example.com" + assert msg["Subject"] == "Your e-mail is getting there" + assert msg.details.rcpttos == ["al...@example.com"] assert msg.details.peer assert msg.details.mailfrom # send another e-mail send_plain_email( - 'b...@example.com', 'webmas...@example.com', - 'His e-mail too', 'Seems like this test actually works!', - smtpserver.addr) + "b...@example.com", + "webmas...@example.com", + "His e-mail too", + "Seems like this test actually works!", + smtpserver.addr, + ) msg = smtpserver.outbox[-1] - assert msg['To'] == 'b...@example.com' - assert msg['From'] == 'webmas...@example.com' - assert msg['Subject'] == 'His e-mail too' + assert msg["To"] == "b...@example.com" + assert msg["From"] == "webmas...@example.com" + assert msg["Subject"] == "His e-mail too" # two mails are now in outbox assert len(smtpserver.outbox) == 2 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-localserver-0.6.0/tox.ini new/pytest-localserver-0.7.0/tox.ini --- old/pytest-localserver-0.6.0/tox.ini 2022-05-05 21:38:00.000000000 +0200 +++ new/pytest-localserver-0.7.0/tox.ini 2022-08-30 09:11:43.000000000 +0200 @@ -1,30 +1,47 @@ [tox] -envlist = py35,py36,py37,py38,py39,py310 +envlist = py{35,36,37,38,39,310,311,py3}{,-smtp},lint recreate = True isolated_build = True [tox:hudson] downloadcache = {toxworkdir}/_download -[gh-actions] -python = - 3.5: py35 - 3.6: py36 - 3.7: py37 - 3.8: py38 - 3.9: py39 - 3.10: py310 - [testenv] description = run test suite under {basepython} deps = - pytest >=4, <7; python_version<'3.10' - pytest >=6.2.5, <7; python_version>='3.10' -# pytest-cov >=2, <3 + # Future major versions of pytest may break backwards compatibility in a way + # that prevents them from working with this package, so we prevent testing + # with major versions that haven't been released yet. Each time a new major + # version of pytest is released, once it's confirmed to work with this + # package, we should bump this limit to the next major version. + # + # The lower bounds come from testing with different pytest versions using + # tox's --force-dep option to find the earliest versions of pytest that are + # known to work. If you add code that breaks with an old version of pytest, + # feel free to raise these bounds to represent the earliest version that + # works with your code. Don't forget to modify the corresponding entries in + # the Github workflows configuration file if you do change these lower + # bounds. + pytest >=4, <8; python_version<'3.10' + pytest >=6.2.4, <8; python_version>='3.10' pytest-cov six requests +extras = + smtp: smtp commands = - py.test -v \ + pytest -v \ --junitxml=junit-{envname}.xml \ {posargs} + +[testenv:lint] +skip_install = True +basepython = python3 +deps = pre-commit>=2.9.3 +commands = pre-commit run --all-files --show-diff-on-failure {posargs:} + +[flake8] +max-line-length = 120 +extend-ignore = + ; whitespace before ':' + E203