opentelemetry-instrumentation-aiohttp-server 0.42b0__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.
@@ -0,0 +1,60 @@
1
+ *.py[cod]
2
+ *.sw[op]
3
+
4
+ # C extensions
5
+ *.so
6
+
7
+ # Packages
8
+ *.egg
9
+ *.egg-info
10
+ dist
11
+ dist-info
12
+ build
13
+ eggs
14
+ parts
15
+ bin
16
+ var
17
+ sdist
18
+ develop-eggs
19
+ .installed.cfg
20
+ pyvenv.cfg
21
+ lib
22
+ lib64
23
+ __pycache__
24
+ venv*/
25
+ .venv*/
26
+
27
+ # Installer logs
28
+ pip-log.txt
29
+
30
+ # Unit test / coverage reports
31
+ coverage.xml
32
+ .coverage
33
+ .nox
34
+ .tox
35
+ .cache
36
+ htmlcov
37
+
38
+ # Translations
39
+ *.mo
40
+
41
+ # Mac
42
+ .DS_Store
43
+
44
+ # Mr Developer
45
+ .mr.developer.cfg
46
+ .project
47
+ .pydevproject
48
+
49
+ # JetBrains
50
+ .idea
51
+
52
+ # VSCode
53
+ .vscode
54
+
55
+ # Sphinx
56
+ _build/
57
+
58
+ # mypy
59
+ .mypy_cache/
60
+ target
@@ -0,0 +1,55 @@
1
+ Metadata-Version: 2.3
2
+ Name: opentelemetry-instrumentation-aiohttp-server
3
+ Version: 0.42b0
4
+ Summary: Aiohttp server instrumentation for OpenTelemetry
5
+ Project-URL: Homepage, https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/instrumentation/opentelemetry-instrumentation-aiohttp-server
6
+ Author-email: OpenTelemetry Authors <cncf-opentelemetry-contributors@lists.cncf.io>
7
+ License-Expression: Apache-2.0
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: Apache Software License
11
+ Classifier: Programming Language :: Python
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.7
14
+ Classifier: Programming Language :: Python :: 3.8
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Requires-Python: >=3.7
19
+ Requires-Dist: opentelemetry-api~=1.12
20
+ Requires-Dist: opentelemetry-instrumentation==0.42b0
21
+ Requires-Dist: opentelemetry-semantic-conventions==0.42b0
22
+ Requires-Dist: opentelemetry-util-http==0.42b0
23
+ Requires-Dist: wrapt<2.0.0,>=1.0.0
24
+ Provides-Extra: instruments
25
+ Requires-Dist: aiohttp~=3.0; extra == 'instruments'
26
+ Provides-Extra: test
27
+ Requires-Dist: aiohttp~=3.0; extra == 'test'
28
+ Requires-Dist: pytest-aiohttp; extra == 'test'
29
+ Requires-Dist: pytest-asyncio; extra == 'test'
30
+ Description-Content-Type: text/x-rst
31
+
32
+ OpenTelemetry aiohttp server Integration
33
+ ========================================
34
+
35
+ |pypi|
36
+
37
+ .. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-aiohttp-client.svg
38
+ :target: https://pypi.org/project/opentelemetry-instrumentation-aiohttp-client/
39
+
40
+ This library allows tracing HTTP requests made by the
41
+ `aiohttp server <https://docs.aiohttp.org/en/stable/server.html>`_ library.
42
+
43
+ Installation
44
+ ------------
45
+
46
+ ::
47
+
48
+ pip install opentelemetry-instrumentation-aiohttp-server
49
+
50
+ References
51
+ ----------
52
+
53
+ * `OpenTelemetry Project <https://opentelemetry.io/>`_
54
+ * `aiohttp client Tracing <https://docs.aiohttp.org/en/stable/tracing_reference.html>`_
55
+ * `OpenTelemetry Python Examples <https://github.com/open-telemetry/opentelemetry-python/tree/main/docs/examples>`_
@@ -0,0 +1,24 @@
1
+ OpenTelemetry aiohttp server Integration
2
+ ========================================
3
+
4
+ |pypi|
5
+
6
+ .. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-aiohttp-client.svg
7
+ :target: https://pypi.org/project/opentelemetry-instrumentation-aiohttp-client/
8
+
9
+ This library allows tracing HTTP requests made by the
10
+ `aiohttp server <https://docs.aiohttp.org/en/stable/server.html>`_ library.
11
+
12
+ Installation
13
+ ------------
14
+
15
+ ::
16
+
17
+ pip install opentelemetry-instrumentation-aiohttp-server
18
+
19
+ References
20
+ ----------
21
+
22
+ * `OpenTelemetry Project <https://opentelemetry.io/>`_
23
+ * `aiohttp client Tracing <https://docs.aiohttp.org/en/stable/tracing_reference.html>`_
24
+ * `OpenTelemetry Python Examples <https://github.com/open-telemetry/opentelemetry-python/tree/main/docs/examples>`_
@@ -0,0 +1,61 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "opentelemetry-instrumentation-aiohttp-server"
7
+ dynamic = ["version"]
8
+ description = "Aiohttp server instrumentation for OpenTelemetry"
9
+ readme = "README.rst"
10
+ license = "Apache-2.0"
11
+ requires-python = ">=3.7"
12
+ authors = [
13
+ { name = "OpenTelemetry Authors", email = "cncf-opentelemetry-contributors@lists.cncf.io"}
14
+ ]
15
+ classifiers = [
16
+ "Development Status :: 4 - Beta",
17
+ "Intended Audience :: Developers",
18
+ "License :: OSI Approved :: Apache Software License",
19
+ "Programming Language :: Python",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.7",
22
+ "Programming Language :: Python :: 3.8",
23
+ "Programming Language :: Python :: 3.9",
24
+ "Programming Language :: Python :: 3.10",
25
+ "Programming Language :: Python :: 3.11"
26
+ ]
27
+ dependencies = [
28
+ "opentelemetry-api ~= 1.12",
29
+ "opentelemetry-instrumentation == 0.42b0",
30
+ "opentelemetry-semantic-conventions == 0.42b0",
31
+ "opentelemetry-util-http == 0.42b0",
32
+ "wrapt >= 1.0.0, < 2.0.0",
33
+ ]
34
+
35
+ [project.optional-dependencies]
36
+ instruments = [
37
+ "aiohttp ~= 3.0",
38
+ ]
39
+ test = [
40
+ "opentelemetry-instrumentation-aiohttp-server[instruments]",
41
+ "pytest-asyncio",
42
+ "pytest-aiohttp",
43
+ ]
44
+
45
+ [project.entry-points.opentelemetry_instrumentor]
46
+ aiohttp-server = "opentelemetry.instrumentation.aiohttp_server:AioHttpServerInstrumentor"
47
+
48
+ [project.urls]
49
+ Homepage = "https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/instrumentation/opentelemetry-instrumentation-aiohttp-server"
50
+
51
+ [tool.hatch.version]
52
+ path = "src/opentelemetry/instrumentation/aiohttp_server/version.py"
53
+
54
+ [tool.hatch.build.targets.sdist]
55
+ include = [
56
+ "/src",
57
+ "/tests",
58
+ ]
59
+
60
+ [tool.hatch.build.targets.wheel]
61
+ packages = ["src/opentelemetry"]
@@ -0,0 +1,267 @@
1
+ # Copyright 2020, OpenTelemetry Authors
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import urllib
16
+ from aiohttp import web
17
+ from multidict import CIMultiDictProxy
18
+ from timeit import default_timer
19
+ from typing import Tuple, Dict, List, Union
20
+
21
+ from opentelemetry import context, trace, metrics
22
+ from opentelemetry.context import _SUPPRESS_HTTP_INSTRUMENTATION_KEY
23
+ from opentelemetry.instrumentation.aiohttp_server.package import _instruments
24
+ from opentelemetry.instrumentation.aiohttp_server.version import __version__
25
+ from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
26
+ from opentelemetry.instrumentation.utils import http_status_to_status_code
27
+ from opentelemetry.propagators.textmap import Getter
28
+ from opentelemetry.propagate import extract
29
+ from opentelemetry.semconv.trace import SpanAttributes
30
+ from opentelemetry.semconv.metrics import MetricInstruments
31
+ from opentelemetry.trace.status import Status, StatusCode
32
+ from opentelemetry.util.http import get_excluded_urls
33
+ from opentelemetry.util.http import remove_url_credentials
34
+
35
+ _duration_attrs = [
36
+ SpanAttributes.HTTP_METHOD,
37
+ SpanAttributes.HTTP_HOST,
38
+ SpanAttributes.HTTP_SCHEME,
39
+ SpanAttributes.HTTP_STATUS_CODE,
40
+ SpanAttributes.HTTP_FLAVOR,
41
+ SpanAttributes.HTTP_SERVER_NAME,
42
+ SpanAttributes.NET_HOST_NAME,
43
+ SpanAttributes.NET_HOST_PORT,
44
+ SpanAttributes.HTTP_ROUTE,
45
+ ]
46
+
47
+ _active_requests_count_attrs = [
48
+ SpanAttributes.HTTP_METHOD,
49
+ SpanAttributes.HTTP_HOST,
50
+ SpanAttributes.HTTP_SCHEME,
51
+ SpanAttributes.HTTP_FLAVOR,
52
+ SpanAttributes.HTTP_SERVER_NAME,
53
+ ]
54
+
55
+ tracer = trace.get_tracer(__name__)
56
+ meter = metrics.get_meter(__name__, __version__)
57
+ _excluded_urls = get_excluded_urls("AIOHTTP_SERVER")
58
+
59
+
60
+ def _parse_duration_attrs(req_attrs):
61
+ duration_attrs = {}
62
+ for attr_key in _duration_attrs:
63
+ if req_attrs.get(attr_key) is not None:
64
+ duration_attrs[attr_key] = req_attrs[attr_key]
65
+ return duration_attrs
66
+
67
+
68
+ def _parse_active_request_count_attrs(req_attrs):
69
+ active_requests_count_attrs = {}
70
+ for attr_key in _active_requests_count_attrs:
71
+ if req_attrs.get(attr_key) is not None:
72
+ active_requests_count_attrs[attr_key] = req_attrs[attr_key]
73
+ return active_requests_count_attrs
74
+
75
+
76
+ def get_default_span_details(request: web.Request) -> Tuple[str, dict]:
77
+ """Default implementation for get_default_span_details
78
+ Args:
79
+ request: the request object itself.
80
+ Returns:
81
+ a tuple of the span name, and any attributes to attach to the span.
82
+ """
83
+ span_name = request.path.strip() or f"HTTP {request.method}"
84
+ return span_name, {}
85
+
86
+
87
+ def _get_view_func(request: web.Request) -> str:
88
+ """Returns the name of the request handler.
89
+ Args:
90
+ request: the request object itself.
91
+ Returns:
92
+ a string containing the name of the handler function
93
+ """
94
+ try:
95
+ return request.match_info.handler.__name__
96
+ except AttributeError:
97
+ return "unknown"
98
+
99
+
100
+ def collect_request_attributes(request: web.Request) -> Dict:
101
+ """Collects HTTP request attributes from the ASGI scope and returns a
102
+ dictionary to be used as span creation attributes."""
103
+
104
+ server_host, port, http_url = (
105
+ request.url.host,
106
+ request.url.port,
107
+ str(request.url),
108
+ )
109
+ query_string = request.query_string
110
+ if query_string and http_url:
111
+ if isinstance(query_string, bytes):
112
+ query_string = query_string.decode("utf8")
113
+ http_url += "?" + urllib.parse.unquote(query_string)
114
+
115
+ result = {
116
+ SpanAttributes.HTTP_SCHEME: request.scheme,
117
+ SpanAttributes.HTTP_HOST: server_host,
118
+ SpanAttributes.NET_HOST_PORT: port,
119
+ SpanAttributes.HTTP_ROUTE: _get_view_func(request),
120
+ SpanAttributes.HTTP_FLAVOR: f"{request.version.major}.{request.version.minor}",
121
+ SpanAttributes.HTTP_TARGET: request.path,
122
+ SpanAttributes.HTTP_URL: remove_url_credentials(http_url),
123
+ }
124
+
125
+ http_method = request.method
126
+ if http_method:
127
+ result[SpanAttributes.HTTP_METHOD] = http_method
128
+
129
+ http_host_value_list = (
130
+ [request.host] if type(request.host) != list else request.host
131
+ )
132
+ if http_host_value_list:
133
+ result[SpanAttributes.HTTP_SERVER_NAME] = ",".join(
134
+ http_host_value_list
135
+ )
136
+ http_user_agent = request.headers.get("user-agent")
137
+ if http_user_agent:
138
+ result[SpanAttributes.HTTP_USER_AGENT] = http_user_agent
139
+
140
+ # remove None values
141
+ result = {k: v for k, v in result.items() if v is not None}
142
+
143
+ return result
144
+
145
+
146
+ def set_status_code(span, status_code: int) -> None:
147
+ """Adds HTTP response attributes to span using the status_code argument."""
148
+
149
+ try:
150
+ status_code = int(status_code)
151
+ except ValueError:
152
+ span.set_status(
153
+ Status(
154
+ StatusCode.ERROR,
155
+ "Non-integer HTTP status: " + repr(status_code),
156
+ )
157
+ )
158
+ else:
159
+ span.set_attribute(SpanAttributes.HTTP_STATUS_CODE, status_code)
160
+ span.set_status(
161
+ Status(http_status_to_status_code(status_code, server_span=True))
162
+ )
163
+
164
+
165
+ class AiohttpGetter(Getter):
166
+ """Extract current trace from headers"""
167
+
168
+ def get(self, carrier, key: str) -> Union[List, None]:
169
+ """Getter implementation to retrieve an HTTP header value from the ASGI
170
+ scope.
171
+
172
+ Args:
173
+ carrier: ASGI scope object
174
+ key: header name in scope
175
+ Returns:
176
+ A list of all header values matching the key, or None if the key
177
+ does not match any header.
178
+ """
179
+ headers: CIMultiDictProxy = carrier.headers
180
+ if not headers:
181
+ return None
182
+ return headers.getall(key, None)
183
+
184
+ def keys(self, carrier: Dict) -> List:
185
+ return list(carrier.keys())
186
+
187
+
188
+ getter = AiohttpGetter()
189
+
190
+
191
+ @web.middleware
192
+ async def middleware(request, handler):
193
+ """Middleware for aiohttp implementing tracing logic"""
194
+ if (
195
+ context.get_value("suppress_instrumentation")
196
+ or context.get_value(_SUPPRESS_HTTP_INSTRUMENTATION_KEY)
197
+ or _excluded_urls.url_disabled(request.url.path)
198
+ ):
199
+ return await handler(request)
200
+
201
+ span_name, additional_attributes = get_default_span_details(request)
202
+
203
+ req_attrs = collect_request_attributes(request)
204
+ duration_attrs = _parse_duration_attrs(req_attrs)
205
+ active_requests_count_attrs = _parse_active_request_count_attrs(req_attrs)
206
+
207
+ duration_histogram = meter.create_histogram(
208
+ name=MetricInstruments.HTTP_SERVER_DURATION,
209
+ unit="ms",
210
+ description="measures the duration of the inbound HTTP request",
211
+ )
212
+
213
+ active_requests_counter = meter.create_up_down_counter(
214
+ name=MetricInstruments.HTTP_SERVER_ACTIVE_REQUESTS,
215
+ unit="requests",
216
+ description="measures the number of concurrent HTTP requests those are currently in flight",
217
+ )
218
+
219
+ with tracer.start_as_current_span(
220
+ span_name,
221
+ context=extract(request, getter=getter),
222
+ kind=trace.SpanKind.SERVER,
223
+ ) as span:
224
+ attributes = collect_request_attributes(request)
225
+ attributes.update(additional_attributes)
226
+ span.set_attributes(attributes)
227
+ start = default_timer()
228
+ active_requests_counter.add(1, active_requests_count_attrs)
229
+ try:
230
+ resp = await handler(request)
231
+ set_status_code(span, resp.status)
232
+ except web.HTTPException as ex:
233
+ set_status_code(span, ex.status_code)
234
+ raise
235
+ finally:
236
+ duration = max((default_timer() - start) * 1000, 0)
237
+ duration_histogram.record(duration, duration_attrs)
238
+ active_requests_counter.add(-1, active_requests_count_attrs)
239
+ return resp
240
+
241
+
242
+ class _InstrumentedApplication(web.Application):
243
+ """Insert tracing middleware"""
244
+
245
+ def __init__(self, *args, **kwargs):
246
+ middlewares = kwargs.pop("middlewares", [])
247
+ middlewares.insert(0, middleware)
248
+ kwargs["middlewares"] = middlewares
249
+ super().__init__(*args, **kwargs)
250
+
251
+
252
+ class AioHttpServerInstrumentor(BaseInstrumentor):
253
+ # pylint: disable=protected-access,attribute-defined-outside-init
254
+ """An instrumentor for aiohttp.web.Application
255
+
256
+ See `BaseInstrumentor`
257
+ """
258
+
259
+ def _instrument(self, **kwargs):
260
+ self._original_app = web.Application
261
+ setattr(web, "Application", _InstrumentedApplication)
262
+
263
+ def _uninstrument(self, **kwargs):
264
+ setattr(web, "Application", self._original_app)
265
+
266
+ def instrumentation_dependencies(self):
267
+ return _instruments
@@ -0,0 +1,16 @@
1
+ # Copyright The OpenTelemetry Authors
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+
16
+ _instruments = ("aiohttp ~= 3.0",)
@@ -0,0 +1,15 @@
1
+ # Copyright The OpenTelemetry Authors
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ __version__ = "0.42b0"
@@ -0,0 +1,105 @@
1
+ # Copyright 2020, OpenTelemetry Authors
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import pytest
16
+ import pytest_asyncio
17
+ import aiohttp
18
+ from http import HTTPStatus
19
+ from .utils import HTTPMethod
20
+
21
+ from opentelemetry import trace as trace_api
22
+ from opentelemetry.test.test_base import TestBase
23
+ from opentelemetry.instrumentation.aiohttp_server import AioHttpServerInstrumentor
24
+ from opentelemetry.semconv.trace import SpanAttributes
25
+ from opentelemetry.util._importlib_metadata import entry_points
26
+
27
+ from opentelemetry.test.globals_test import (
28
+ reset_trace_globals,
29
+ )
30
+
31
+
32
+ @pytest.fixture(scope="session")
33
+ def tracer():
34
+ test_base = TestBase()
35
+
36
+ tracer_provider, memory_exporter = test_base.create_tracer_provider()
37
+
38
+ reset_trace_globals()
39
+ trace_api.set_tracer_provider(tracer_provider)
40
+
41
+ yield tracer_provider, memory_exporter
42
+
43
+ reset_trace_globals()
44
+
45
+
46
+ async def default_handler(request, status=200):
47
+ return aiohttp.web.Response(status=status)
48
+
49
+
50
+ @pytest_asyncio.fixture
51
+ async def server_fixture(tracer, aiohttp_server):
52
+ _, memory_exporter = tracer
53
+
54
+ AioHttpServerInstrumentor().instrument()
55
+
56
+ app = aiohttp.web.Application()
57
+ app.add_routes(
58
+ [aiohttp.web.get("/test-path", default_handler)])
59
+
60
+ server = await aiohttp_server(app)
61
+ yield server, app
62
+
63
+ memory_exporter.clear()
64
+
65
+ AioHttpServerInstrumentor().uninstrument()
66
+
67
+
68
+ def test_checking_instrumentor_pkg_installed():
69
+
70
+ (instrumentor_entrypoint,) = entry_points(group="opentelemetry_instrumentor", name="aiohttp-server")
71
+ instrumentor = instrumentor_entrypoint.load()()
72
+ assert (isinstance(instrumentor, AioHttpServerInstrumentor))
73
+
74
+
75
+ @pytest.mark.asyncio
76
+ @pytest.mark.parametrize("url, expected_method, expected_status_code", [
77
+ ("/test-path", HTTPMethod.GET, HTTPStatus.OK),
78
+ ("/not-found", HTTPMethod.GET, HTTPStatus.NOT_FOUND)
79
+ ])
80
+ async def test_status_code_instrumentation(
81
+ tracer,
82
+ server_fixture,
83
+ aiohttp_client,
84
+ url,
85
+ expected_method,
86
+ expected_status_code
87
+ ):
88
+ _, memory_exporter = tracer
89
+ server, app = server_fixture
90
+
91
+ assert len(memory_exporter.get_finished_spans()) == 0
92
+
93
+ client = await aiohttp_client(server)
94
+ await client.get(url)
95
+
96
+ assert len(memory_exporter.get_finished_spans()) == 1
97
+
98
+ [span] = memory_exporter.get_finished_spans()
99
+
100
+ assert expected_method.value == span.attributes[SpanAttributes.HTTP_METHOD]
101
+ assert expected_status_code == span.attributes[SpanAttributes.HTTP_STATUS_CODE]
102
+
103
+ assert f"http://{server.host}:{server.port}{url}" == span.attributes[
104
+ SpanAttributes.HTTP_URL
105
+ ]
@@ -0,0 +1,32 @@
1
+ # Copyright 2020, OpenTelemetry Authors
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from enum import Enum
16
+
17
+
18
+ class HTTPMethod(Enum):
19
+ """HTTP methods and descriptions"""
20
+
21
+ def __repr__(self):
22
+ return f"{self.value}"
23
+
24
+ CONNECT = 'CONNECT'
25
+ DELETE = 'DELETE'
26
+ GET = 'GET'
27
+ HEAD = 'HEAD'
28
+ OPTIONS = 'OPTIONS'
29
+ PATCH = 'PATCH'
30
+ POST = 'POST'
31
+ PUT = 'PUT'
32
+ TRACE = 'TRACE'