csu 2.4.2__tar.gz → 2.5.0__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.
- {csu-2.4.2 → csu-2.5.0}/.bumpversion.cfg +1 -1
- {csu-2.4.2 → csu-2.5.0}/.cookiecutterrc +1 -1
- {csu-2.4.2 → csu-2.5.0}/.pre-commit-config.yaml +3 -3
- {csu-2.4.2 → csu-2.5.0}/PKG-INFO +3 -3
- {csu-2.4.2 → csu-2.5.0}/README.rst +2 -2
- {csu-2.4.2 → csu-2.5.0}/pyproject.toml +1 -1
- {csu-2.4.2 → csu-2.5.0}/src/csu/__init__.py +1 -1
- {csu-2.4.2 → csu-2.5.0}/src/csu/conf.py +7 -5
- {csu-2.4.2 → csu-2.5.0}/src/csu/forms/fields.py +1 -6
- {csu-2.4.2 → csu-2.5.0}/src/csu/logging.py +23 -5
- {csu-2.4.2 → csu-2.5.0}/src/csu/service.py +19 -13
- {csu-2.4.2 → csu-2.5.0}/src/csu/xml.py +2 -2
- {csu-2.4.2 → csu-2.5.0}/src/csu.egg-info/PKG-INFO +3 -3
- {csu-2.4.2 → csu-2.5.0}/tests/test_service.py +12 -12
- {csu-2.4.2 → csu-2.5.0}/tests/testproject/settings.py +3 -2
- {csu-2.4.2 → csu-2.5.0}/.coveragerc +0 -0
- {csu-2.4.2 → csu-2.5.0}/.editorconfig +0 -0
- {csu-2.4.2 → csu-2.5.0}/.github/workflows/github-actions.yml +0 -0
- {csu-2.4.2 → csu-2.5.0}/.tombi.toml +0 -0
- {csu-2.4.2 → csu-2.5.0}/AUTHORS.rst +0 -0
- {csu-2.4.2 → csu-2.5.0}/CHANGELOG.rst +0 -0
- {csu-2.4.2 → csu-2.5.0}/CONTRIBUTING.rst +0 -0
- {csu-2.4.2 → csu-2.5.0}/LICENSE +0 -0
- {csu-2.4.2 → csu-2.5.0}/MANIFEST.in +0 -0
- {csu-2.4.2 → csu-2.5.0}/ci/bootstrap.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/ci/requirements.txt +0 -0
- {csu-2.4.2 → csu-2.5.0}/ci/templates/.github/workflows/github-actions.yml +0 -0
- {csu-2.4.2 → csu-2.5.0}/pytest.ini +0 -0
- {csu-2.4.2 → csu-2.5.0}/setup.cfg +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/admin.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/consts.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/drf/__init__.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/drf/auth.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/drf/fields.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/drf/forms.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/drf/perms.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/drf/phonenumber.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/drf/serializers.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/drf/test_auth.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/drf/test_fields.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/drf/test_forms.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/drf/test_phonenumber.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/drf/test_serializers.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/drf/views.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/enums.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/env.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/exceptions.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/export.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/fixups.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/forms/__init__.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/forms/crispy.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/gettext.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/gettext_lazy.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/locale/ro/LC_MESSAGES/django.mo +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/locale/ro/LC_MESSAGES/django.po +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/management.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/models.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/query.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/routers.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/templates/api_exception.html +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/templates/forms/widgets/opaquewidget.html +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/test_consts.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/test_env.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/test_exceptions.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/test_logging.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/test_management.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/test_service.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/test_timezones.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/test_utils.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/test_xml.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/timezones.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/utils.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/views.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/worker/__init__.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/worker/admin.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/worker/asgi.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/worker/engine.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/worker/enums.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/worker/job.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/worker/models.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/worker/registry.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu/wsgi.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu.egg-info/SOURCES.txt +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu.egg-info/dependency_links.txt +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu.egg-info/requires.txt +0 -0
- {csu-2.4.2 → csu-2.5.0}/src/csu.egg-info/top_level.txt +0 -0
- {csu-2.4.2 → csu-2.5.0}/tests/cassettes/test_service/test_custom_context.yaml +0 -0
- {csu-2.4.2 → csu-2.5.0}/tests/cassettes/test_service/test_custom_context_0_retries.yaml +0 -0
- {csu-2.4.2 → csu-2.5.0}/tests/cassettes/test_service/test_decoding.yaml +0 -0
- {csu-2.4.2 → csu-2.5.0}/tests/cassettes/test_service/test_error.yaml +0 -0
- {csu-2.4.2 → csu-2.5.0}/tests/cassettes/test_service/test_logging.yaml +0 -0
- {csu-2.4.2 → csu-2.5.0}/tests/cassettes/test_service/test_redirects.yaml +0 -0
- {csu-2.4.2 → csu-2.5.0}/tests/cassettes/test_service_auth/test_async.yaml +0 -0
- {csu-2.4.2 → csu-2.5.0}/tests/cassettes/test_service_auth/test_async_auth.yaml +0 -0
- {csu-2.4.2 → csu-2.5.0}/tests/cassettes/test_service_auth/test_sync.yaml +0 -0
- {csu-2.4.2 → csu-2.5.0}/tests/cassettes/test_service_auth/test_sync_auth.yaml +0 -0
- {csu-2.4.2 → csu-2.5.0}/tests/conftest.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/tests/exampleworker.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/tests/test_exampleworker.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/tests/test_models.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/tests/test_service_auth.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/tests/test_views.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/tests/test_worker.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/tests/testproject/__init__.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/tests/testproject/fixtures/testuser.json +0 -0
- {csu-2.4.2 → csu-2.5.0}/tests/testproject/models.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/tests/testproject/urls.py +0 -0
- {csu-2.4.2 → csu-2.5.0}/tox.ini +0 -0
|
@@ -6,19 +6,19 @@ exclude: '^(\.tox|ci/templates|\.bumpversion\.cfg)(/|$)'
|
|
|
6
6
|
# Note the order is intentional to avoid multiple passes of the hooks
|
|
7
7
|
repos:
|
|
8
8
|
- repo: https://github.com/adamchainz/django-upgrade
|
|
9
|
-
rev: 1.
|
|
9
|
+
rev: 1.32.0
|
|
10
10
|
hooks:
|
|
11
11
|
- id: django-upgrade
|
|
12
12
|
args: [ --target-version, "5.2" ]
|
|
13
13
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
14
|
-
rev: v0.
|
|
14
|
+
rev: v0.16.6
|
|
15
15
|
hooks:
|
|
16
16
|
- id: ruff
|
|
17
17
|
# Using --unsafe-fixes can change code behavior
|
|
18
18
|
args: [--fix, --exit-non-zero-on-fix, --show-fixes, --unsafe-fixes]
|
|
19
19
|
- id: ruff-format
|
|
20
20
|
- repo: https://github.com/tombi-toml/tombi-pre-commit
|
|
21
|
-
rev: v1.1
|
|
21
|
+
rev: v1.5.1
|
|
22
22
|
hooks:
|
|
23
23
|
- id: tombi-format
|
|
24
24
|
# args: [ "--offline" ]
|
{csu-2.4.2 → csu-2.5.0}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: csu
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.5.0
|
|
4
4
|
Summary: Clean Slate Utils - bunch of utility code, mostly Django/DRF specific.
|
|
5
5
|
Author-email: Ionel Cristian Mărieș <contact@ionelmc.ro>
|
|
6
6
|
License-Expression: BSD-2-Clause
|
|
@@ -69,9 +69,9 @@ Overview
|
|
|
69
69
|
.. |supported-implementations| image:: https://img.shields.io/pypi/implementation/csu.svg
|
|
70
70
|
:alt: Supported implementations
|
|
71
71
|
:target: https://pypi.org/project/csu
|
|
72
|
-
.. |commits-since| image:: https://img.shields.io/github/commits-since/ionelmc/python-csu/v2.
|
|
72
|
+
.. |commits-since| image:: https://img.shields.io/github/commits-since/ionelmc/python-csu/v2.5.0.svg
|
|
73
73
|
:alt: Commits since latest release
|
|
74
|
-
:target: https://github.com/ionelmc/python-csu/compare/v2.
|
|
74
|
+
:target: https://github.com/ionelmc/python-csu/compare/v2.5.0...main
|
|
75
75
|
.. |scrutinizer| image:: https://img.shields.io/scrutinizer/quality/g/ionelmc/python-csu/main.svg
|
|
76
76
|
:alt: Scrutinizer Status
|
|
77
77
|
:target: https://scrutinizer-ci.com/g/ionelmc/python-csu/
|
|
@@ -34,9 +34,9 @@ Overview
|
|
|
34
34
|
.. |supported-implementations| image:: https://img.shields.io/pypi/implementation/csu.svg
|
|
35
35
|
:alt: Supported implementations
|
|
36
36
|
:target: https://pypi.org/project/csu
|
|
37
|
-
.. |commits-since| image:: https://img.shields.io/github/commits-since/ionelmc/python-csu/v2.
|
|
37
|
+
.. |commits-since| image:: https://img.shields.io/github/commits-since/ionelmc/python-csu/v2.5.0.svg
|
|
38
38
|
:alt: Commits since latest release
|
|
39
|
-
:target: https://github.com/ionelmc/python-csu/compare/v2.
|
|
39
|
+
:target: https://github.com/ionelmc/python-csu/compare/v2.5.0...main
|
|
40
40
|
.. |scrutinizer| image:: https://img.shields.io/scrutinizer/quality/g/ionelmc/python-csu/main.svg
|
|
41
41
|
:alt: Scrutinizer Status
|
|
42
42
|
:target: https://scrutinizer-ci.com/g/ionelmc/python-csu/
|
|
@@ -25,10 +25,12 @@ LOGGING_AUTH_INFO_FIELDS = getattr(settings, "CSU_LOGGING_AUTH_INFO_FIELDS", ("_
|
|
|
25
25
|
assert isinstance(LOGGING_AUTH_INFO_FIELDS, list | tuple), f"Expected CSU_LOGGING_AUTH_INFO_FIELDS={LOGGING_AUTH_INFO_FIELDS!r} to be a list or tuple."
|
|
26
26
|
LOGGING_TB_LIMIT = getattr(settings, "CSU_LOGGING_TB_LIMIT", 5)
|
|
27
27
|
LOGGING_REQUEST_BODY_LIMIT = getattr(settings, "CSU_LOGGING_REQUEST_BODY_LIMIT", 102400)
|
|
28
|
-
|
|
28
|
+
LOGGING_RESPONSE_TEXT_LIMIT = getattr(settings, "LOGGING_RESPONSE_TEXT_LIMIT", 102400)
|
|
29
|
+
LOGGING_RESPONSE_BINARY_LIMIT = getattr(settings, "LOGGING_RESPONSE_BINARY_LIMIT", 64)
|
|
29
30
|
LOGGING_SHOW_HEADERS = getattr(settings, "CSU_LOGGING_SHOW_HEADERS", False)
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
SERVICE_LOGGING_REQUEST_BODY_LIMIT = getattr(settings, "CSU_SERVICE_LOGGING_REQUEST_BODY_LIMIT", None)
|
|
33
|
+
SERVICE_LOGGING_REQUEST_SHOW_HEADERS = getattr(settings, "CSU_SERVICE_LOGGING_REQUEST_SHOW_HEADERS", False)
|
|
34
|
+
SERVICE_LOGGING_RESPONSE_TEXT_LIMIT = getattr(settings, "CSU_SERVICE_LOGGING_RESPONSE_TEXT_LIMIT", 102400)
|
|
35
|
+
SERVICE_LOGGING_RESPONSE_BINARY_LIMIT = getattr(settings, "CSU_SERVICE_LOGGING_RESPONSE_BINARY_LIMIT", 64)
|
|
36
|
+
SERVICE_LOGGING_RESPONSE_SHOW_HEADERS = getattr(settings, "CSU_SERVICE_LOGGING_RESPONSE_SHOW_HEADERS", False)
|
|
@@ -34,17 +34,12 @@ class OpaqueField(forms.MultiValueField, forms.FileField):
|
|
|
34
34
|
value_widget: type
|
|
35
35
|
value_field: type
|
|
36
36
|
|
|
37
|
-
def __init__(self,
|
|
38
|
-
if not (required is UNSPECIFIED or required):
|
|
39
|
-
raise TypeError("Cannot make this field not mandatory.")
|
|
37
|
+
def __init__(self, widget=UNSPECIFIED, **kwargs):
|
|
40
38
|
if widget is not UNSPECIFIED:
|
|
41
39
|
raise TypeError("Cannot override widget.")
|
|
42
|
-
if not (disabled is UNSPECIFIED or not disabled):
|
|
43
|
-
raise TypeError("Cannot disable this field.")
|
|
44
40
|
super().__init__(
|
|
45
41
|
fields=[forms.CharField(required=False), self.value_field(required=False)],
|
|
46
42
|
widget=OpaqueWidget(self.value_widget, self.display_value),
|
|
47
|
-
required=False,
|
|
48
43
|
require_all_fields=False,
|
|
49
44
|
**kwargs,
|
|
50
45
|
)
|
|
@@ -11,7 +11,8 @@ from rest_framework.request import Request
|
|
|
11
11
|
from rest_framework.response import Response
|
|
12
12
|
|
|
13
13
|
from .conf import LOGGING_REQUEST_BODY_LIMIT
|
|
14
|
-
from .conf import
|
|
14
|
+
from .conf import LOGGING_RESPONSE_BINARY_LIMIT
|
|
15
|
+
from .conf import LOGGING_RESPONSE_TEXT_LIMIT
|
|
15
16
|
from .conf import LOGGING_SHOW_HEADERS
|
|
16
17
|
from .consts import LINE_LENGTH
|
|
17
18
|
from .consts import REQUEST_DATA_LINE
|
|
@@ -24,6 +25,12 @@ from .consts import THICK_LINE
|
|
|
24
25
|
default_logger = getLogger("csu")
|
|
25
26
|
|
|
26
27
|
|
|
28
|
+
def is_text_content_type(content_type: str) -> bool:
|
|
29
|
+
return (
|
|
30
|
+
content_type.startswith("text/") or content_type.endswith(("json", "plain", "xml")) or any(part in content_type for part in ("json", "script", "xml"))
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
27
34
|
def get_remote_addresses(environ, placeholder=None):
|
|
28
35
|
remote_addr = [environ.get("REMOTE_ADDR", placeholder)]
|
|
29
36
|
forwarded_for = environ.get("HTTP_X_FORWARDED_FOR", "").split(",")
|
|
@@ -63,7 +70,7 @@ def get_request_line(environ, status_code, auth=None, *extra_auth):
|
|
|
63
70
|
return format, arguments
|
|
64
71
|
|
|
65
72
|
|
|
66
|
-
def fa_append_repr(format: list[str], arguments: list, value, limit:
|
|
73
|
+
def fa_append_repr(format: list[str], arguments: list, value, limit: int | None):
|
|
67
74
|
value = repr(value)
|
|
68
75
|
if limit and (size := len(value)) > limit:
|
|
69
76
|
format.append("%s\n ... %s more characters")
|
|
@@ -111,19 +118,30 @@ def get_content_lines(request: Request | HttpRequest | ASGIRequest, response: Re
|
|
|
111
118
|
"\n ".join(f"{name}: {value}" for name, value in request.headers.items()),
|
|
112
119
|
)
|
|
113
120
|
if response:
|
|
121
|
+
if response.headers:
|
|
122
|
+
format.append("\n%s\n %s")
|
|
123
|
+
arguments += (
|
|
124
|
+
" response headers ".center(LINE_LENGTH, "-"),
|
|
125
|
+
"\n ".join(f"{name}: {value}" for name, value in response.headers.items()),
|
|
126
|
+
)
|
|
127
|
+
content_type = response.headers.get("content-type")
|
|
128
|
+
else:
|
|
129
|
+
content_type = None
|
|
130
|
+
|
|
131
|
+
is_text = is_text_content_type(content_type or "text/")
|
|
114
132
|
try:
|
|
115
133
|
if getattr(response, "is_rendered", True) and response.content:
|
|
116
134
|
format.append("\n%s\n ")
|
|
117
135
|
arguments.append(RESPONSE_CONTENT_LINE)
|
|
118
|
-
fa_append_repr(format, arguments, response.content,
|
|
136
|
+
fa_append_repr(format, arguments, response.content, LOGGING_RESPONSE_TEXT_LIMIT if is_text else LOGGING_RESPONSE_BINARY_LIMIT)
|
|
119
137
|
elif hasattr(response, "data") and response.data is not None:
|
|
120
138
|
format.append("\n%s\n ")
|
|
121
139
|
arguments.append(RESPONSE_DATA_LINE)
|
|
122
|
-
fa_append_repr(format, arguments, response.data,
|
|
140
|
+
fa_append_repr(format, arguments, response.data, LOGGING_RESPONSE_TEXT_LIMIT if is_text else LOGGING_RESPONSE_BINARY_LIMIT)
|
|
123
141
|
else:
|
|
124
142
|
format.append("\n%s\n ")
|
|
125
143
|
arguments.append(RESPONSE_LINE)
|
|
126
|
-
fa_append_repr(format, arguments, response,
|
|
144
|
+
fa_append_repr(format, arguments, response, LOGGING_RESPONSE_TEXT_LIMIT if is_text else LOGGING_RESPONSE_BINARY_LIMIT)
|
|
127
145
|
except Exception as exc:
|
|
128
146
|
format.append("\n%s\n Failed to get response: %s")
|
|
129
147
|
arguments += (
|
|
@@ -19,10 +19,11 @@ from niquests.exceptions import ConnectionError
|
|
|
19
19
|
from niquests.typing import TLSClientCertType
|
|
20
20
|
from niquests.typing import TLSVerifyType
|
|
21
21
|
|
|
22
|
-
from .conf import
|
|
23
|
-
from .conf import
|
|
24
|
-
from .conf import
|
|
25
|
-
from .conf import
|
|
22
|
+
from .conf import SERVICE_LOGGING_REQUEST_BODY_LIMIT
|
|
23
|
+
from .conf import SERVICE_LOGGING_REQUEST_SHOW_HEADERS
|
|
24
|
+
from .conf import SERVICE_LOGGING_RESPONSE_BINARY_LIMIT
|
|
25
|
+
from .conf import SERVICE_LOGGING_RESPONSE_SHOW_HEADERS
|
|
26
|
+
from .conf import SERVICE_LOGGING_RESPONSE_TEXT_LIMIT
|
|
26
27
|
from .consts import LINE_LENGTH
|
|
27
28
|
from .consts import THICK_LINE
|
|
28
29
|
from .exceptions import DecodeError
|
|
@@ -33,13 +34,14 @@ from .exceptions import RetryableError
|
|
|
33
34
|
from .exceptions import RetryableStatusError
|
|
34
35
|
from .exceptions import UnexpectedStatusError
|
|
35
36
|
from .exceptions import get_event_id
|
|
37
|
+
from .logging import is_text_content_type
|
|
36
38
|
|
|
37
39
|
|
|
38
40
|
class HTTPServiceResponse:
|
|
39
41
|
status: int
|
|
40
42
|
http_response: Response | AsyncResponse
|
|
41
43
|
event_id: str
|
|
42
|
-
json:
|
|
44
|
+
json: list | dict | None = None
|
|
43
45
|
text: str
|
|
44
46
|
content: bytes
|
|
45
47
|
|
|
@@ -89,8 +91,11 @@ class HTTPServiceContext[RTYPE = HTTPServiceResponse]:
|
|
|
89
91
|
client_class = Session
|
|
90
92
|
client: Session
|
|
91
93
|
logger: Logger
|
|
92
|
-
|
|
93
|
-
|
|
94
|
+
log_request_body_limit = SERVICE_LOGGING_REQUEST_BODY_LIMIT
|
|
95
|
+
log_request_show_headers = SERVICE_LOGGING_REQUEST_SHOW_HEADERS
|
|
96
|
+
log_response_text_limit = SERVICE_LOGGING_RESPONSE_TEXT_LIMIT
|
|
97
|
+
log_response_binary_limit = SERVICE_LOGGING_RESPONSE_BINARY_LIMIT
|
|
98
|
+
log_response_show_headers = SERVICE_LOGGING_RESPONSE_SHOW_HEADERS
|
|
94
99
|
|
|
95
100
|
def __init__(self, service: HTTPService[Self], event_id=None, auth=None, proxy=None, **kwargs):
|
|
96
101
|
if auth is None:
|
|
@@ -123,14 +128,14 @@ class HTTPServiceContext[RTYPE = HTTPServiceResponse]:
|
|
|
123
128
|
self.handle_log_request(request)
|
|
124
129
|
|
|
125
130
|
def handle_log_request(self, request: PreparedRequest):
|
|
126
|
-
if
|
|
131
|
+
if self.log_request_show_headers:
|
|
127
132
|
header = " request headers ".center(LINE_LENGTH, "-"), "\n ".join(f"{k}: {v!r}" for k, v in sorted(request.headers.items()))
|
|
128
133
|
else:
|
|
129
134
|
header = (request.headers.get("authorization", ""),)
|
|
130
135
|
|
|
131
136
|
if request.body:
|
|
132
137
|
size = len(request.body)
|
|
133
|
-
limit = self.
|
|
138
|
+
limit = self.log_request_body_limit
|
|
134
139
|
if limit and size > limit:
|
|
135
140
|
content = f"{request.body!r:.{limit}}\n ... {size - limit} more bytes"
|
|
136
141
|
else:
|
|
@@ -142,12 +147,12 @@ class HTTPServiceContext[RTYPE = HTTPServiceResponse]:
|
|
|
142
147
|
content = request_line = None
|
|
143
148
|
|
|
144
149
|
if content is None:
|
|
145
|
-
if
|
|
150
|
+
if self.log_request_show_headers:
|
|
146
151
|
self.logger.info("[%s] %s %s\n%s\n %s", self.short_id, request.method, request.url, *header)
|
|
147
152
|
else:
|
|
148
153
|
self.logger.info("[%s] %s %s +[%s]", self.short_id, request.method, request.url, *header)
|
|
149
154
|
else:
|
|
150
|
-
if
|
|
155
|
+
if self.log_request_show_headers:
|
|
151
156
|
self.logger.info(
|
|
152
157
|
"[%s] %s %s\n%s\n %s\n%s\n %s\n%s",
|
|
153
158
|
self.short_id,
|
|
@@ -176,14 +181,15 @@ class HTTPServiceContext[RTYPE = HTTPServiceResponse]:
|
|
|
176
181
|
def handle_log_response(self, response: Response | AsyncResponse, content):
|
|
177
182
|
size = len(content) if content else 0
|
|
178
183
|
content_type = response.headers.get("content-type")
|
|
184
|
+
is_text = is_text_content_type(content_type or "text/")
|
|
179
185
|
content_type = "no content-type" if content_type is None else repr(content_type)
|
|
180
186
|
response_line = f" response body ({content_type} - {size} bytes) ".center(LINE_LENGTH, "-")
|
|
181
|
-
limit = self.
|
|
187
|
+
limit = self.log_response_text_limit if is_text else self.log_response_binary_limit
|
|
182
188
|
if limit and size > limit:
|
|
183
189
|
content = f"{content!r:.{limit}}\n ... {size - limit} more bytes"
|
|
184
190
|
else:
|
|
185
191
|
content = f"{content!r}"
|
|
186
|
-
if
|
|
192
|
+
if self.log_response_show_headers:
|
|
187
193
|
headers_line = " response headers ".center(LINE_LENGTH, "-")
|
|
188
194
|
headers = "\n ".join(f"{k}: {v!r}" for k, v in sorted(response.headers.items()))
|
|
189
195
|
self.logger.info(
|
|
@@ -91,13 +91,13 @@ def replace_ns(value: str, replacement: tuple[str, str]) -> str:
|
|
|
91
91
|
class XML:
|
|
92
92
|
element: Element
|
|
93
93
|
|
|
94
|
-
def __init__(self, element, namespaces:
|
|
94
|
+
def __init__(self, element, namespaces: dict | None = None):
|
|
95
95
|
assert isinstance(element, Element), "Expected an Element instance. Perhaps you wanted to use XML.fromstring?"
|
|
96
96
|
self.element = element
|
|
97
97
|
self.namespaces = namespaces or {}
|
|
98
98
|
|
|
99
99
|
@classmethod
|
|
100
|
-
def fromstring(cls, xml: str, namespaces:
|
|
100
|
+
def fromstring(cls, xml: str, namespaces: dict | None = None) -> Self:
|
|
101
101
|
try:
|
|
102
102
|
return cls(
|
|
103
103
|
fromstring(xml, forbid_dtd=True, forbid_entities=True, forbid_external=True),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: csu
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.5.0
|
|
4
4
|
Summary: Clean Slate Utils - bunch of utility code, mostly Django/DRF specific.
|
|
5
5
|
Author-email: Ionel Cristian Mărieș <contact@ionelmc.ro>
|
|
6
6
|
License-Expression: BSD-2-Clause
|
|
@@ -69,9 +69,9 @@ Overview
|
|
|
69
69
|
.. |supported-implementations| image:: https://img.shields.io/pypi/implementation/csu.svg
|
|
70
70
|
:alt: Supported implementations
|
|
71
71
|
:target: https://pypi.org/project/csu
|
|
72
|
-
.. |commits-since| image:: https://img.shields.io/github/commits-since/ionelmc/python-csu/v2.
|
|
72
|
+
.. |commits-since| image:: https://img.shields.io/github/commits-since/ionelmc/python-csu/v2.5.0.svg
|
|
73
73
|
:alt: Commits since latest release
|
|
74
|
-
:target: https://github.com/ionelmc/python-csu/compare/v2.
|
|
74
|
+
:target: https://github.com/ionelmc/python-csu/compare/v2.5.0...main
|
|
75
75
|
.. |scrutinizer| image:: https://img.shields.io/scrutinizer/quality/g/ionelmc/python-csu/main.svg
|
|
76
76
|
:alt: Scrutinizer Status
|
|
77
77
|
:target: https://scrutinizer-ci.com/g/ionelmc/python-csu/
|
|
@@ -260,7 +260,7 @@ json.decoder.JSONDecodeError: Expecting value: line 2 column 5 (char 5)
|
|
|
260
260
|
During handling of the above exception, another exception occurred:
|
|
261
261
|
|
|
262
262
|
Traceback (most recent call last):
|
|
263
|
-
File "[&SERVICE_PATH]", line
|
|
263
|
+
File "[&SERVICE_PATH]", line 236, in handle_process_response
|
|
264
264
|
json = response.json(parse_float=Decimal)
|
|
265
265
|
File "[&MODELS_PATH]", line 1529, in json
|
|
266
266
|
raise RequestsJSONDecodeError(e.msg, e.doc, e.pos)
|
|
@@ -275,10 +275,10 @@ Traceback (most recent call last):
|
|
|
275
275
|
File "[&TEST_PATH]", line 78, in json
|
|
276
276
|
return ctx.request("GET", "status/418", accept_statuses=[418]).json
|
|
277
277
|
~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
278
|
-
File "[&SERVICE_PATH]", line
|
|
278
|
+
File "[&SERVICE_PATH]", line 314, in request
|
|
279
279
|
return self.handle_process_response(response, expect_json=expect_json)
|
|
280
280
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
281
|
-
File "[&SERVICE_PATH]", line
|
|
281
|
+
File "[&SERVICE_PATH]", line 238, in handle_process_response
|
|
282
282
|
raise DecodeError(response, exc, event_id=self.event_id) from exc
|
|
283
283
|
csu.exceptions.DecodeError: DecodeError(JSONDecodeError('Expecting value: line 2 column 5 (char 5)'), response=<Response Dummy [418]>)
|
|
284
284
|
(418, b'\\n -=[ teapot ]=-\\n\\n _...._\\n .\\' _ _ `.\\n | ."` ^ `". _,\\n \\\\_;`"---"`|//\\n | ;/\\n \\\\_ _/\\n `"""`\\n')
|
|
@@ -340,7 +340,7 @@ Traceback (most recent call last):
|
|
|
340
340
|
File "[&TEST_PATH]", line 47, in error
|
|
341
341
|
return ctx.request("GET", "status/599", expect_json=False)
|
|
342
342
|
~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
343
|
-
File "[&SERVICE_PATH]", line
|
|
343
|
+
File "[&SERVICE_PATH]", line 313, in request
|
|
344
344
|
raise UnexpectedStatusError(response, accept_statuses, event_id=self.event_id)
|
|
345
345
|
csu.exceptions.UnexpectedStatusError: UnexpectedStatusError(<Response Dummy [599]>, accept_statuses=[200])
|
|
346
346
|
(599, b'')
|
|
@@ -540,7 +540,7 @@ INFO | [01:000000.00] POST [&HTTPBIN]/anything?foo=bar&accept_statuses=%7B999
|
|
|
540
540
|
"""\
|
|
541
541
|
ERROR | [01:000000.00] POST [&HTTPBIN]/anything?foo=bar&accept_statuses=%7B999%7D&expect_json=true&follow_redirects=false&retries_left=3&retry_count=0&retry_statuses=%7B200%7D !> RetryableStatusError('200 not in [999] but in [200]', 200, b'{"args":{"accept_statuses":"{999}","expect_json":"true","follow_redirects":"false","foo":"bar","retries_left":"3","retry_count":"0","retry_statuses":"{200}"},"data":"config={\\'custom\\': \\'config\\'}","files":{},"form":{},"headers":{"Accept":"*/*","Accept-Encoding":"gzip, deflate, br","Connection":"keep-alive","Content-Length":"27","Host":"127.0.0.1:12345","User-Agent":"python-httpx/0.X.X"},"json":null,"method":"POST","origin":"127.0.0.1","url":"http://127.0.0.1:12345/anything?foo=bar&accept_statuses={999}&expect_json=true&follow_redirects=false&retries_left=3&retry_count=0&retry_statuses={200}"}\\n', event_id=241212:01:000000.00) (will retry 3 more times)
|
|
542
542
|
Traceback (most recent call last):
|
|
543
|
-
File "[&SERVICE_PATH]", line
|
|
543
|
+
File "[&SERVICE_PATH]", line 311, in request
|
|
544
544
|
raise RetryableStatusError(response, accept_statuses, retry_statuses, event_id=self.event_id)
|
|
545
545
|
csu.exceptions.RetryableStatusError: RetryableStatusError(<Response Dummy [200]>, accept_statuses=[999], retry_statuses=[200])
|
|
546
546
|
(200, b'{"args":{"accept_statuses":"{999}","expect_json":"true","follow_redirects":"false","foo":"bar","retries_left":"3","retry_count":"0","retry_statuses":"{200}"},"data":"config={\\'custom\\': \\'config\\'}","files":{},"form":{},"headers":{"Accept":"*/*","Accept-Encoding":"gzip, deflate, br","Connection":"keep-alive","Content-Length":"27","Host":"127.0.0.1:12345","User-Agent":"python-httpx/0.X.X"},"json":null,"method":"POST","origin":"127.0.0.1","url":"http://127.0.0.1:12345/anything?foo=bar&accept_statuses={999}&expect_json=true&follow_redirects=false&retries_left=3&retry_count=0&retry_statuses={200}"}\\n')
|
|
@@ -574,7 +574,7 @@ INFO | [01:000000.00] POST [&HTTPBIN]/anything?foo=bar&accept_statuses=%7B999
|
|
|
574
574
|
"""\
|
|
575
575
|
ERROR | [01:000000.00] POST [&HTTPBIN]/anything?foo=bar&accept_statuses=%7B999%7D&expect_json=true&follow_redirects=false&retries_left=2&retry_count=1&retry_statuses=%7B200%7D !> RetryableStatusError('200 not in [999] but in [200]', 200, b'{"args":{"accept_statuses":"{999}","expect_json":"true","follow_redirects":"false","foo":"bar","retries_left":"2","retry_count":"1","retry_statuses":"{200}"},"data":"config={\\'custom\\': \\'config\\'}","files":{},"form":{},"headers":{"Accept":"*/*","Accept-Encoding":"gzip, deflate, br","Connection":"keep-alive","Content-Length":"27","Host":"127.0.0.1:12345","User-Agent":"python-httpx/0.X.X"},"json":null,"method":"POST","origin":"127.0.0.1","url":"http://127.0.0.1:12345/anything?foo=bar&accept_statuses={999}&expect_json=true&follow_redirects=false&retries_left=2&retry_count=1&retry_statuses={200}"}\\n', event_id=241212:01:000000.00) (will retry 2 more times)
|
|
576
576
|
Traceback (most recent call last):
|
|
577
|
-
File "[&SERVICE_PATH]", line
|
|
577
|
+
File "[&SERVICE_PATH]", line 311, in request
|
|
578
578
|
raise RetryableStatusError(response, accept_statuses, retry_statuses, event_id=self.event_id)
|
|
579
579
|
csu.exceptions.RetryableStatusError: RetryableStatusError(<Response Dummy [200]>, accept_statuses=[999], retry_statuses=[200])
|
|
580
580
|
(200, b'{"args":{"accept_statuses":"{999}","expect_json":"true","follow_redirects":"false","foo":"bar","retries_left":"2","retry_count":"1","retry_statuses":"{200}"},"data":"config={\\'custom\\': \\'config\\'}","files":{},"form":{},"headers":{"Accept":"*/*","Accept-Encoding":"gzip, deflate, br","Connection":"keep-alive","Content-Length":"27","Host":"127.0.0.1:12345","User-Agent":"python-httpx/0.X.X"},"json":null,"method":"POST","origin":"127.0.0.1","url":"http://127.0.0.1:12345/anything?foo=bar&accept_statuses={999}&expect_json=true&follow_redirects=false&retries_left=2&retry_count=1&retry_statuses={200}"}\\n')
|
|
@@ -608,7 +608,7 @@ INFO | [01:000000.00] POST [&HTTPBIN]/anything?foo=bar&accept_statuses=%7B999
|
|
|
608
608
|
"""\
|
|
609
609
|
ERROR | [01:000000.00] POST [&HTTPBIN]/anything?foo=bar&accept_statuses=%7B999%7D&expect_json=true&follow_redirects=false&retries_left=1&retry_count=2&retry_statuses=%7B200%7D !> RetryableStatusError('200 not in [999] but in [200]', 200, b'{"args":{"accept_statuses":"{999}","expect_json":"true","follow_redirects":"false","foo":"bar","retries_left":"1","retry_count":"2","retry_statuses":"{200}"},"data":"config={\\'custom\\': \\'config\\'}","files":{},"form":{},"headers":{"Accept":"*/*","Accept-Encoding":"gzip, deflate, br","Connection":"keep-alive","Content-Length":"27","Host":"127.0.0.1:12345","User-Agent":"python-httpx/0.X.X"},"json":null,"method":"POST","origin":"127.0.0.1","url":"http://127.0.0.1:12345/anything?foo=bar&accept_statuses={999}&expect_json=true&follow_redirects=false&retries_left=1&retry_count=2&retry_statuses={200}"}\\n', event_id=241212:01:000000.00) (will retry 1 more times)
|
|
610
610
|
Traceback (most recent call last):
|
|
611
|
-
File "[&SERVICE_PATH]", line
|
|
611
|
+
File "[&SERVICE_PATH]", line 311, in request
|
|
612
612
|
raise RetryableStatusError(response, accept_statuses, retry_statuses, event_id=self.event_id)
|
|
613
613
|
csu.exceptions.RetryableStatusError: RetryableStatusError(<Response Dummy [200]>, accept_statuses=[999], retry_statuses=[200])
|
|
614
614
|
(200, b'{"args":{"accept_statuses":"{999}","expect_json":"true","follow_redirects":"false","foo":"bar","retries_left":"1","retry_count":"2","retry_statuses":"{200}"},"data":"config={\\'custom\\': \\'config\\'}","files":{},"form":{},"headers":{"Accept":"*/*","Accept-Encoding":"gzip, deflate, br","Connection":"keep-alive","Content-Length":"27","Host":"127.0.0.1:12345","User-Agent":"python-httpx/0.X.X"},"json":null,"method":"POST","origin":"127.0.0.1","url":"http://127.0.0.1:12345/anything?foo=bar&accept_statuses={999}&expect_json=true&follow_redirects=false&retries_left=1&retry_count=2&retry_statuses={200}"}\\n')
|
|
@@ -656,31 +656,31 @@ ERROR | (renderer: NoneType)
|
|
|
656
656
|
| ...<6 lines>...
|
|
657
657
|
| accept_statuses=[999],
|
|
658
658
|
| )
|
|
659
|
-
| File "[&SERVICE_PATH]", line
|
|
659
|
+
| File "[&SERVICE_PATH]", line 325, in request
|
|
660
660
|
| raise ExhaustedRetriesError(retry_budget, retry_failures, event_id=self.event_id)
|
|
661
661
|
| csu.exceptions.ExhaustedRetriesError: ExhaustedRetriesError(3)
|
|
662
662
|
| ([RetryableStatusError('200 not in [999] but in [200]', 200, b'{"args":{"accept_statuses":"{999}","expect_json":"true","follow_redirects":"false","foo":"bar","retries_left":"3","retry_count":"0","retry_statuses":"{200}"},"data":"config={\\'custom\\': \\'config\\'}","files":{},"form":{},"headers":{"Accept":"*/*","Accept-Encoding":"gzip, deflate, br","Connection":"keep-alive","Content-Length":"27","Host":"127.0.0.1:12345","User-Agent":"python-httpx/0.X.X"},"json":null,"method":"POST","origin":"127.0.0.1","url":"http://127.0.0.1:12345/anything?foo=bar&accept_statuses={999}&expect_json=true&follow_redirects=false&retries_left=3&retry_count=0&retry_statuses={200}"}\\n', event_id=241212:01:000000.00), RetryableStatusError('200 not in [999] but in [200]', 200, b'{"args":{"accept_statuses":"{999}","expect_json":"true","follow_redirects":"false","foo":"bar","retries_left":"2","retry_count":"1","retry_statuses":"{200}"},"data":"config={\\'custom\\': \\'config\\'}","files":{},"form":{},"headers":{"Accept":"*/*","Accept-Encoding":"gzip, deflate, br","Connection":"keep-alive","Content-Length":"27","Host":"127.0.0.1:12345","User-Agent":"python-httpx/0.X.X"},"json":null,"method":"POST","origin":"127.0.0.1","url":"http://127.0.0.1:12345/anything?foo=bar&accept_statuses={999}&expect_json=true&follow_redirects=false&retries_left=2&retry_count=1&retry_statuses={200}"}\\n', event_id=241212:01:000000.00), RetryableStatusError('200 not in [999] but in [200]', 200, b'{"args":{"accept_statuses":"{999}","expect_json":"true","follow_redirects":"false","foo":"bar","retries_left":"1","retry_count":"2","retry_statuses":"{200}"},"data":"config={\\'custom\\': \\'config\\'}","files":{},"form":{},"headers":{"Accept":"*/*","Accept-Encoding":"gzip, deflate, br","Connection":"keep-alive","Content-Length":"27","Host":"127.0.0.1:12345","User-Agent":"python-httpx/0.X.X"},"json":null,"method":"POST","origin":"127.0.0.1","url":"http://127.0.0.1:12345/anything?foo=bar&accept_statuses={999}&expect_json=true&follow_redirects=false&retries_left=1&retry_count=2&retry_statuses={200}"}\\n', event_id=241212:01:000000.00), RetryableStatusError('200 not in [999] but in [200]', 200, b'{"args":{"accept_statuses":"{999}","expect_json":"true","follow_redirects":"false","foo":"bar","retries_left":"0","retry_count":"3","retry_statuses":"{200}"},"data":"config={\\'custom\\': \\'config\\'}","files":{},"form":{},"headers":{"Accept":"*/*","Accept-Encoding":"gzip, deflate, br","Connection":"keep-alive","Content-Length":"27","Host":"127.0.0.1:12345","User-Agent":"python-httpx/0.X.X"},"json":null,"method":"POST","origin":"127.0.0.1","url":"http://127.0.0.1:12345/anything?foo=bar&accept_statuses={999}&expect_json=true&follow_redirects=false&retries_left=0&retry_count=3&retry_statuses={200}"}\\n', event_id=241212:01:000000.00)],)
|
|
663
663
|
+-+---------------- 1 ----------------
|
|
664
664
|
| Traceback (most recent call last):
|
|
665
|
-
| File "[&SERVICE_PATH]", line
|
|
665
|
+
| File "[&SERVICE_PATH]", line 311, in request
|
|
666
666
|
| raise RetryableStatusError(response, accept_statuses, retry_statuses, event_id=self.event_id)
|
|
667
667
|
| csu.exceptions.RetryableStatusError: RetryableStatusError(<Response Dummy [200]>, accept_statuses=[999], retry_statuses=[200])
|
|
668
668
|
| (200, b'{"args":{"accept_statuses":"{999}","expect_json":"true","follow_redirects":"false","foo":"bar","retries_left":"3","retry_count":"0","retry_statuses":"{200}"},"data":"config={\\'custom\\': \\'config\\'}","files":{},"form":{},"headers":{"Accept":"*/*","Accept-Encoding":"gzip, deflate, br","Connection":"keep-alive","Content-Length":"27","Host":"127.0.0.1:12345","User-Agent":"python-httpx/0.X.X"},"json":null,"method":"POST","origin":"127.0.0.1","url":"http://127.0.0.1:12345/anything?foo=bar&accept_statuses={999}&expect_json=true&follow_redirects=false&retries_left=3&retry_count=0&retry_statuses={200}"}\\n')
|
|
669
669
|
+---------------- 2 ----------------
|
|
670
670
|
| Traceback (most recent call last):
|
|
671
|
-
| File "[&SERVICE_PATH]", line
|
|
671
|
+
| File "[&SERVICE_PATH]", line 311, in request
|
|
672
672
|
| raise RetryableStatusError(response, accept_statuses, retry_statuses, event_id=self.event_id)
|
|
673
673
|
| csu.exceptions.RetryableStatusError: RetryableStatusError(<Response Dummy [200]>, accept_statuses=[999], retry_statuses=[200])
|
|
674
674
|
| (200, b'{"args":{"accept_statuses":"{999}","expect_json":"true","follow_redirects":"false","foo":"bar","retries_left":"2","retry_count":"1","retry_statuses":"{200}"},"data":"config={\\'custom\\': \\'config\\'}","files":{},"form":{},"headers":{"Accept":"*/*","Accept-Encoding":"gzip, deflate, br","Connection":"keep-alive","Content-Length":"27","Host":"127.0.0.1:12345","User-Agent":"python-httpx/0.X.X"},"json":null,"method":"POST","origin":"127.0.0.1","url":"http://127.0.0.1:12345/anything?foo=bar&accept_statuses={999}&expect_json=true&follow_redirects=false&retries_left=2&retry_count=1&retry_statuses={200}"}\\n')
|
|
675
675
|
+---------------- 3 ----------------
|
|
676
676
|
| Traceback (most recent call last):
|
|
677
|
-
| File "[&SERVICE_PATH]", line
|
|
677
|
+
| File "[&SERVICE_PATH]", line 311, in request
|
|
678
678
|
| raise RetryableStatusError(response, accept_statuses, retry_statuses, event_id=self.event_id)
|
|
679
679
|
| csu.exceptions.RetryableStatusError: RetryableStatusError(<Response Dummy [200]>, accept_statuses=[999], retry_statuses=[200])
|
|
680
680
|
| (200, b'{"args":{"accept_statuses":"{999}","expect_json":"true","follow_redirects":"false","foo":"bar","retries_left":"1","retry_count":"2","retry_statuses":"{200}"},"data":"config={\\'custom\\': \\'config\\'}","files":{},"form":{},"headers":{"Accept":"*/*","Accept-Encoding":"gzip, deflate, br","Connection":"keep-alive","Content-Length":"27","Host":"127.0.0.1:12345","User-Agent":"python-httpx/0.X.X"},"json":null,"method":"POST","origin":"127.0.0.1","url":"http://127.0.0.1:12345/anything?foo=bar&accept_statuses={999}&expect_json=true&follow_redirects=false&retries_left=1&retry_count=2&retry_statuses={200}"}\\n')
|
|
681
681
|
+---------------- 4 ----------------
|
|
682
682
|
| Traceback (most recent call last):
|
|
683
|
-
| File "[&SERVICE_PATH]", line
|
|
683
|
+
| File "[&SERVICE_PATH]", line 311, in request
|
|
684
684
|
| raise RetryableStatusError(response, accept_statuses, retry_statuses, event_id=self.event_id)
|
|
685
685
|
| csu.exceptions.RetryableStatusError: RetryableStatusError(<Response Dummy [200]>, accept_statuses=[999], retry_statuses=[200])
|
|
686
686
|
| (200, b'{"args":{"accept_statuses":"{999}","expect_json":"true","follow_redirects":"false","foo":"bar","retries_left":"0","retry_count":"3","retry_statuses":"{200}"},"data":"config={\\'custom\\': \\'config\\'}","files":{},"form":{},"headers":{"Accept":"*/*","Accept-Encoding":"gzip, deflate, br","Connection":"keep-alive","Content-Length":"27","Host":"127.0.0.1:12345","User-Agent":"python-httpx/0.X.X"},"json":null,"method":"POST","origin":"127.0.0.1","url":"http://127.0.0.1:12345/anything?foo=bar&accept_statuses={999}&expect_json=true&follow_redirects=false&retries_left=0&retry_count=3&retry_statuses={200}"}\\n')
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
CSU_LOGGING_SHOW_HEADERS = True
|
|
2
|
+
CSU_SERVICE_LOGGING_REQUEST_SHOW_HEADERS = True
|
|
3
|
+
CSU_SERVICE_LOGGING_RESPONSE_SHOW_HEADERS = True
|
|
3
4
|
ALLOWED_HOSTS = ["localhost", "127.0.0.1"]
|
|
4
5
|
DATABASES = {
|
|
5
6
|
"default": {
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{csu-2.4.2 → csu-2.5.0}/LICENSE
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{csu-2.4.2 → csu-2.5.0}/tox.ini
RENAMED
|
File without changes
|