pytest_httpserver 1.0.9__tar.gz → 1.0.10__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/CHANGES.rst +23 -0
  2. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/PKG-INFO +15 -9
  3. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/README.md +14 -8
  4. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/doc/conf.py +1 -1
  5. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/pyproject.toml +54 -1
  6. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/pytest_httpserver/blocking_httpserver.py +18 -16
  7. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/pytest_httpserver/httpserver.py +76 -78
  8. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/pytest_httpserver/pytest_plugin.py +4 -4
  9. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/test_blocking_httpserver.py +5 -2
  10. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/test_handler_errors.py +6 -6
  11. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/test_json_matcher.py +1 -1
  12. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/test_parse_qs.py +4 -4
  13. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/test_port_changing.py +2 -2
  14. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/test_querymatcher.py +1 -1
  15. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/test_release.py +7 -6
  16. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/CONTRIBUTION.md +0 -0
  17. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/LICENSE +0 -0
  18. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/doc/Makefile +0 -0
  19. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/doc/_static/.placeholder +0 -0
  20. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/doc/api.rst +0 -0
  21. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/doc/background.rst +0 -0
  22. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/doc/changes.rst +0 -0
  23. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/doc/fixtures.rst +0 -0
  24. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/doc/guide.rst +0 -0
  25. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/doc/howto.rst +0 -0
  26. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/doc/index.rst +0 -0
  27. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/doc/tutorial.rst +0 -0
  28. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/doc/upgrade.rst +0 -0
  29. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/example.py +0 -0
  30. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/example_pytest.py +0 -0
  31. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/pytest_httpserver/__init__.py +0 -0
  32. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/pytest_httpserver/py.typed +0 -0
  33. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/assets/Makefile +0 -0
  34. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/assets/README +0 -0
  35. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/assets/rootCA.cnf +0 -0
  36. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/assets/rootCA.crt +0 -0
  37. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/assets/rootCA.key +0 -0
  38. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/assets/rootCA.srl +0 -0
  39. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/assets/server.cnf +0 -0
  40. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/assets/server.crt +0 -0
  41. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/assets/server.csr +0 -0
  42. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/assets/server.key +0 -0
  43. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/assets/v3.ext +0 -0
  44. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/conftest.py +0 -0
  45. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/examples/test_example_blocking_httpserver.py +0 -0
  46. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/examples/test_example_query_params1.py +0 -0
  47. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/examples/test_example_query_params2.py +0 -0
  48. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/examples/test_howto_authorization_headers.py +0 -0
  49. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/examples/test_howto_case_insensitive_matcher.py +0 -0
  50. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/examples/test_howto_check.py +0 -0
  51. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/examples/test_howto_check_handler_errors.py +0 -0
  52. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/examples/test_howto_custom_handler.py +0 -0
  53. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/examples/test_howto_header_value_matcher.py +0 -0
  54. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/examples/test_howto_json_matcher.py +0 -0
  55. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/examples/test_howto_query_params_dict.py +0 -0
  56. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/examples/test_howto_query_params_never_do_this.py +0 -0
  57. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/examples/test_howto_query_params_proper_use.py +0 -0
  58. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/examples/test_howto_regexp.py +0 -0
  59. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/examples/test_howto_timeout_requests.py +0 -0
  60. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/examples/test_howto_url_matcher.py +0 -0
  61. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/examples/test_howto_wait_success.py +0 -0
  62. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/test_headers.py +0 -0
  63. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/test_ip_protocols.py +0 -0
  64. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/test_mixed.py +0 -0
  65. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/test_oneshot.py +0 -0
  66. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/test_ordered.py +0 -0
  67. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/test_permanent.py +0 -0
  68. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/test_querystring.py +0 -0
  69. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/test_ssl.py +0 -0
  70. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/test_urimatch.py +0 -0
  71. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/test_wait.py +0 -0
  72. {pytest_httpserver-1.0.9 → pytest_httpserver-1.0.10}/tests/test_with_statement.py +0 -0
@@ -2,6 +2,29 @@
2
2
  Release Notes
3
3
  =============
4
4
 
5
+ .. _Release Notes_1.0.10:
6
+
7
+ 1.0.10
8
+ ======
9
+
10
+ .. _Release Notes_1.0.10_New Features:
11
+
12
+ New Features
13
+ ------------
14
+
15
+ - When there's no handler for the request, add more details to the response
16
+ sent by the server about the request to help debugging.
17
+
18
+
19
+ .. _Release Notes_1.0.10_Other Notes:
20
+
21
+ Other Notes
22
+ -----------
23
+
24
+ - Use ruff for linting. It includes some source code changes which should not
25
+ introduce functional changes, or API changes.
26
+
27
+
5
28
  .. _Release Notes_1.0.9:
6
29
 
7
30
  1.0.9
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pytest_httpserver
3
- Version: 1.0.9
3
+ Version: 1.0.10
4
4
  Summary: pytest-httpserver is a httpserver for pytest
5
5
  Home-page: https://github.com/csernazs/pytest-httpserver
6
6
  License: MIT
@@ -27,10 +27,12 @@ Description-Content-Type: text/markdown
27
27
 
