c2cwsgiutils 6.0.10.dev11__py3-none-any.whl → 6.1.0__py3-none-any.whl
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.
- c2cwsgiutils/__init__.py +14 -11
- c2cwsgiutils/acceptance/__init__.py +2 -3
- c2cwsgiutils/acceptance/connection.py +1 -2
- c2cwsgiutils/acceptance/image.py +9 -17
- c2cwsgiutils/acceptance/package-lock.json +270 -1062
- c2cwsgiutils/acceptance/package.json +2 -2
- c2cwsgiutils/acceptance/print.py +7 -3
- c2cwsgiutils/acceptance/utils.py +1 -3
- c2cwsgiutils/auth.py +43 -37
- c2cwsgiutils/broadcast/__init__.py +16 -16
- c2cwsgiutils/broadcast/interface.py +3 -3
- c2cwsgiutils/broadcast/local.py +1 -0
- c2cwsgiutils/broadcast/redis.py +13 -12
- c2cwsgiutils/client_info.py +13 -5
- c2cwsgiutils/config_utils.py +1 -0
- c2cwsgiutils/coverage_setup.py +4 -3
- c2cwsgiutils/db.py +36 -41
- c2cwsgiutils/db_maintenance_view.py +13 -13
- c2cwsgiutils/debug/__init__.py +2 -2
- c2cwsgiutils/debug/_listeners.py +1 -1
- c2cwsgiutils/debug/_views.py +7 -6
- c2cwsgiutils/debug/utils.py +9 -9
- c2cwsgiutils/errors.py +13 -14
- c2cwsgiutils/health_check.py +25 -30
- c2cwsgiutils/index.py +14 -16
- c2cwsgiutils/loader.py +1 -1
- c2cwsgiutils/logging_view.py +12 -12
- c2cwsgiutils/models_graph.py +0 -1
- c2cwsgiutils/pretty_json.py +0 -1
- c2cwsgiutils/prometheus.py +1 -7
- c2cwsgiutils/pyramid.py +0 -1
- c2cwsgiutils/pyramid_logging.py +2 -1
- c2cwsgiutils/redis_stats.py +9 -9
- c2cwsgiutils/redis_utils.py +19 -18
- c2cwsgiutils/request_tracking/__init__.py +14 -13
- c2cwsgiutils/request_tracking/_sql.py +0 -1
- c2cwsgiutils/scripts/genversion.py +5 -5
- c2cwsgiutils/scripts/stats_db.py +19 -17
- c2cwsgiutils/scripts/test_print.py +5 -5
- c2cwsgiutils/sentry.py +55 -20
- c2cwsgiutils/services.py +2 -2
- c2cwsgiutils/setup_process.py +0 -2
- c2cwsgiutils/sql_profiler/__init__.py +6 -6
- c2cwsgiutils/sql_profiler/_impl.py +19 -17
- c2cwsgiutils/sqlalchemylogger/README.md +30 -13
- c2cwsgiutils/sqlalchemylogger/handlers.py +12 -11
- c2cwsgiutils/stats_pyramid/__init__.py +1 -5
- c2cwsgiutils/stats_pyramid/_db_spy.py +2 -2
- c2cwsgiutils/stats_pyramid/_pyramid_spy.py +0 -1
- c2cwsgiutils/version.py +11 -5
- {c2cwsgiutils-6.0.10.dev11.dist-info → c2cwsgiutils-6.1.0.dist-info}/LICENSE +1 -1
- {c2cwsgiutils-6.0.10.dev11.dist-info → c2cwsgiutils-6.1.0.dist-info}/METADATA +12 -12
- c2cwsgiutils-6.1.0.dist-info/RECORD +67 -0
- {c2cwsgiutils-6.0.10.dev11.dist-info → c2cwsgiutils-6.1.0.dist-info}/WHEEL +1 -1
- c2cwsgiutils-6.0.10.dev11.dist-info/RECORD +0 -67
- {c2cwsgiutils-6.0.10.dev11.dist-info → c2cwsgiutils-6.1.0.dist-info}/entry_points.txt +0 -0
c2cwsgiutils/__init__.py
CHANGED
@@ -1,12 +1,12 @@
|
|
1
|
+
import ast
|
1
2
|
import configparser
|
2
3
|
import logging
|
3
4
|
import os
|
4
|
-
import re
|
5
5
|
import sys
|
6
6
|
from configparser import SectionProxy
|
7
7
|
from typing import Any
|
8
8
|
|
9
|
-
|
9
|
+
_LOG = logging.getLogger(__name__)
|
10
10
|
|
11
11
|
|
12
12
|
def get_config_defaults() -> dict[str, str]:
|
@@ -16,13 +16,13 @@ def get_config_defaults() -> dict[str, str]:
|
|
16
16
|
configparser does not support duplicated defaults with different cases, this function filter
|
17
17
|
the second one to avoid the issue.
|
18
18
|
|
19
|
-
configparser
|
19
|
+
configparser interpret the % then we need to escape them
|
20
20
|
"""
|
21
21
|
result: dict[str, str] = {}
|
22
22
|
lowercase_keys: set[str] = set()
|
23
23
|
for key, value in os.environ.items():
|
24
24
|
if key.lower() in lowercase_keys:
|
25
|
-
|
25
|
+
_LOG.warning("The environment variable '%s' is duplicated with different case, ignoring", key)
|
26
26
|
continue
|
27
27
|
lowercase_keys.add(key.lower())
|
28
28
|
result[key] = value.replace("%", "%%")
|
@@ -32,23 +32,26 @@ def get_config_defaults() -> dict[str, str]:
|
|
32
32
|
def _create_handlers(config: configparser.ConfigParser) -> dict[str, Any]:
|
33
33
|
handlers = [k.strip() for k in config["handlers"]["keys"].split(",")]
|
34
34
|
d_handlers: dict[str, Any] = {}
|
35
|
-
stream_re = re.compile(r"\((.*?),\)")
|
36
35
|
for hh in handlers:
|
37
36
|
block = config[f"handler_{hh}"]
|
38
|
-
|
39
|
-
|
40
|
-
raise Exception(f"Could not parse args of handler {hh}") # pylint: disable=broad-exception-raised
|
41
|
-
args = stream_match.groups()[0]
|
37
|
+
if "args" in block:
|
38
|
+
raise ValueError(f"Can not parse args of handlers {hh}, use kwargs instead.")
|
42
39
|
c = block["class"]
|
43
40
|
if "." not in c:
|
44
41
|
# classes like StreamHandler does not need the prefix in the ini so we add it here
|
45
42
|
c = f"logging.{c}"
|
46
43
|
conf = {
|
47
44
|
"class": c,
|
48
|
-
"stream": f"ext://{args}", # like ext://sys.stdout
|
49
45
|
}
|
46
|
+
if "level" in block:
|
47
|
+
conf["level"] = block["level"]
|
50
48
|
if "formatter" in block:
|
51
49
|
conf["formatter"] = block["formatter"]
|
50
|
+
if "filters" in block:
|
51
|
+
conf["filters"] = block["filters"]
|
52
|
+
if "kwargs" in block:
|
53
|
+
kwargs = ast.literal_eval(block["kwargs"])
|
54
|
+
conf.update(kwargs)
|
52
55
|
d_handlers[hh] = conf
|
53
56
|
return d_handlers
|
54
57
|
|
@@ -57,7 +60,7 @@ def _filter_logger(block: SectionProxy) -> dict[str, Any]:
|
|
57
60
|
out: dict[str, Any] = {"level": block["level"]}
|
58
61
|
handlers = block.get("handlers", "")
|
59
62
|
if handlers != "":
|
60
|
-
out["handlers"] = [block["handlers"]]
|
63
|
+
out["handlers"] = [k.strip() for k in block["handlers"].split(",")]
|
61
64
|
return out
|
62
65
|
|
63
66
|
|
@@ -3,7 +3,7 @@ import time
|
|
3
3
|
import typing
|
4
4
|
from functools import wraps
|
5
5
|
|
6
|
-
|
6
|
+
_LOG = logging.getLogger(__name__)
|
7
7
|
|
8
8
|
|
9
9
|
def retry(
|
@@ -16,7 +16,6 @@ def retry(
|
|
16
16
|
original from: http://wiki.python.org/moin/PythonDecoratorLibrary#Retry
|
17
17
|
|
18
18
|
Arguments:
|
19
|
-
|
20
19
|
exception_to_check: the exception to check. may be a tuple of exceptions to check
|
21
20
|
tries: number of times to try (not retry) before giving up
|
22
21
|
delay: initial delay between retries in seconds
|
@@ -32,7 +31,7 @@ def retry(
|
|
32
31
|
return f(*args, **kwargs)
|
33
32
|
except exception_to_check as e:
|
34
33
|
msg = f"{e:s}, Retrying in {mdelay:d} seconds..."
|
35
|
-
|
34
|
+
_LOG.warning(msg)
|
36
35
|
time.sleep(mdelay)
|
37
36
|
mtries -= 1
|
38
37
|
mdelay *= backoff
|
@@ -82,8 +82,7 @@ class Connection:
|
|
82
82
|
**kwargs: Any,
|
83
83
|
) -> Any:
|
84
84
|
"""Get the given URL (relative to the root of API)."""
|
85
|
-
|
86
|
-
from lxml import etree # nosec
|
85
|
+
from lxml import etree # nosec # pylint: disable=import-outside-toplevel
|
87
86
|
|
88
87
|
with self.session.get(
|
89
88
|
self.base_url + url,
|
c2cwsgiutils/acceptance/image.py
CHANGED
@@ -3,11 +3,11 @@ import os
|
|
3
3
|
import subprocess # nosec
|
4
4
|
from typing import TYPE_CHECKING, Any, Optional
|
5
5
|
|
6
|
-
import numpy as np
|
7
|
-
import skimage.color
|
8
|
-
import skimage.io
|
9
|
-
import skimage.metrics
|
10
|
-
import skimage.transform
|
6
|
+
import numpy as np # pylint: disable=import-error
|
7
|
+
import skimage.color # pylint: disable=import-error
|
8
|
+
import skimage.io # pylint: disable=import-error
|
9
|
+
import skimage.metrics # pylint: disable=import-error
|
10
|
+
import skimage.transform # pylint: disable=import-error
|
11
11
|
|
12
12
|
if TYPE_CHECKING:
|
13
13
|
from typing import TypeAlias
|
@@ -58,7 +58,7 @@ def normalize_image(image: NpNdarrayInt) -> NpNdarrayInt:
|
|
58
58
|
return image
|
59
59
|
|
60
60
|
|
61
|
-
def check_image(
|
61
|
+
def check_image(
|
62
62
|
result_folder: str,
|
63
63
|
image_to_check: NpNdarrayInt,
|
64
64
|
expected_filename: str,
|
@@ -108,13 +108,6 @@ def check_image( # pylint: disable=too-many-locals,too-many-statements
|
|
108
108
|
|
109
109
|
mask = None
|
110
110
|
if mask_filename is not None:
|
111
|
-
background_color = [255, 255, 255]
|
112
|
-
for color in range(3):
|
113
|
-
img_hist, _ = skimage.exposure.histogram(
|
114
|
-
image_to_check[..., color], nbins=256, source_range="dtype"
|
115
|
-
)
|
116
|
-
background_color[color] = np.argmax(img_hist)
|
117
|
-
|
118
111
|
mask = skimage.io.imread(mask_filename)
|
119
112
|
|
120
113
|
assert mask is not None, "Wrong mask: " + mask_filename
|
@@ -137,7 +130,7 @@ def check_image( # pylint: disable=too-many-locals,too-many-statements
|
|
137
130
|
assert (
|
138
131
|
mask.shape[0] == image_to_check.shape[0] and mask.shape[1] == image_to_check.shape[1]
|
139
132
|
), f"Mask and image should have the same shape ({mask.shape} != {image_to_check.shape})"
|
140
|
-
image_to_check[mask] =
|
133
|
+
image_to_check[mask] = [255, 255, 255]
|
141
134
|
|
142
135
|
if not os.path.exists(result_folder):
|
143
136
|
os.makedirs(result_folder)
|
@@ -155,7 +148,7 @@ def check_image( # pylint: disable=too-many-locals,too-many-statements
|
|
155
148
|
assert (
|
156
149
|
expected.shape[0] == mask.shape[0] and expected.shape[1] == mask.shape[1]
|
157
150
|
), f"Mask and expected image should have the same shape ({mask.shape} != {expected.shape})"
|
158
|
-
expected[mask] =
|
151
|
+
expected[mask] = [255, 255, 255]
|
159
152
|
|
160
153
|
assert (
|
161
154
|
expected.shape == image_to_check.shape
|
@@ -196,7 +189,7 @@ def check_screenshot(
|
|
196
189
|
|
197
190
|
See also `check_image` for the other parameters.
|
198
191
|
|
199
|
-
|
192
|
+
Arguments:
|
200
193
|
url: The URL to screenshot
|
201
194
|
width: The width of the generated screenshot
|
202
195
|
height: The height of the generated screenshot
|
@@ -209,7 +202,6 @@ def check_screenshot(
|
|
209
202
|
generate_expected_image: See `check_image`
|
210
203
|
use_mask: See `check_image`
|
211
204
|
"""
|
212
|
-
|
213
205
|
if headers is None:
|
214
206
|
headers = {}
|
215
207
|
if media is None:
|