28
28
  [![Build Status](https://github.com/csernazs/pytest-httpserver/workflows/build/badge.svg?branch=master)](https://github.com/csernazs/pytest-httpserver/actions?query=workflow%3Abuild+branch%3Amaster)
29
29
  [![Documentation Status](https://readthedocs.org/projects/pytest-httpserver/badge/?version=latest)](https://pytest-httpserver.readthedocs.io/en/latest/?badge=latest)
30
- [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
31
- [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=K6PU3AGBZW4QC&item_name=pytest-httpserver&currency_code=EUR&source=url)
30
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
32
31
  [![codecov](https://codecov.io/gh/csernazs/pytest-httpserver/branch/master/graph/badge.svg?token=MX2JXbHqRH)](https://codecov.io/gh/csernazs/pytest-httpserver)
33
32
  [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
33
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
34
+ [![Downloads](https://static.pepy.tech/badge/pytest-httpserver/month)](https://pepy.tech/project/pytest-httpserver)
35
+ [![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit)](https://github.com/pre-commit/pre-commit)
34
36
 
35
37
  ## pytest_httpserver
36
38
 
@@ -144,12 +146,16 @@ documentation](https://pytest-httpserver.readthedocs.io/en/latest/api.html#block
144
146
 
145
147
  ### Donation
146
148
 
147
- If you want to donate to this project, you can find the donate button at the top
148
- of the README.
149
+ Currently, this project is based heavily on werkzeug and pytest.
149
150
 
150
- Currently, this project is based heavily on werkzeug. Werkzeug does all the heavy lifting
151
- behind the scenes, parsing HTTP request and defining Request and Response objects, which
152
- are currently transparent in the API.
151
+ Werkzeug does all the heavy lifting behind the scenes, parsing HTTP request and
152
+ defining Request and Response objects, which are currently transparent in the
153
+ API.
153
154
 
154
- If you wish to donate, please consider donating to them: https://palletsprojects.com/donate
155
+ If you wish to donate to werkzeug: https://palletsprojects.com/donate
156
+
157
+
158
+ Pytest is the de-facto test library for python.
159
+
160
+ If you wish to donate to pytest: https://opencollective.com/pytest
155
161
 
@@ -1,9 +1,11 @@
1
1
  [![Build Status](https://github.com/csernazs/pytest-httpserver/workflows/build/badge.svg?branch=master)](https://github.com/csernazs/pytest-httpserver/actions?query=workflow%3Abuild+branch%3Amaster)
2
2
  [![Documentation Status](https://readthedocs.org/projects/pytest-httpserver/badge/?version=latest)](https://pytest-httpserver.readthedocs.io/en/latest/?badge=latest)
3
- [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
4
- [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=K6PU3AGBZW4QC&item_name=pytest-httpserver&currency_code=EUR&source=url)
3
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
5
4
  [![codecov](https://codecov.io/gh/csernazs/pytest-httpserver/branch/master/graph/badge.svg?token=MX2JXbHqRH)](https://codecov.io/gh/csernazs/pytest-httpserver)
6
5
  [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
6
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
7
+ [![Downloads](https://static.pepy.tech/badge/pytest-httpserver/month)](https://pepy.tech/project/pytest-httpserver)
8
+ [![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit)](https://github.com/pre-commit/pre-commit)
7
9
 
8
10
  ## pytest_httpserver
9
11
 
@@ -117,11 +119,15 @@ documentation](https://pytest-httpserver.readthedocs.io/en/latest/api.html#block
117
119
 
118
120
  ### Donation
119
121
 
120
- If you want to donate to this project, you can find the donate button at the top
121
- of the README.
122
+ Currently, this project is based heavily on werkzeug and pytest.
122
123
 
123
- Currently, this project is based heavily on werkzeug. Werkzeug does all the heavy lifting
124
- behind the scenes, parsing HTTP request and defining Request and Response objects, which
125
- are currently transparent in the API.
124
+ Werkzeug does all the heavy lifting behind the scenes, parsing HTTP request and
125
+ defining Request and Response objects, which are currently transparent in the
126
+ API.
126
127
 
127
- If you wish to donate, please consider donating to them: https://palletsprojects.com/donate
128
+ If you wish to donate to werkzeug: https://palletsprojects.com/donate
129
+
130
+
131
+ Pytest is the de-facto test library for python.
132
+
133
+ If you wish to donate to pytest: https://opencollective.com/pytest
@@ -66,7 +66,7 @@ author = "Zsolt Cserna"
66
66
  # built documents.
67
67
  #
68
68
  # The short X.Y version.
69
- version = "1.0.9"
69
+ version = "1.0.10"
70
70
  # The full version, including alpha/beta/rc tags.
71
71
  release = version
72
72
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "pytest_httpserver"
3
- version = "1.0.9"
3
+ version = "1.0.10"
4
4
  description = "pytest-httpserver is a httpserver for pytest"
5
5
  authors = ["Zsolt Cserna <cserna.zsolt@gmail.com>"]
6
6
  license = "MIT"
@@ -51,6 +51,7 @@ coverage = ">=6.4.4,<8.0.0"
51
51
  types-toml = "^0.10.8"
52
52
  toml = "^0.10.2"
53
53
  black = "^23.1.0"
54
+ ruff = "^0.2.1"
54
55
 
55
56
 
56
57
  [tool.poetry.group.doc]
@@ -88,3 +89,55 @@ markers = [
88
89
  [tool.mypy]
89
90
  files = ["pytest_httpserver", "scripts", "tests", "doc"]
90
91
  implicit_reexport = false
92
+
93
+
94
+ [tool.black]
95
+ line-length = 120
96
+ safe = true
97
+
98
+ [tool.ruff]
99
+ lint.select = ["ALL"]
100
+ lint.ignore = [
101
+ "I",
102
+ "D",
103
+
104
+ "ANN",
105
+ "ARG005",
106
+ "B011",
107
+ "B904",
108
+ "C408",
109
+ "C901",
110
+ "COM812",
111
+ "EM101",
112
+ "EM103",
113
+ "FBT002",
114
+ "FIX002",
115
+ "INP001",
116
+ "PGH003",
117
+ "PLR0912",
118
+ "PLR0913",
119
+ "PLR2004",
120
+ "PLW2901",
121
+ "PT004",
122
+ "PT012",
123
+ "PT013",
124
+ "PTH118",
125
+ "PTH120",
126
+ "RET504",
127
+ "RET505",
128
+ "RET506",
129
+ "RUF005",
130
+ "S101",
131
+ "S113",
132
+ "S603",
133
+ "S607",
134
+ "SIM108",
135
+ "T201",
136
+ "TD002",
137
+ "TD003",
138
+ "TRY003",
139
+ "UP032",
140
+ ]
141
+ line-length = 120
142
+ target-version = "py38"
143
+ exclude = ["doc", "example*.py", "tests/examples/*.py"]
@@ -1,15 +1,11 @@
1
+ from __future__ import annotations
2
+
1
3
  from queue import Empty
2
4
  from queue import Queue
3
- from ssl import SSLContext
5
+ from typing import TYPE_CHECKING
4
6
  from typing import Any
5
- from typing import Dict
6
7
  from typing import Mapping
7
- from typing import Optional
8
8
  from typing import Pattern
9
- from typing import Union
10
-
11
- from werkzeug.wrappers import Request
12
- from werkzeug.wrappers import Response
13
9
 
14
10
  from pytest_httpserver.httpserver import METHOD_ALL
15
11
  from pytest_httpserver.httpserver import UNDEFINED
@@ -19,6 +15,12 @@ from pytest_httpserver.httpserver import QueryMatcher
19
15
  from pytest_httpserver.httpserver import RequestHandlerBase
20
16
  from pytest_httpserver.httpserver import URIPattern
21
17
 
18
+ if TYPE_CHECKING:
19
+ from ssl import SSLContext
20
+
21
+ from werkzeug.wrappers import Request
22
+ from werkzeug.wrappers import Response
23
+
22
24
 
23
25
  class BlockingRequestHandler(RequestHandlerBase):
24
26
  """
@@ -59,23 +61,23 @@ class BlockingHTTPServer(HTTPServerBase):
59
61
  self,
60
62
  host=DEFAULT_LISTEN_HOST,
61
63
  port=DEFAULT_LISTEN_PORT,
62
- ssl_context: Optional[SSLContext] = None,
64
+ ssl_context: SSLContext | None = None,
63
65
  timeout: int = 30,
64
66
  ):
65
67
  super().__init__(host, port, ssl_context)
66
68
  self.timeout = timeout
67
69
  self.request_queue: Queue[Request] = Queue()
68
- self.request_handlers: Dict[Request, Queue[BlockingRequestHandler]] = {}
70
+ self.request_handlers: dict[Request, Queue[BlockingRequestHandler]] = {}
69
71
 
70
72
  def assert_request(
71
73
  self,
72
- uri: Union[str, URIPattern, Pattern[str]],
74
+ uri: str | URIPattern | Pattern[str],
73
75
  method: str = METHOD_ALL,
74
- data: Union[str, bytes, None] = None,
76
+ data: str | bytes | None = None,
75
77
  data_encoding: str = "utf-8",
76
- headers: Optional[Mapping[str, str]] = None,
77
- query_string: Union[None, QueryMatcher, str, bytes, Mapping] = None,
78
- header_value_matcher: Optional[HeaderValueMatcher] = None,
78
+ headers: Mapping[str, str] | None = None,
79
+ query_string: None | QueryMatcher | str | bytes | Mapping = None,
80
+ header_value_matcher: HeaderValueMatcher | None = None,
79
81
  json: Any = UNDEFINED,
80
82
  timeout: int = 30,
81
83
  ) -> BlockingRequestHandler:
@@ -127,7 +129,7 @@ class BlockingHTTPServer(HTTPServerBase):
127
129
  try:
128
130
  request = self.request_queue.get(timeout=timeout)
129
131
  except Empty:
130
- raise AssertionError(f"Waiting for request {matcher} timed out")
132
+ raise AssertionError(f"Waiting for request {matcher} timed out") # noqa: EM102
131
133
 
132
134
  diff = matcher.difference(request)
133
135
 
@@ -137,7 +139,7 @@ class BlockingHTTPServer(HTTPServerBase):
137
139
 
138
140
  if diff:
139
141
  request_handler.respond_with_response(self.respond_nohandler(request))
140
- raise AssertionError(f"Request {matcher} does not match: {diff}")
142
+ raise AssertionError(f"Request {matcher} does not match: {diff}") # noqa: EM102
141
143
 
142
144
  return request_handler
143
145
 
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  import abc
2
4
  import ipaddress
3
5
  import json
@@ -11,11 +13,11 @@ from contextlib import contextmanager
11
13
  from contextlib import suppress
12
14
  from copy import copy
13
15
  from enum import Enum
14
- from ssl import SSLContext
16
+ from typing import TYPE_CHECKING
15
17
  from typing import Any
16
18
  from typing import Callable
19
+ from typing import ClassVar
17
20
  from typing import Iterable
18
- from typing import List
19
21
  from typing import Mapping
20
22
  from typing import MutableMapping
21
23
  from typing import Optional
@@ -30,6 +32,9 @@ from werkzeug.serving import make_server
30
32
  from werkzeug.wrappers import Request
31
33
  from werkzeug.wrappers import Response
32
34
 
35
+ if TYPE_CHECKING:
36
+ from ssl import SSLContext
37
+
33
38
  URI_DEFAULT = ""
34
39
  METHOD_ALL = "__ALL"
35
40
 
@@ -54,32 +59,24 @@ class Error(Exception):
54
59
  Base class for all exception defined in this package.
55
60
  """
56
61
 
57
- pass
58
-
59
62
 
60
63
  class NoHandlerError(Error):
61
64
  """
62
65
  Raised when a :py:class:`RequestHandler` has no registered method to serve the request.
63
66
  """
64
67
 
65
- pass
66
-
67
68
 
68
69
  class HTTPServerError(Error):
69
70
  """
70
71
  Raised when there's a problem with HTTP server.
71
72
  """
72
73
 
73
- pass
74
-
75
74
 
76
75
  class NoMethodFoundForMatchingHeaderValueError(Error):
77
76
  """
78
77
  Raised when a :py:class:`HeaderValueMatcher` has no registered method to match the header value.
79
78
  """
80
79
 
81
- pass
82
-
83
80
 
84
81
  class WaitingSettings:
85
82
  """Class for providing default settings and storing them in HTTPServer
@@ -89,7 +86,12 @@ class WaitingSettings:
89
86
  :param timeout: time (in seconds) until time is out
90
87
  """
91
88
 
92
- def __init__(self, raise_assertions: bool = True, stop_on_nohandler: bool = True, timeout: float = 5):
89
+ def __init__(
90
+ self,
91
+ raise_assertions: bool = True, # noqa: FBT001
92
+ stop_on_nohandler: bool = True, # noqa: FBT001
93
+ timeout: float = 5,
94
+ ):
93
95
  self.raise_assertions = raise_assertions
94
96
  self.stop_on_nohandler = stop_on_nohandler
95
97
  self.timeout = timeout
@@ -105,7 +107,7 @@ class Waiting:
105
107
  self._start = time.monotonic()
106
108
  self._stop = None
107
109
 
108
- def complete(self, result: bool):
110
+ def complete(self, result: bool): # noqa: FBT001
109
111
  self._result = result
110
112
  self._stop = time.monotonic()
111
113
 
@@ -127,23 +129,23 @@ class HeaderValueMatcher:
127
129
  and return whether they are equal as bool.
128
130
  """
129
131
 
130
- DEFAULT_MATCHERS: MutableMapping[str, Callable[[Optional[str], str], bool]] = {}
132
+ DEFAULT_MATCHERS: ClassVar[MutableMapping[str, Callable[[str | None, str], bool]]] = {}
131
133
 
132
- def __init__(self, matchers: Optional[Mapping[str, Callable[[Optional[str], str], bool]]] = None):
134
+ def __init__(self, matchers: Mapping[str, Callable[[str | None, str], bool]] | None = None):
133
135
  self.matchers = self.DEFAULT_MATCHERS if matchers is None else matchers
134
136
 
135
137
  @staticmethod
136
- def authorization_header_value_matcher(actual: Optional[str], expected: str) -> bool:
137
- callable = getattr(Authorization, "from_header", None)
138
- if callable is None: # Werkzeug < 2.3.0
139
- callable = werkzeug.http.parse_authorization_header # type: ignore[attr-defined]
140
- return callable(actual) == callable(expected)
138
+ def authorization_header_value_matcher(actual: str | None, expected: str) -> bool:
139
+ func = getattr(Authorization, "from_header", None)
140
+ if func is None: # Werkzeug < 2.3.0
141
+ func = werkzeug.http.parse_authorization_header # type: ignore[attr-defined]
142
+ return func(actual) == func(expected)
141
143
 
142
144
  @staticmethod
143
- def default_header_value_matcher(actual: Optional[str], expected: str) -> bool:
145
+ def default_header_value_matcher(actual: str | None, expected: str) -> bool:
144
146
  return actual == expected
145
147
 
146
- def __call__(self, header_name: str, actual: Optional[str], expected: str) -> bool:
148
+ def __call__(self, header_name: str, actual: str | None, expected: str) -> bool:
147
149
  try:
148
150
  matcher = self.matchers[header_name]
149
151
  except KeyError:
@@ -181,7 +183,7 @@ class StringQueryMatcher(QueryMatcher):
181
183
  Matches a query for a string or bytes specified
182
184
  """
183
185
 
184
- def __init__(self, query_string: Union[bytes, str]):
186
+ def __init__(self, query_string: bytes | str):
185
187
  """
186
188
  :param query_string: the query string will be compared to this string or bytes.
187
189
  If string is specified, it will be encoded by the encode() method.
@@ -209,7 +211,7 @@ class MappingQueryMatcher(QueryMatcher):
209
211
  Matches a query string to a dictionary or MultiDict specified
210
212
  """
211
213
 
212
- def __init__(self, query_dict: Union[Mapping, MultiDict]):
214
+ def __init__(self, query_dict: Mapping | MultiDict):
213
215
  """
214
216
  :param query_dict: if dictionary (Mapping) is specified, it will be used as a
215
217
  key-value mapping where both key and value should be string. If there are multiple
@@ -232,26 +234,26 @@ class BooleanQueryMatcher(QueryMatcher):
232
234
  Matches the query depending on the boolean value
233
235
  """
234
236
 
235
- def __init__(self, result: bool):
237
+ def __init__(self, result: bool): # noqa: FBT001
236
238
  """
237
239
  :param result: if this parameter is true, the query match will be always
238
240
  successful. Otherwise, no query match will be successful.
239
241
  """
240
242
  self.result = result
241
243
 
242
- def get_comparing_values(self, request_query_string):
244
+ def get_comparing_values(self, request_query_string): # noqa: ARG002
243
245
  if self.result:
244
246
  return (True, True)
245
247
  else:
246
248
  return (True, False)
247
249
 
248
250
 
249
- def _create_query_matcher(query_string: Union[None, QueryMatcher, str, bytes, Mapping]) -> QueryMatcher:
251
+ def _create_query_matcher(query_string: None | QueryMatcher | str | bytes | Mapping) -> QueryMatcher:
250
252
  if isinstance(query_string, QueryMatcher):
251
253
  return query_string
252
254
 
253
255
  if query_string is None:
254
- return BooleanQueryMatcher(True)
256
+ return BooleanQueryMatcher(result=True)
255
257
 
256
258
  if isinstance(query_string, (str, bytes)):
257
259
  return StringQueryMatcher(query_string)
@@ -272,7 +274,6 @@ class URIPattern(abc.ABC):
272
274
  with "/" and does not contain the query part.
273
275
  :return: True if there's a match, False otherwise
274
276
  """
275
- pass
276
277
 
277
278
 
278
279
  class RequestMatcher:
@@ -306,13 +307,13 @@ class RequestMatcher:
306
307
 
307
308
  def __init__(
308
309
  self,
309
- uri: Union[str, URIPattern, Pattern[str]],
310
+ uri: str | URIPattern | Pattern[str],
310
311
  method: str = METHOD_ALL,
311
- data: Union[str, bytes, None] = None,
312
+ data: str | bytes | None = None,
312
313
  data_encoding: str = "utf-8",
313
- headers: Optional[Mapping[str, str]] = None,
314
- query_string: Union[None, QueryMatcher, str, bytes, Mapping] = None,
315
- header_value_matcher: Optional[HVMATCHER_T] = None,
314
+ headers: Mapping[str, str] | None = None,
315
+ query_string: None | QueryMatcher | str | bytes | Mapping = None,
316
+ header_value_matcher: HVMATCHER_T | None = None,
316
317
  json: Any = UNDEFINED,
317
318
  ):
318
319
  if json is not UNDEFINED and data is not None:
@@ -383,7 +384,7 @@ class RequestMatcher:
383
384
  #
384
385
  # also, python will raise TypeError when self.uri is a conflicting type
385
386
 
386
- return self.uri == URI_DEFAULT or path == self.uri
387
+ return self.uri in (URI_DEFAULT, path)
387
388
 
388
389
  def match_json(self, request: Request) -> bool:
389
390
  """
@@ -409,7 +410,7 @@ class RequestMatcher:
409
410
 
410
411
  return json_received == self.json
411
412
 
412
- def difference(self, request: Request) -> List[Tuple]:
413
+ def difference(self, request: Request) -> list[tuple]:
413
414
  """
414
415
  Calculates the difference between the matcher and the request.
415
416
 
@@ -421,12 +422,12 @@ class RequestMatcher:
421
422
  matches the fields set in the matcher object.
422
423
  """
423
424
 
424
- retval: List[Tuple] = []
425
+ retval: list[tuple] = []
425
426
 
426
427
  if not self.match_uri(request):
427
428
  retval.append(("uri", request.path, self.uri))
428
429
 
429
- if self.method != METHOD_ALL and self.method != request.method:
430
+ if self.method not in (METHOD_ALL, request.method):
430
431
  retval.append(("method", request.method, self.method))
431
432
 
432
433
  if not self.query_matcher.match(request.query_string):
@@ -468,7 +469,7 @@ class RequestHandlerBase(abc.ABC):
468
469
  self,
469
470
  response_json,
470
471
  status: int = 200,
471
- headers: Optional[Mapping[str, str]] = None,
472
+ headers: Mapping[str, str] | None = None,
472
473
  content_type: str = "application/json",
473
474
  ):
474
475
  """
@@ -485,11 +486,11 @@ class RequestHandlerBase(abc.ABC):
485
486
 
486
487
  def respond_with_data(
487
488
  self,
488
- response_data: Union[str, bytes] = "",
489
+ response_data: str | bytes = "",
489
490
  status: int = 200,
490
- headers: Optional[HEADERS_T] = None,
491
- mimetype: Optional[str] = None,
492
- content_type: Optional[str] = None,
491
+ headers: HEADERS_T | None = None,
492
+ mimetype: str | None = None,
493
+ content_type: str | None = None,
493
494
  ):
494
495
  """
495
496
  Prepares a response with raw data.
@@ -514,8 +515,6 @@ class RequestHandlerBase(abc.ABC):
514
515
  :param response: the response object which will be responded
515
516
  """
516
517
 
517
- pass
518
-
519
518
 
520
519
  class RequestHandler(RequestHandlerBase):
521
520
  """
@@ -529,7 +528,7 @@ class RequestHandler(RequestHandlerBase):
529
528
 
530
529
  def __init__(self, matcher: RequestMatcher):
531
530
  self.matcher = matcher
532
- self.request_handler: Optional[Callable[[Request], Response]] = None
531
+ self.request_handler: Callable[[Request], Response] | None = None
533
532
 
534
533
  def respond(self, request: Request) -> Response:
535
534
  """
@@ -576,7 +575,7 @@ class RequestHandlerList(list):
576
575
 
577
576
  """
578
577
 
579
- def match(self, request: Request) -> Optional[RequestHandler]:
578
+ def match(self, request: Request) -> RequestHandler | None:
580
579
  """
581
580
  Returns the first request handler which matches the specified request. Otherwise, it returns `None`.
582
581
  """
@@ -619,7 +618,7 @@ class HTTPServerBase(abc.ABC): # pylint: disable=too-many-instance-attributes
619
618
  self,
620
619
  host: str,
621
620
  port: int,
622
- ssl_context: Optional[SSLContext] = None,
621
+ ssl_context: SSLContext | None = None,
623
622
  ):
624
623
  """
625
624
  Initializes the instance.
@@ -629,9 +628,9 @@ class HTTPServerBase(abc.ABC): # pylint: disable=too-many-instance-attributes
629
628
  self.port = port
630
629
  self.server = None
631
630
  self.server_thread = None
632
- self.assertions: List[str] = []
633
- self.handler_errors: List[Exception] = []
634
- self.log: List[Tuple[Request, Response]] = []
631
+ self.assertions: list[str] = []
632
+ self.handler_errors: list[Exception] = []
633
+ self.log: list[tuple[Request, Response]] = []
635
634
  self.ssl_context = ssl_context
636
635
  self.no_handler_status_code = 500
637
636
 
@@ -821,9 +820,9 @@ class HTTPServerBase(abc.ABC): # pylint: disable=too-many-instance-attributes
821
820
  As the result, there's an assertion added (which can be raised by :py:meth:`check_assertions`).
822
821
 
823
822
  """
824
- text = "No handler found for request {!r}.\n".format(request)
823
+ text = "No handler found for request {!r} with data {!r}.".format(request, request.data)
825
824
  self.add_assertion(text + extra_message)
826
- return Response("No handler found for this request", self.no_handler_status_code)
825
+ return Response(text + extra_message, self.no_handler_status_code)
827
826
 
828
827
  @abc.abstractmethod
829
828
  def dispatch(self, request: Request) -> Response:
@@ -833,7 +832,6 @@ class HTTPServerBase(abc.ABC): # pylint: disable=too-many-instance-attributes
833
832
  :param request: the request object from the werkzeug library
834
833
  :return: the response object what the handler responded, or a response which contains the error
835
834
  """
836
- pass
837
835
 
838
836
  @Request.application # type: ignore
839
837
  def application(self, request: Request):
@@ -916,15 +914,15 @@ class HTTPServer(HTTPServerBase): # pylint: disable=too-many-instance-attribute
916
914
  self,
917
915
  host=DEFAULT_LISTEN_HOST,
918
916
  port=DEFAULT_LISTEN_PORT,
919
- ssl_context: Optional[SSLContext] = None,
920
- default_waiting_settings: Optional[WaitingSettings] = None,
917
+ ssl_context: SSLContext | None = None,
918
+ default_waiting_settings: WaitingSettings | None = None,
921
919
  ):
922
920
  """
923
921
  Initializes the instance.
924
922
  """
925
923
  super().__init__(host, port, ssl_context)
926
924
 
927
- self.ordered_handlers: List[RequestHandler] = []
925
+ self.ordered_handlers: list[RequestHandler] = []
928
926
  self.oneshot_handlers = RequestHandlerList()
929
927
  self.handlers = RequestHandlerList()
930
928
  self.permanently_failed = False
@@ -957,13 +955,13 @@ class HTTPServer(HTTPServerBase): # pylint: disable=too-many-instance-attribute
957
955
 
958
956
  def expect_request(
959
957
  self,
960
- uri: Union[str, URIPattern, Pattern[str]],
958
+ uri: str | URIPattern | Pattern[str],
961
959
  method: str = METHOD_ALL,
962
- data: Union[str, bytes, None] = None,
960
+ data: str | bytes | None = None,
963
961
  data_encoding: str = "utf-8",
964
- headers: Optional[Mapping[str, str]] = None,
965
- query_string: Union[None, QueryMatcher, str, bytes, Mapping] = None,
966
- header_value_matcher: Optional[HVMATCHER_T] = None,
962
+ headers: Mapping[str, str] | None = None,
963
+ query_string: None | QueryMatcher | str | bytes | Mapping = None,
964
+ header_value_matcher: HVMATCHER_T | None = None,
967
965
  handler_type: HandlerType = HandlerType.PERMANENT,
968
966
  json: Any = UNDEFINED,
969
967
  ) -> RequestHandler:
@@ -1040,13 +1038,13 @@ class HTTPServer(HTTPServerBase): # pylint: disable=too-many-instance-attribute
1040
1038
 
1041
1039
  def expect_oneshot_request(
1042
1040
  self,
1043
- uri: Union[str, URIPattern, Pattern[str]],
1041
+ uri: str | URIPattern | Pattern[str],
1044
1042
  method: str = METHOD_ALL,
1045
- data: Union[str, bytes, None] = None,
1043
+ data: str | bytes | None = None,
1046
1044
  data_encoding: str = "utf-8",
1047
- headers: Optional[Mapping[str, str]] = None,
1048
- query_string: Union[None, QueryMatcher, str, bytes, Mapping] = None,
1049
- header_value_matcher: Optional[HVMATCHER_T] = None,
1045
+ headers: Mapping[str, str] | None = None,
1046
+ query_string: None | QueryMatcher | str | bytes | Mapping = None,
1047
+ header_value_matcher: HVMATCHER_T | None = None,
1050
1048
  json: Any = UNDEFINED,
1051
1049
  ) -> RequestHandler:
1052
1050
  """
@@ -1095,13 +1093,13 @@ class HTTPServer(HTTPServerBase): # pylint: disable=too-many-instance-attribute
1095
1093
 
1096
1094
  def expect_ordered_request(
1097
1095
  self,
1098
- uri: Union[str, URIPattern, Pattern[str]],
1096
+ uri: str | URIPattern | Pattern[str],
1099
1097
  method: str = METHOD_ALL,
1100
- data: Union[str, bytes, None] = None,
1098
+ data: str | bytes | None = None,
1101
1099
  data_encoding: str = "utf-8",
1102
- headers: Optional[Mapping[str, str]] = None,
1103
- query_string: Union[None, QueryMatcher, str, bytes, Mapping] = None,
1104
- header_value_matcher: Optional[HVMATCHER_T] = None,
1100
+ headers: Mapping[str, str] | None = None,
1101
+ query_string: None | QueryMatcher | str | bytes | Mapping = None,
1102
+ header_value_matcher: HVMATCHER_T | None = None,
1105
1103
  json: Any = UNDEFINED,
1106
1104
  ) -> RequestHandler:
1107
1105
  """
@@ -1185,7 +1183,7 @@ class HTTPServer(HTTPServerBase): # pylint: disable=too-many-instance-attribute
1185
1183
 
1186
1184
  """
1187
1185
  if self._waiting_settings.stop_on_nohandler:
1188
- self._set_waiting_result(False)
1186
+ self._set_waiting_result(value=False)
1189
1187
 
1190
1188
  return super().respond_nohandler(request, self.format_matchers() + extra_message)
1191
1189
 
@@ -1263,7 +1261,7 @@ class HTTPServer(HTTPServerBase): # pylint: disable=too-many-instance-attribute
1263
1261
 
1264
1262
  return response
1265
1263
 
1266
- def _set_waiting_result(self, value: bool) -> None:
1264
+ def _set_waiting_result(self, value: bool) -> None: # noqa: FBT001
1267
1265
  """Set waiting_result
1268
1266
 
1269
1267
  Setting is implemented as putting value to queue without waiting. If queue is full we simply ignore the
@@ -1274,14 +1272,14 @@ class HTTPServer(HTTPServerBase): # pylint: disable=too-many-instance-attribute
1274
1272
 
1275
1273
  def _update_waiting_result(self) -> None:
1276
1274
  if not self.oneshot_handlers and not self.ordered_handlers:
1277
- self._set_waiting_result(True)
1275
+ self._set_waiting_result(value=True)
1278
1276
 
1279
1277
  @contextmanager
1280
1278
  def wait(
1281
1279
  self,
1282
- raise_assertions: Optional[bool] = None,
1283
- stop_on_nohandler: Optional[bool] = None,
1284
- timeout: Optional[float] = None,
1280
+ raise_assertions: bool | None = None,
1281
+ stop_on_nohandler: bool | None = None,
1282
+ timeout: float | None = None,
1285
1283
  ):
1286
1284
  """Context manager to wait until the first of following event occurs: all ordered and oneshot handlers were
1287
1285
  executed, unexpected request was received (if `stop_on_nohandler` is set to `True`), or time was out
@@ -1331,7 +1329,7 @@ class HTTPServer(HTTPServerBase): # pylint: disable=too-many-instance-attribute
1331
1329
  waiting.complete(result=False)
1332
1330
  if self._waiting_settings.raise_assertions:
1333
1331
  raise AssertionError(
1334
- "Wait timeout occurred, but some handlers left:\n" "{}".format(self.format_matchers())
1332
+ "Wait timeout occurred, but some handlers left:\n{}".format(self.format_matchers())
1335
1333
  )
1336
1334
  if self._waiting_settings.raise_assertions and not waiting.result:
1337
1335
  self.check_assertions()
@@ -54,14 +54,14 @@ def make_httpserver(httpserver_listen_address, httpserver_ssl_context):
54
54
  server.stop()
55
55
 
56
56
 
57
- def pytest_sessionfinish(session, exitstatus): # pylint: disable=unused-argument
57
+ def pytest_sessionfinish(session, exitstatus): # noqa: ARG001
58
58
  if Plugin.SERVER is not None:
59
59
  Plugin.SERVER.clear()
60
60
  if Plugin.SERVER.is_running():
61
61
  Plugin.SERVER.stop()
62
62
 
63
63
 
64
- @pytest.fixture
64
+ @pytest.fixture()
65
65
  def httpserver(make_httpserver):
66
66
  server = make_httpserver
67
67
  yield server
@@ -78,7 +78,7 @@ def make_httpserver_ipv4(httpserver_ssl_context):
78
78
  server.stop()
79
79
 
80
80
 
81
- @pytest.fixture
81
+ @pytest.fixture()
82
82
  def httpserver_ipv4(make_httpserver_ipv4):
83
83
  server = make_httpserver_ipv4
84
84
  yield server
@@ -95,7 +95,7 @@ def make_httpserver_ipv6(httpserver_ssl_context):
95
95
  server.stop()
96
96
 
97
97
 
98
- @pytest.fixture
98
+ @pytest.fixture()
99
99
  def httpserver_ipv6(make_httpserver_ipv6):
100
100
  server = make_httpserver_ipv6
101
101
  yield server
@@ -40,7 +40,7 @@ def then_the_response_is_got_from(server_connection, response):
40
40
  assert server_connection.get(timeout=9).json() == response
41
41
 
42
42
 
43
- @pytest.fixture
43
+ @pytest.fixture()
44
44
  def httpserver():
45
45
  server = BlockingHTTPServer(timeout=1)
46
46
  server.start()
@@ -97,7 +97,10 @@ def test_ignores_when_request_is_not_asserted(httpserver: BlockingHTTPServer):
97
97
  )
98
98
 
99
99
  with when_a_request_is_being_sent_to_the_server(request) as server_connection:
100
- assert server_connection.get(timeout=9).text == "No handler found for this request"
100
+ assert (
101
+ server_connection.get(timeout=9).text == "No handler found for request "
102
+ f"<Request 'http://localhost:{httpserver.port}/my/path' [GET]> with data b''."
103
+ )
101
104
 
102
105
 
103
106
  def test_raises_assertion_error_when_request_was_not_responded(httpserver: BlockingHTTPServer):
@@ -7,7 +7,7 @@ from pytest_httpserver import HTTPServer
7
7
 
8
8
  def test_check_assertions_raises_handler_assertions(httpserver: HTTPServer):
9
9
  def handler(_):
10
- assert 1 == 2
10
+ assert False # noqa: PT015
11
11
 
12
12
  httpserver.expect_request("/foobar").respond_with_handler(handler)
13
13
 
@@ -29,7 +29,7 @@ def test_check_handler_errors_raises_handler_error(httpserver: HTTPServer):
29
29
 
30
30
  httpserver.check_assertions()
31
31
 
32
- with pytest.raises(ValueError):
32
+ with pytest.raises(ValueError): # noqa: PT011
33
33
  httpserver.check_handler_errors()
34
34
 
35
35
 
@@ -48,10 +48,10 @@ def test_check_handler_errors_correct_order(httpserver: HTTPServer):
48
48
 
49
49
  httpserver.check_assertions()
50
50
 
51
- with pytest.raises(ValueError):
51
+ with pytest.raises(ValueError): # noqa: PT011
52
52
  httpserver.check_handler_errors()
53
53
 
54
- with pytest.raises(OSError):
54
+ with pytest.raises(OSError): # noqa: PT011
55
55
  httpserver.check_handler_errors()
56
56
 
57
57
  httpserver.check_handler_errors()
@@ -69,7 +69,7 @@ def test_missing_matcher_raises_exception(httpserver):
69
69
 
70
70
  def test_check_raises_errors_in_order(httpserver):
71
71
  def handler1(_):
72
- assert 1 == 2
72
+ assert False # noqa: PT015
73
73
 
74
74
  def handler2(_):
75
75
  pass # does nothing
@@ -88,5 +88,5 @@ def test_check_raises_errors_in_order(httpserver):
88
88
  with pytest.raises(AssertionError):
89
89
  httpserver.check()
90
90
 
91
- with pytest.raises(ValueError):
91
+ with pytest.raises(ValueError): # noqa: PT011
92
92
  httpserver.check()
@@ -36,5 +36,5 @@ def test_json_matcher_with_invalid_json(httpserver: HTTPServer):
36
36
 
37
37
 
38
38
  def test_data_and_json_mutually_exclusive(httpserver: HTTPServer):
39
- with pytest.raises(ValueError):
39
+ with pytest.raises(ValueError): # noqa: PT011
40
40
  httpserver.expect_request("/foo", json={}, data="foo")
@@ -1,6 +1,6 @@
1
+ from __future__ import annotations
2
+
1
3
  import urllib.parse
2
- from typing import List
3
- from typing import Tuple
4
4
 
5
5
  import pytest
6
6
 
@@ -17,6 +17,6 @@ parse_qsl_semicolon_cases = [
17
17
  ]
18
18
 
19
19
 
20
- @pytest.mark.parametrize("qs,expected", parse_qsl_semicolon_cases)
21
- def test_qsl(qs: str, expected: List[Tuple[bytes, bytes]]):
20
+ @pytest.mark.parametrize(("qs", "expected"), parse_qsl_semicolon_cases)
21
+ def test_qsl(qs: str, expected: list[tuple[bytes, bytes]]):
22
22
  assert urllib.parse.parse_qsl(qs, keep_blank_values=True) == expected
@@ -9,7 +9,7 @@ PORT_KEY = "PYTEST_HTTPSERVER_PORT"
9
9
  HOST_KEY = "PYTEST_HTTPSERVER_HOST"
10
10
 
11
11
 
12
- @pytest.fixture
12
+ @pytest.fixture()
13
13
  def tmpenv():
14
14
  old_vars = {}
15
15
  for key in (HOST_KEY, PORT_KEY):
@@ -37,7 +37,7 @@ def test_port_changing_by_environment(httpserver: HTTPServer):
37
37
  assert httpserver.port == int(os.environ[PORT_KEY])
38
38
 
39
39
 
40
- def test_get_httpserver_listen_address_with_env(tmpenv):
40
+ def test_get_httpserver_listen_address_with_env(tmpenv): # noqa: ARG001
41
41
  address = get_httpserver_listen_address()
42
42
  assert address[0] == "5.5.5.5"
43
43
  assert address[1] == 12345
@@ -28,7 +28,7 @@ def test_qm_bytes():
28
28
 
29
29
 
30
30
  def test_qm_boolean():
31
- qm = BooleanQueryMatcher(True)
31
+ qm = BooleanQueryMatcher(result=True)
32
32
  assert_match(qm, b"k1=v1")
33
33
 
34
34
 
@@ -1,5 +1,4 @@
1
- # TODO: skip if poetry is not available or add mark to test it explicitly
2
-
1
+ from __future__ import annotations
3
2
 
4
3
  import email
5
4
  import re
@@ -10,11 +9,13 @@ import zipfile
10
9
  from dataclasses import dataclass
11
10
  from pathlib import Path
12
11
  from typing import Iterable
13
- from typing import Tuple
14
12
 
15
13
  import pytest
16
14
  import toml
17
15
 
16
+ # TODO: skip if poetry is not available or add mark to test it explicitly
17
+
18
+
18
19
  pytestmark = pytest.mark.release
19
20
 
20
21
  NAME = "pytest-httpserver"
@@ -45,7 +46,7 @@ class Wheel:
45
46
 
46
47
  def extract(self):
47
48
  with zipfile.ZipFile(self.path) as zf:
48
- zf.extractall(self.wheel_out_dir)
49
+ zf.extractall(self.wheel_out_dir) # noqa: S202
49
50
 
50
51
  def get_meta(self, version: str, name: str = NAME_UNDERSCORE) -> email.message.Message:
51
52
  metadata_path = self.wheel_out_dir.joinpath(f"{name}-{version}.dist-info", "METADATA")
@@ -65,7 +66,7 @@ class Sdist:
65
66
 
66
67
  def extract(self):
67
68
  with tarfile.open(self.path, mode="r:gz") as tf:
68
- tf.extractall(self.sdist_out_dir)
69
+ tf.extractall(self.sdist_out_dir) # noqa: S202
69
70
 
70
71
 
71
72
  @dataclass
@@ -104,7 +105,7 @@ def version(pyproject) -> str:
104
105
  return pyproject["tool"]["poetry"]["version"]
105
106
 
106
107
 
107
- def version_to_tuple(version: str) -> Tuple:
108
+ def version_to_tuple(version: str) -> tuple:
108
109
  return tuple([int(x) for x in version.split(".")])
109
110
 
110
111