c2cwsgiutils 6.2.0.dev34__tar.gz → 6.2.0.dev36__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.
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/PKG-INFO +1 -1
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/acceptance/__init__.py +1 -0
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/acceptance/connection.py +3 -2
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/acceptance/image.py +5 -3
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/acceptance/package-lock.json +13 -13
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/acceptance/package.json +1 -1
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/acceptance/print.py +1 -0
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/acceptance/utils.py +2 -1
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/auth.py +9 -8
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/broadcast/__init__.py +1 -1
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/broadcast/local.py +4 -0
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/broadcast/redis.py +8 -2
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/client_info.py +2 -0
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/coverage_setup.py +2 -2
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/db.py +11 -2
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/db_maintenance_view.py +1 -1
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/debug/__init__.py +4 -2
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/debug/_views.py +2 -3
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/errors.py +7 -2
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/health_check.py +39 -29
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/index.py +1 -1
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/logging_view.py +1 -1
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/models_graph.py +1 -1
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/pretty_json.py +1 -1
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/profiler.py +1 -0
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/prometheus.py +2 -0
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/pyramid.py +1 -0
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/pyramid_logging.py +4 -0
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/redis_stats.py +1 -1
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/redis_utils.py +2 -0
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/request_tracking/__init__.py +1 -1
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/scripts/genversion.py +4 -2
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/scripts/stats_db.py +1 -0
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/scripts/test_print.py +4 -1
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/sentry.py +1 -1
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/setup_process.py +3 -1
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/sql_profiler/__init__.py +1 -1
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/sql_profiler/_impl.py +1 -1
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/sqlalchemylogger/handlers.py +18 -12
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/stats_pyramid/__init__.py +2 -1
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/stats_pyramid/_pyramid_spy.py +1 -0
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/version.py +1 -1
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/pyproject.toml +8 -8
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/LICENSE +0 -0
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/README.md +0 -0
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/__init__.py +0 -0
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/acceptance/screenshot.js +0 -0
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/broadcast/interface.py +0 -0
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/broadcast/utils.py +0 -0
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/config_utils.py +0 -0
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/debug/_listeners.py +0 -0
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/debug/utils.py +0 -0
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/loader.py +0 -0
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/py.typed +0 -0
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/request_tracking/_sql.py +0 -0
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/scripts/__init__.py +0 -0
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/services.py +0 -0
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/sqlalchemylogger/README.md +0 -0
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/sqlalchemylogger/__init__.py +0 -0
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/sqlalchemylogger/_filters.py +0 -0
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/sqlalchemylogger/_models.py +0 -0
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/sqlalchemylogger/examples/example.py +0 -0
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/static/favicon-16x16.png +0 -0
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/static/favicon-32x32.png +0 -0
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/stats_pyramid/_db_spy.py +0 -0
- {c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/templates/index.html.mako +0 -0
@@ -20,6 +20,7 @@ def retry(
|
|
20
20
|
tries: number of times to try (not retry) before giving up
|
21
21
|
delay: initial delay between retries in seconds
|
22
22
|
backoff: backoff multiplier e.g. value of 2 will double the delay each retry
|
23
|
+
|
23
24
|
"""
|
24
25
|
|
25
26
|
def deco_retry(f: typing.Callable[..., typing.Any]) -> typing.Callable[..., typing.Any]:
|
@@ -20,6 +20,7 @@ class Connection:
|
|
20
20
|
"""The connection."""
|
21
21
|
|
22
22
|
def __init__(self, base_url: str, origin: str) -> None:
|
23
|
+
"""Initialize the connection."""
|
23
24
|
self.base_url = base_url
|
24
25
|
if not self.base_url.endswith("/"):
|
25
26
|
self.base_url += "/"
|
@@ -93,10 +94,10 @@ class Connection:
|
|
93
94
|
check_response(r, expected_status, cache_expected=cache_expected)
|
94
95
|
self._check_cors(cors, r)
|
95
96
|
r.raw.decode_content = True
|
96
|
-
doc = etree.parse(r.raw) #
|
97
|
+
doc = etree.parse(r.raw) # noqa: S320
|
97
98
|
if schema is not None:
|
98
99
|
with open(schema, encoding="utf-8") as schema_file:
|
99
|
-
xml_schema = etree.XMLSchema(etree.parse(schema_file)) #
|
100
|
+
xml_schema = etree.XMLSchema(etree.parse(schema_file)) # noqa: S320
|
100
101
|
xml_schema.assertValid(doc)
|
101
102
|
return doc
|
102
103
|
|
@@ -10,7 +10,7 @@ import skimage.metrics # pylint: disable=import-error
|
|
10
10
|
import skimage.transform # pylint: disable=import-error
|
11
11
|
|
12
12
|
if TYPE_CHECKING:
|
13
|
-
from
|
13
|
+
from typing_extensions import TypeAlias
|
14
14
|
|
15
15
|
NpNdarrayInt: TypeAlias = np.ndarray[np.uint8, Any]
|
16
16
|
else:
|
@@ -89,6 +89,7 @@ def check_image(
|
|
89
89
|
level: The minimum similarity level (between 0.0 and 1.0), default to 1.0
|
90
90
|
generate_expected_image: If `True` generate the expected image instead of checking it
|
91
91
|
use_mask: If `False` don't use the mask event if the file exists
|
92
|
+
|
92
93
|
"""
|
93
94
|
assert image_to_check is not None, "Image required"
|
94
95
|
image_file_basename = os.path.splitext(os.path.basename(expected_filename))[0]
|
@@ -122,7 +123,7 @@ def check_image(
|
|
122
123
|
if np.issubdtype(mask.dtype, np.floating):
|
123
124
|
mask = (mask * 255).astype("uint8")
|
124
125
|
|
125
|
-
assert ((
|
126
|
+
assert ((mask > 0) & (mask < 255)).sum() == 0, "Mask should be only black and white image"
|
126
127
|
|
127
128
|
# Convert to boolean
|
128
129
|
mask = mask == 0
|
@@ -139,7 +140,7 @@ def check_image(
|
|
139
140
|
return
|
140
141
|
if not os.path.isfile(expected_filename):
|
141
142
|
skimage.io.imsave(expected_filename, image_to_check)
|
142
|
-
|
143
|
+
raise AssertionError("Expected image not found: " + expected_filename)
|
143
144
|
expected = skimage.io.imread(expected_filename)
|
144
145
|
assert expected is not None, "Wrong image: " + expected_filename
|
145
146
|
expected = normalize_image(expected)
|
@@ -201,6 +202,7 @@ def check_screenshot(
|
|
201
202
|
level: See `check_image`
|
202
203
|
generate_expected_image: See `check_image`
|
203
204
|
use_mask: See `check_image`
|
205
|
+
|
204
206
|
"""
|
205
207
|
if headers is None:
|
206
208
|
headers = {}
|
{c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/acceptance/package-lock.json
RENAMED
@@ -6,7 +6,7 @@
|
|
6
6
|
"": {
|
7
7
|
"dependencies": {
|
8
8
|
"commander": "12.1.0",
|
9
|
-
"puppeteer": "23.
|
9
|
+
"puppeteer": "23.9.0"
|
10
10
|
}
|
11
11
|
},
|
12
12
|
"node_modules/@babel/code-frame": {
|
@@ -379,9 +379,9 @@
|
|
379
379
|
}
|
380
380
|
},
|
381
381
|
"node_modules/devtools-protocol": {
|
382
|
-
"version": "0.0.
|
383
|
-
"resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.
|
384
|
-
"integrity": "sha512-
|
382
|
+
"version": "0.0.1367902",
|
383
|
+
"resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1367902.tgz",
|
384
|
+
"integrity": "sha512-XxtPuC3PGakY6PD7dG66/o8KwJ/LkH2/EKe19Dcw58w53dv4/vSQEkn/SzuyhHE2q4zPgCkxQBxus3VV4ql+Pg==",
|
385
385
|
"license": "BSD-3-Clause"
|
386
386
|
},
|
387
387
|
"node_modules/emoji-regex": {
|
@@ -868,17 +868,17 @@
|
|
868
868
|
}
|
869
869
|
},
|
870
870
|
"node_modules/puppeteer": {
|
871
|
-
"version": "23.
|
872
|
-
"resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-23.
|
873
|
-
"integrity": "sha512-
|
871
|
+
"version": "23.9.0",
|
872
|
+
"resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-23.9.0.tgz",
|
873
|
+
"integrity": "sha512-WfB8jGwFV+qrD9dcJJVvWPFJBU6kxeu2wxJz9WooDGfM3vIiKLgzImEDBxUQnCBK/2cXB3d4dV6gs/LLpgfLDg==",
|
874
874
|
"hasInstallScript": true,
|
875
875
|
"license": "Apache-2.0",
|
876
876
|
"dependencies": {
|
877
877
|
"@puppeteer/browsers": "2.4.1",
|
878
878
|
"chromium-bidi": "0.8.0",
|
879
879
|
"cosmiconfig": "^9.0.0",
|
880
|
-
"devtools-protocol": "0.0.
|
881
|
-
"puppeteer-core": "23.
|
880
|
+
"devtools-protocol": "0.0.1367902",
|
881
|
+
"puppeteer-core": "23.9.0",
|
882
882
|
"typed-query-selector": "^2.12.0"
|
883
883
|
},
|
884
884
|
"bin": {
|
@@ -889,15 +889,15 @@
|
|
889
889
|
}
|
890
890
|
},
|
891
891
|
"node_modules/puppeteer-core": {
|
892
|
-
"version": "23.
|
893
|
-
"resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-23.
|
894
|
-
"integrity": "sha512-
|
892
|
+
"version": "23.9.0",
|
893
|
+
"resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-23.9.0.tgz",
|
894
|
+
"integrity": "sha512-hLVrav2HYMVdK0YILtfJwtnkBAwNOztUdR4aJ5YKDvgsbtagNr6urUJk9HyjRA9e+PaLI3jzJ0wM7A4jSZ7Qxw==",
|
895
895
|
"license": "Apache-2.0",
|
896
896
|
"dependencies": {
|
897
897
|
"@puppeteer/browsers": "2.4.1",
|
898
898
|
"chromium-bidi": "0.8.0",
|
899
899
|
"debug": "^4.3.7",
|
900
|
-
"devtools-protocol": "0.0.
|
900
|
+
"devtools-protocol": "0.0.1367902",
|
901
901
|
"typed-query-selector": "^2.12.0",
|
902
902
|
"ws": "^8.18.0"
|
903
903
|
},
|
@@ -21,6 +21,7 @@ class PrintConnection(connection.Connection):
|
|
21
21
|
base_url: The base URL to the print server (including the /print)
|
22
22
|
app: The name of the application to use
|
23
23
|
origin: The origin and referrer to include in the requests
|
24
|
+
|
24
25
|
"""
|
25
26
|
super().__init__(base_url=base_url, origin=origin)
|
26
27
|
self.session.headers["Referrer"] = origin
|
@@ -32,6 +32,7 @@ def retry_timeout(what: Callable[[], Any], timeout: float = _DEFAULT_TIMEOUT, in
|
|
32
32
|
what: the function to try
|
33
33
|
timeout: the timeout to get a success
|
34
34
|
interval: the interval between try
|
35
|
+
|
35
36
|
"""
|
36
37
|
timeout = time.perf_counter() + timeout
|
37
38
|
while True:
|
@@ -46,7 +47,7 @@ def retry_timeout(what: Callable[[], Any], timeout: float = _DEFAULT_TIMEOUT, in
|
|
46
47
|
error = str(e)
|
47
48
|
_LOG.info(" Failed: %s", e)
|
48
49
|
if time.perf_counter() > timeout:
|
49
|
-
|
50
|
+
raise AssertionError("Timeout: " + error)
|
50
51
|
time.sleep(interval)
|
51
52
|
|
52
53
|
|
@@ -12,32 +12,32 @@ from requests_oauthlib import OAuth2Session
|
|
12
12
|
from c2cwsgiutils.config_utils import config_bool, env_or_config, env_or_settings
|
13
13
|
|
14
14
|
_COOKIE_AGE = 7 * 24 * 3600
|
15
|
-
SECRET_PROP = "c2c.secret" #
|
16
|
-
SECRET_ENV = "C2C_SECRET" #
|
15
|
+
SECRET_PROP = "c2c.secret" # noqa: S105
|
16
|
+
SECRET_ENV = "C2C_SECRET" # noqa: S105
|
17
17
|
_GITHUB_REPOSITORY_PROP = "c2c.auth.github.repository"
|
18
18
|
_GITHUB_REPOSITORY_ENV = "C2C_AUTH_GITHUB_REPOSITORY"
|
19
19
|
_GITHUB_ACCESS_TYPE_PROP = "c2c.auth.github.access_type"
|
20
20
|
_GITHUB_ACCESS_TYPE_ENV = "C2C_AUTH_GITHUB_ACCESS_TYPE"
|
21
21
|
GITHUB_AUTH_URL_PROP = "c2c.auth.github.auth_url"
|
22
22
|
GITHUB_AUTH_URL_ENV = "C2C_AUTH_GITHUB_AUTH_URL"
|
23
|
-
GITHUB_TOKEN_URL_PROP = "c2c.auth.github.token_url" #
|
24
|
-
GITHUB_TOKEN_URL_ENV = "C2C_AUTH_GITHUB_TOKEN_URL" #
|
23
|
+
GITHUB_TOKEN_URL_PROP = "c2c.auth.github.token_url" # noqa: S105
|
24
|
+
GITHUB_TOKEN_URL_ENV = "C2C_AUTH_GITHUB_TOKEN_URL" # noqa: S105
|
25
25
|
GITHUB_USER_URL_PROP = "c2c.auth.github.user_url"
|
26
26
|
GITHUB_USER_URL_ENV = "C2C_AUTH_GITHUB_USER_URL"
|
27
27
|
_GITHUB_REPO_URL_PROP = "c2c.auth.github.repo_url"
|
28
28
|
_GITHUB_REPO_URL_ENV = "C2C_AUTH_GITHUB_REPO_URL"
|
29
29
|
GITHUB_CLIENT_ID_PROP = "c2c.auth.github.client_id"
|
30
30
|
GITHUB_CLIENT_ID_ENV = "C2C_AUTH_GITHUB_CLIENT_ID"
|
31
|
-
GITHUB_CLIENT_SECRET_PROP = "c2c.auth.github.client_secret" #
|
32
|
-
GITHUB_CLIENT_SECRET_ENV = "C2C_AUTH_GITHUB_CLIENT_SECRET" #
|
31
|
+
GITHUB_CLIENT_SECRET_PROP = "c2c.auth.github.client_secret" # noqa: S105
|
32
|
+
GITHUB_CLIENT_SECRET_ENV = "C2C_AUTH_GITHUB_CLIENT_SECRET" # noqa: S105
|
33
33
|
GITHUB_SCOPE_PROP = "c2c.auth.github.scope"
|
34
34
|
GITHUB_SCOPE_ENV = "C2C_AUTH_GITHUB_SCOPE"
|
35
35
|
# To be able to use private repository
|
36
36
|
GITHUB_SCOPE_DEFAULT = "repo"
|
37
37
|
GITHUB_AUTH_COOKIE_PROP = "c2c.auth.github.auth.cookie"
|
38
38
|
GITHUB_AUTH_COOKIE_ENV = "C2C_AUTH_GITHUB_COOKIE"
|
39
|
-
GITHUB_AUTH_SECRET_PROP = "c2c.auth.github.auth.secret" #
|
40
|
-
GITHUB_AUTH_SECRET_ENV = "C2C_AUTH_GITHUB_SECRET" #
|
39
|
+
GITHUB_AUTH_SECRET_PROP = "c2c.auth.github.auth.secret" # noqa: S105
|
40
|
+
GITHUB_AUTH_SECRET_ENV = "C2C_AUTH_GITHUB_SECRET" # noqa: S105
|
41
41
|
GITHUB_AUTH_PROXY_URL_PROP = "c2c.auth.github.auth.proxy_url"
|
42
42
|
GITHUB_AUTH_PROXY_URL_ENV = "C2C_AUTH_GITHUB_PROXY_URL"
|
43
43
|
USE_SESSION_PROP = "c2c.use_session"
|
@@ -209,6 +209,7 @@ def check_access(
|
|
209
209
|
request: is the request object.
|
210
210
|
repo: is the repository to check access to (<organization>/<repository>).
|
211
211
|
access_type: is the type of access to check (admin|push|pull).
|
212
|
+
|
212
213
|
"""
|
213
214
|
if not is_auth(request):
|
214
215
|
return False
|
@@ -19,7 +19,7 @@ _broadcaster: Optional[interface.BaseBroadcaster] = None
|
|
19
19
|
|
20
20
|
def init(config: Optional[pyramid.config.Configurator] = None) -> None:
|
21
21
|
"""Initialize the broadcaster with Redis, if configured, for backward compatibility."""
|
22
|
-
warnings.warn("init function is deprecated; use includeme instead")
|
22
|
+
warnings.warn("init function is deprecated; use includeme instead", stacklevel=2)
|
23
23
|
includeme(config)
|
24
24
|
|
25
25
|
|
@@ -9,17 +9,21 @@ class LocalBroadcaster(interface.BaseBroadcaster):
|
|
9
9
|
"""Fake implementation of broadcasting messages (will just answer locally)."""
|
10
10
|
|
11
11
|
def __init__(self) -> None:
|
12
|
+
"""Initialize the broadcaster."""
|
12
13
|
self._subscribers: MutableMapping[str, Callable[..., Any]] = {}
|
13
14
|
|
14
15
|
def subscribe(self, channel: str, callback: Callable[..., Any]) -> None:
|
16
|
+
"""Subscribe to a channel."""
|
15
17
|
self._subscribers[channel] = callback
|
16
18
|
|
17
19
|
def unsubscribe(self, channel: str) -> None:
|
20
|
+
"""Unsubscribe from a channel."""
|
18
21
|
del self._subscribers[channel]
|
19
22
|
|
20
23
|
def broadcast(
|
21
24
|
self, channel: str, params: Mapping[str, Any], expect_answers: bool, timeout: float
|
22
25
|
) -> Optional[list[Any]]:
|
26
|
+
"""Broadcast a message to all the listeners."""
|
23
27
|
subscriber = self._subscribers.get(channel, None)
|
24
28
|
answers = [utils.add_host_info(subscriber(**params))] if subscriber is not None else []
|
25
29
|
return answers if expect_answers else None
|
@@ -23,6 +23,7 @@ class RedisBroadcaster(interface.BaseBroadcaster):
|
|
23
23
|
master: "redis.client.Redis[str]",
|
24
24
|
slave: "redis.client.Redis[str]",
|
25
25
|
) -> None:
|
26
|
+
"""Initialize the broadcaster."""
|
26
27
|
from c2cwsgiutils import redis_utils # pylint: disable=import-outside-toplevel
|
27
28
|
|
28
29
|
self._master = master
|
@@ -40,6 +41,8 @@ class RedisBroadcaster(interface.BaseBroadcaster):
|
|
40
41
|
return self._broadcast_prefix + channel
|
41
42
|
|
42
43
|
def subscribe(self, channel: str, callback: Callable[..., Any]) -> None:
|
44
|
+
"""Subscribe to a channel."""
|
45
|
+
|
43
46
|
def wrapper(message: Mapping[str, Any]) -> None:
|
44
47
|
_LOG.debug("Received a broadcast on %s: %s", message["channel"], repr(message["data"]))
|
45
48
|
data = json.loads(message["data"])
|
@@ -58,6 +61,7 @@ class RedisBroadcaster(interface.BaseBroadcaster):
|
|
58
61
|
self._pub_sub.subscribe(**{actual_channel: wrapper})
|
59
62
|
|
60
63
|
def unsubscribe(self, channel: str) -> None:
|
64
|
+
"""Unsubscribe from a channel."""
|
61
65
|
_LOG.debug("Unsubscribing from %s")
|
62
66
|
actual_channel = self._get_channel(channel)
|
63
67
|
self._pub_sub.unsubscribe(actual_channel)
|
@@ -65,6 +69,7 @@ class RedisBroadcaster(interface.BaseBroadcaster):
|
|
65
69
|
def broadcast(
|
66
70
|
self, channel: str, params: Mapping[str, Any], expect_answers: bool, timeout: float
|
67
71
|
) -> Optional[list[Any]]:
|
72
|
+
"""Broadcast a message to all the listeners."""
|
68
73
|
if expect_answers:
|
69
74
|
return self._broadcast_with_answer(channel, params, timeout)
|
70
75
|
else:
|
@@ -85,7 +90,8 @@ class RedisBroadcaster(interface.BaseBroadcaster):
|
|
85
90
|
cond.notify()
|
86
91
|
|
87
92
|
answer_channel = self._get_channel(channel) + "".join(
|
88
|
-
random.choice(string.ascii_uppercase + string.digits)
|
93
|
+
random.choice(string.ascii_uppercase + string.digits) # noqa: S311
|
94
|
+
for _ in range(10)
|
89
95
|
)
|
90
96
|
_LOG.debug("Subscribing for broadcast answers on %s", answer_channel)
|
91
97
|
self._pub_sub.subscribe(**{answer_channel: callback})
|
@@ -98,7 +104,7 @@ class RedisBroadcaster(interface.BaseBroadcaster):
|
|
98
104
|
with cond:
|
99
105
|
while len(answers) < nb_received:
|
100
106
|
to_wait = timeout_time - time.perf_counter()
|
101
|
-
if to_wait <= 0.0:
|
107
|
+
if to_wait <= 0.0:
|
102
108
|
_LOG.warning(
|
103
109
|
"timeout waiting for %d/%d answers on %s",
|
104
110
|
len(answers),
|
@@ -16,9 +16,11 @@ class Filter:
|
|
16
16
|
"""
|
17
17
|
|
18
18
|
def __init__(self, application: Callable[[dict[str, str], Any], Any]):
|
19
|
+
"""Initialize the filter."""
|
19
20
|
self._application = application
|
20
21
|
|
21
22
|
def __call__(self, environ: dict[str, str], start_response: Any) -> Any:
|
23
|
+
"""Update the environ with the headers."""
|
22
24
|
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Forwarded
|
23
25
|
if "HTTP_FORWARDED" in environ:
|
24
26
|
_handle_forwarded(environ)
|
@@ -10,7 +10,7 @@ _LOG = logging.getLogger(__name__)
|
|
10
10
|
|
11
11
|
def init() -> None:
|
12
12
|
"""Initialize the code coverage, for backward compatibility."""
|
13
|
-
warnings.warn("init function is deprecated; use includeme instead")
|
13
|
+
warnings.warn("init function is deprecated; use includeme instead", stacklevel=2)
|
14
14
|
includeme()
|
15
15
|
|
16
16
|
|
@@ -22,7 +22,7 @@ def includeme(config: Optional[pyramid.config.Configurator] = None) -> None:
|
|
22
22
|
import coverage # pylint: disable=import-outside-toplevel
|
23
23
|
|
24
24
|
_LOG.warning("Setting up code coverage")
|
25
|
-
report_dir = "/tmp/coverage/api" #
|
25
|
+
report_dir = "/tmp/coverage/api" # noqa: S108
|
26
26
|
os.makedirs(report_dir, exist_ok=True)
|
27
27
|
cov = coverage.Coverage(
|
28
28
|
data_file=os.path.join(report_dir, "coverage"),
|
@@ -66,8 +66,11 @@ def setup_session(
|
|
66
66
|
force_slave: The method/paths that needs to use the slave
|
67
67
|
|
68
68
|
Returns: The SQLAlchemy session, the R/W engine and the R/O engine
|
69
|
+
|
69
70
|
"""
|
70
|
-
warnings.warn(
|
71
|
+
warnings.warn(
|
72
|
+
"setup_session function is deprecated; use init and request.dbsession instead", stacklevel=2
|
73
|
+
)
|
71
74
|
if slave_prefix is None:
|
72
75
|
slave_prefix = master_prefix
|
73
76
|
settings = config.registry.settings
|
@@ -122,8 +125,11 @@ def create_session(
|
|
122
125
|
engine_config: The rest of the parameters are passed as is to the sqlalchemy.create_engine function
|
123
126
|
|
124
127
|
Returns: The SQLAlchemy session
|
128
|
+
|
125
129
|
"""
|
126
|
-
warnings.warn(
|
130
|
+
warnings.warn(
|
131
|
+
"create_session function is deprecated; use init and request.dbsession instead", stacklevel=2
|
132
|
+
)
|
127
133
|
if slave_url is None:
|
128
134
|
slave_url = url
|
129
135
|
|
@@ -215,6 +221,7 @@ class SessionFactory(_sessionmaker):
|
|
215
221
|
ro_engine: sqlalchemy.engine.Engine,
|
216
222
|
rw_engine: sqlalchemy.engine.Engine,
|
217
223
|
):
|
224
|
+
"""Initialize the session factory."""
|
218
225
|
super().__init__()
|
219
226
|
self.master_paths: Iterable[Pattern[str]] = (
|
220
227
|
list(map(_RE_COMPILE, force_master)) if force_master else []
|
@@ -232,6 +239,7 @@ class SessionFactory(_sessionmaker):
|
|
232
239
|
def __call__( # type: ignore
|
233
240
|
self, request: Optional[pyramid.request.Request], readwrite: Optional[bool] = None, **local_kw: Any
|
234
241
|
) -> _scoped_session:
|
242
|
+
"""Set the engine based on the request."""
|
235
243
|
if readwrite is not None:
|
236
244
|
if readwrite and not FORCE_READONLY:
|
237
245
|
_LOG.debug("Using %s database", self.rw_engine.c2c_name) # type: ignore
|
@@ -374,6 +382,7 @@ def init(
|
|
374
382
|
force_slave: The method/paths that needs to use the slave
|
375
383
|
|
376
384
|
Returns: The SQLAlchemy session
|
385
|
+
|
377
386
|
"""
|
378
387
|
settings = config.get_settings()
|
379
388
|
settings["tm.manager_hook"] = "pyramid_tm.explicit_manager"
|
@@ -15,7 +15,7 @@ _REDIS_PREFIX = "c2c_db_maintenance_"
|
|
15
15
|
|
16
16
|
def install_subscriber(config: pyramid.config.Configurator) -> None:
|
17
17
|
"""Install the view to configure the loggers, if configured to do so, for backward compatibility."""
|
18
|
-
warnings.warn("install_subscriber function is deprecated; use includeme instead")
|
18
|
+
warnings.warn("install_subscriber function is deprecated; use includeme instead", stacklevel=2)
|
19
19
|
includeme(config)
|
20
20
|
|
21
21
|
|
@@ -16,7 +16,7 @@ dump_memory_maps = utils.dump_memory_maps
|
|
16
16
|
|
17
17
|
def init(config: pyramid.config.Configurator) -> None:
|
18
18
|
"""Initialize the debug tools, for backward compatibility."""
|
19
|
-
warnings.warn("init function is deprecated; use includeme instead")
|
19
|
+
warnings.warn("init function is deprecated; use includeme instead", stacklevel=2)
|
20
20
|
includeme(config)
|
21
21
|
|
22
22
|
|
@@ -37,6 +37,8 @@ def init_daemon(config: Optional[pyramid.config.Configurator] = None) -> None:
|
|
37
37
|
those requests.
|
38
38
|
"""
|
39
39
|
if config_utils.env_or_config(config, ENV_KEY, CONFIG_KEY, type_=config_utils.config_bool):
|
40
|
-
from c2cwsgiutils.debug import
|
40
|
+
from c2cwsgiutils.debug import ( # pylint: disable=import-outside-toplevel
|
41
|
+
_listeners,
|
42
|
+
)
|
41
43
|
|
42
44
|
_listeners.init()
|
@@ -79,7 +79,7 @@ def _dump_memory_diff(request: pyramid.request.Request) -> list[Any]:
|
|
79
79
|
try:
|
80
80
|
if request.params.get("no_warmup", "0").lower() in ("1", "true", "on"):
|
81
81
|
request.invoke_subrequest(sub_request)
|
82
|
-
except Exception: #
|
82
|
+
except Exception: # pylint: disable=broad-except
|
83
83
|
pass
|
84
84
|
|
85
85
|
_LOG.debug("checking memory growth for %s", path)
|
@@ -151,8 +151,7 @@ def _headers(request: pyramid.request.Request) -> Mapping[str, Any]:
|
|
151
151
|
}
|
152
152
|
if "status" in request.params:
|
153
153
|
raise exception_response(int(request.params["status"]), detail=result)
|
154
|
-
|
155
|
-
return result
|
154
|
+
return result
|
156
155
|
|
157
156
|
|
158
157
|
def _error(request: pyramid.request.Request) -> Any:
|
@@ -9,7 +9,12 @@ from typing import Any, Callable
|
|
9
9
|
import pyramid.request
|
10
10
|
import sqlalchemy.exc
|
11
11
|
from cornice import cors
|
12
|
-
from pyramid.httpexceptions import
|
12
|
+
from pyramid.httpexceptions import (
|
13
|
+
HTTPError,
|
14
|
+
HTTPException,
|
15
|
+
HTTPRedirection,
|
16
|
+
HTTPSuccessful,
|
17
|
+
)
|
13
18
|
from webob.request import DisconnectionError
|
14
19
|
|
15
20
|
from c2cwsgiutils import auth, config_utils
|
@@ -152,7 +157,7 @@ def _passthrough(exception: HTTPException, request: pyramid.request.Request) ->
|
|
152
157
|
|
153
158
|
def init(config: pyramid.config.Configurator) -> None:
|
154
159
|
"""Initialize the error views, for backward compatibility."""
|
155
|
-
warnings.warn("init function is deprecated; use includeme instead")
|
160
|
+
warnings.warn("init function is deprecated; use includeme instead", stacklevel=2)
|
156
161
|
includeme(config)
|
157
162
|
|
158
163
|
|
@@ -67,6 +67,7 @@ class JsonCheckException(Exception):
|
|
67
67
|
"""Checker exception used to add some structured content to a failure."""
|
68
68
|
|
69
69
|
def __init__(self, message: str, json: Any):
|
70
|
+
"""Initialize the exception."""
|
70
71
|
super().__init__()
|
71
72
|
self.message = message
|
72
73
|
self.json = json
|
@@ -199,6 +200,7 @@ class HealthCheck:
|
|
199
200
|
"""
|
200
201
|
|
201
202
|
def __init__(self, config: pyramid.config.Configurator) -> None:
|
203
|
+
"""Initialize the health check view."""
|
202
204
|
config.add_route(
|
203
205
|
"c2c_health_check", config_utils.get_base_path(config) + r"/health_check", request_method="GET"
|
204
206
|
)
|
@@ -235,6 +237,7 @@ class HealthCheck:
|
|
235
237
|
engine_type: whether to check only the RW, RO or both engines
|
236
238
|
rw_engin: the RW engine to use (if None, use the session one)
|
237
239
|
ro_engin: the RO engine to use (if None, use the session one)
|
240
|
+
|
238
241
|
"""
|
239
242
|
if query_cb is None:
|
240
243
|
query_cb = self._at_least_one(at_least_one_model)
|
@@ -265,6 +268,7 @@ class HealthCheck:
|
|
265
268
|
version_table: override the table name for the version
|
266
269
|
rw_engin: the RW engine to use (if None, use the session one)
|
267
270
|
ro_engin: the RO engine to use (if None, use the session one)
|
271
|
+
|
268
272
|
"""
|
269
273
|
version_ = _get_alembic_version(alembic_ini_path, name)
|
270
274
|
|
@@ -287,26 +291,28 @@ class HealthCheck:
|
|
287
291
|
assert version_schema
|
288
292
|
assert version_table
|
289
293
|
for binding in _get_bindings(self.session, EngineType.READ_AND_WRITE):
|
290
|
-
with
|
291
|
-
|
294
|
+
with (
|
295
|
+
binding as binded_session,
|
296
|
+
_PROMETHEUS_DB_SUMMARY.labels(
|
292
297
|
configuration=alembic_ini_path, connection=binding.name(), check="alembic"
|
293
|
-
).time()
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
)
|
300
|
-
)
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
)
|
298
|
+
).time(),
|
299
|
+
):
|
300
|
+
result = binded_session.execute(
|
301
|
+
sqlalchemy.text(
|
302
|
+
"SELECT version_num FROM " # noqa: S608
|
303
|
+
f"{sqlalchemy.sql.quoted_name(version_schema, True)}."
|
304
|
+
f"{sqlalchemy.sql.quoted_name(version_table, True)}"
|
305
|
+
)
|
306
|
+
).fetchone()
|
307
|
+
assert result is not None
|
308
|
+
(actual_version,) = result
|
309
|
+
_PROMETHEUS_ALEMBIC_VERSION.labels(
|
310
|
+
version=actual_version, name=name, configuration=alembic_ini_path
|
311
|
+
).set(1)
|
312
|
+
if actual_version != version_:
|
313
|
+
raise Exception( # pylint: disable=broad-exception-raised
|
314
|
+
f"Invalid alembic version (db: {actual_version}, code: {version_})"
|
315
|
+
)
|
310
316
|
return version_
|
311
317
|
|
312
318
|
self._checks.append(
|
@@ -321,9 +327,8 @@ class HealthCheck:
|
|
321
327
|
Mapping[str, str], Callable[[pyramid.request.Request], Mapping[str, str]], None
|
322
328
|
] = None,
|
323
329
|
name: Optional[str] = None,
|
324
|
-
check_cb: Callable[
|
325
|
-
|
326
|
-
] = lambda request, response: None,
|
330
|
+
check_cb: Callable[[pyramid.request.Request, requests.Response], Any] = lambda request,
|
331
|
+
response: None,
|
327
332
|
timeout: float = 3,
|
328
333
|
level: int = 1,
|
329
334
|
) -> None:
|
@@ -339,6 +344,7 @@ class HealthCheck:
|
|
339
344
|
response as parameters)
|
340
345
|
timeout: the timeout
|
341
346
|
level: the level of the health check
|
347
|
+
|
342
348
|
"""
|
343
349
|
|
344
350
|
def check(request: pyramid.request.Request) -> Any:
|
@@ -365,6 +371,7 @@ class HealthCheck:
|
|
365
371
|
Arguments:
|
366
372
|
name: the name of the check (defaults to url)
|
367
373
|
level: the level of the health check
|
374
|
+
|
368
375
|
"""
|
369
376
|
|
370
377
|
def check(request: pyramid.request.Request) -> Any:
|
@@ -413,6 +420,7 @@ class HealthCheck:
|
|
413
420
|
Arguments:
|
414
421
|
name: the name of the check (defaults to "version")
|
415
422
|
level: the level of the health check
|
423
|
+
|
416
424
|
"""
|
417
425
|
|
418
426
|
def check(request: pyramid.request.Request) -> dict[str, Any]:
|
@@ -441,6 +449,7 @@ class HealthCheck:
|
|
441
449
|
name: the name of the check
|
442
450
|
check_cb: the callback to call (takes the request as parameter)
|
443
451
|
level: the level of the health check
|
452
|
+
|
444
453
|
"""
|
445
454
|
assert name
|
446
455
|
self._checks.append((name, check_cb, level))
|
@@ -453,9 +462,8 @@ class HealthCheck:
|
|
453
462
|
"successes": {},
|
454
463
|
}
|
455
464
|
checks = None
|
456
|
-
if "checks" in request.params:
|
457
|
-
|
458
|
-
checks = request.params["checks"].split(",")
|
465
|
+
if "checks" in request.params and request.params["checks"] != "":
|
466
|
+
checks = request.params["checks"].split(",")
|
459
467
|
for name, check, level in self._checks:
|
460
468
|
if level <= max_level and (checks is None or name in checks):
|
461
469
|
self._run_one(check, is_auth, level, name, request, results)
|
@@ -498,11 +506,13 @@ class HealthCheck:
|
|
498
506
|
) -> tuple[str, Callable[[pyramid.request.Request], None]]:
|
499
507
|
def check(request: pyramid.request.Request) -> None:
|
500
508
|
del request # unused
|
501
|
-
with
|
502
|
-
|
509
|
+
with (
|
510
|
+
binding as session,
|
511
|
+
_PROMETHEUS_DB_SUMMARY.labels(
|
503
512
|
connection=binding.name(), check="database", configuration="<default>"
|
504
|
-
).time()
|
505
|
-
|
513
|
+
).time(),
|
514
|
+
):
|
515
|
+
return query_cb(session)
|
506
516
|
|
507
517
|
return "db_engine_" + binding.name(), check
|
508
518
|
|
@@ -501,7 +501,7 @@ def _github_logout(request: pyramid.request.Request) -> dict[str, Any]:
|
|
501
501
|
|
502
502
|
def init(config: pyramid.config.Configurator) -> None:
|
503
503
|
"""Initialize the index page, for backward compatibility."""
|
504
|
-
warnings.warn("init function is deprecated; use includeme instead")
|
504
|
+
warnings.warn("init function is deprecated; use includeme instead", stacklevel=2)
|
505
505
|
includeme(config)
|
506
506
|
|
507
507
|
|
@@ -15,7 +15,7 @@ _REDIS_PREFIX = "c2c_logging_level_"
|
|
15
15
|
|
16
16
|
def install_subscriber(config: pyramid.config.Configurator) -> None:
|
17
17
|
"""Install the view to configure the loggers, if configured to do so, for backward compatibility."""
|
18
|
-
warnings.warn("install_subscriber function is deprecated; use includeme instead")
|
18
|
+
warnings.warn("install_subscriber function is deprecated; use includeme instead", stacklevel=2)
|
19
19
|
includeme(config)
|
20
20
|
|
21
21
|
|
@@ -44,7 +44,7 @@ def _generate_model_graph(module: Any, base: Any) -> None:
|
|
44
44
|
def _print_node(symbol: Any, interesting: set[Any]) -> None:
|
45
45
|
print(f'{symbol.__name__} [label="{_get_table_desc(symbol)}", shape=box];')
|
46
46
|
for parent in symbol.__bases__:
|
47
|
-
if parent
|
47
|
+
if parent is not object:
|
48
48
|
if parent not in interesting:
|
49
49
|
_print_node(parent, interesting)
|
50
50
|
interesting.add(parent)
|
@@ -28,7 +28,7 @@ class _FastDumps:
|
|
28
28
|
|
29
29
|
def init(config: pyramid.config.Configurator) -> None:
|
30
30
|
"""Initialize json and fast_json renderer, for backward compatibility."""
|
31
|
-
warnings.warn("init function is deprecated; use includeme instead")
|
31
|
+
warnings.warn("init function is deprecated; use includeme instead", stacklevel=2)
|
32
32
|
includeme(config)
|
33
33
|
|
34
34
|
|
@@ -9,6 +9,7 @@ class Profile(contextlib.ContextDecorator):
|
|
9
9
|
"""Used to profile a function with a decorator or with a with statement."""
|
10
10
|
|
11
11
|
def __init__(self, path: str, print_number: int = 0) -> None:
|
12
|
+
"""Initialize the profiler."""
|
12
13
|
self.path = path
|
13
14
|
self.print_number = print_number
|
14
15
|
self.pr = cProfile.Profile()
|
@@ -115,6 +115,7 @@ class MultiProcessCustomCollector(prometheus_client.registry.Collector):
|
|
115
115
|
"""Get the metrics from the custom collectors."""
|
116
116
|
|
117
117
|
def collect(self) -> Generator[prometheus_client.core.Metric, None, None]:
|
118
|
+
"""Get the metrics from the custom collectors."""
|
118
119
|
results: list[list[SerializedMetric]] = []
|
119
120
|
for channel in MULTI_PROCESS_COLLECTOR_BROADCAST_CHANNELS:
|
120
121
|
result = broadcast.broadcast(channel, expect_answers=True)
|
@@ -159,6 +160,7 @@ class MemoryMapCollector(prometheus_client.registry.Collector):
|
|
159
160
|
Arguments:
|
160
161
|
memory_type: can be rss, pss or size
|
161
162
|
pids: the list of pids or none
|
163
|
+
|
162
164
|
"""
|
163
165
|
super().__init__()
|
164
166
|
self.memory_type = memory_type
|
@@ -87,10 +87,12 @@ class PyramidCeeSysLogHandler(cee_syslog_handler.CeeSysLogHandler): # type: ign
|
|
87
87
|
"""A CEE (JSON format) log handler with additional information about the current request."""
|
88
88
|
|
89
89
|
def __init__(self, *args: Any, **kargv: Any) -> None:
|
90
|
+
"""Initialize the handler."""
|
90
91
|
super().__init__(*args, **kargv)
|
91
92
|
self.addFilter(_PYRAMID_FILTER)
|
92
93
|
|
93
94
|
def format(self, record: Any) -> str:
|
95
|
+
"""Format the record into a CEE string."""
|
94
96
|
message = _make_message_dict(
|
95
97
|
record,
|
96
98
|
self._fqdn,
|
@@ -112,11 +114,13 @@ class JsonLogHandler(Base):
|
|
112
114
|
"""Log to stdout in JSON."""
|
113
115
|
|
114
116
|
def __init__(self, stream: Optional[TextIO] = None):
|
117
|
+
"""Initialize the handler."""
|
115
118
|
super().__init__(stream)
|
116
119
|
self.addFilter(_PYRAMID_FILTER)
|
117
120
|
self._fqdn = socket.getfqdn()
|
118
121
|
|
119
122
|
def format(self, record: Any) -> str:
|
123
|
+
"""Format the record into a JSON string."""
|
120
124
|
message = _make_message_dict(
|
121
125
|
record, self._fqdn, debugging_fields=True, extra_fields=True, facility=None, static_fields={}
|
122
126
|
)
|
@@ -26,7 +26,7 @@ def _execute_command_patch(self: Any, command: str, *args: Any, **options: Any)
|
|
26
26
|
|
27
27
|
def init(config: Optional[pyramid.config.Configurator] = None) -> None:
|
28
28
|
"""Initialize the Redis tracking, for backward compatibility."""
|
29
|
-
warnings.warn("init function is deprecated; use includeme instead")
|
29
|
+
warnings.warn("init function is deprecated; use includeme instead", stacklevel=2)
|
30
30
|
includeme(config)
|
31
31
|
|
32
32
|
|
@@ -100,11 +100,13 @@ class PubSubWorkerThread(threading.Thread):
|
|
100
100
|
"""A clone of redis.client.PubSubWorkerThread that doesn't die when the connections are broken."""
|
101
101
|
|
102
102
|
def __init__(self, pubsub: redis.client.PubSub, name: Optional[str] = None) -> None:
|
103
|
+
"""Initialize the PubSubWorkerThread."""
|
103
104
|
super().__init__(name=name, daemon=True)
|
104
105
|
self.pubsub = pubsub
|
105
106
|
self._running = False
|
106
107
|
|
107
108
|
def run(self) -> None:
|
109
|
+
"""Run the worker."""
|
108
110
|
if self._running:
|
109
111
|
return
|
110
112
|
self._running = True
|
{c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/request_tracking/__init__.py
RENAMED
@@ -83,7 +83,7 @@ def _patch_requests() -> None:
|
|
83
83
|
|
84
84
|
def init(config: Optional[pyramid.config.Configurator] = None) -> None:
|
85
85
|
"""Initialize the request tracking, for backward compatibility."""
|
86
|
-
warnings.warn("init function is deprecated; use includeme instead")
|
86
|
+
warnings.warn("init function is deprecated; use includeme instead", stacklevel=2)
|
87
87
|
includeme(config)
|
88
88
|
|
89
89
|
|
@@ -24,7 +24,7 @@ def _get_package_version(comp: str) -> tuple[Optional[str], Optional[str]]:
|
|
24
24
|
if matcher:
|
25
25
|
return cast(tuple[str, str], matcher.groups())
|
26
26
|
else:
|
27
|
-
if len(comp) > 0 and
|
27
|
+
if len(comp) > 0 and comp[:3] != "-e ":
|
28
28
|
print("Cannot parse package version: " + comp)
|
29
29
|
return None, None
|
30
30
|
|
@@ -46,7 +46,9 @@ def _get_packages_version() -> dict[str, str]:
|
|
46
46
|
|
47
47
|
def deprecated() -> None:
|
48
48
|
"""Run the command and print a deprecated notice."""
|
49
|
-
warnings.warn(
|
49
|
+
warnings.warn(
|
50
|
+
"c2cwsgiutils_genversion.py is deprecated; use c2cwsgiutils-genversion instead", stacklevel=2
|
51
|
+
)
|
50
52
|
return main()
|
51
53
|
|
52
54
|
|
@@ -62,6 +62,7 @@ class Reporter:
|
|
62
62
|
"""The stats reporter."""
|
63
63
|
|
64
64
|
def __init__(self, args: argparse.Namespace) -> None:
|
65
|
+
"""Initialize the reporter."""
|
65
66
|
self._error: Optional[Exception] = None
|
66
67
|
self.registry = CollectorRegistry()
|
67
68
|
self.prometheus_push = args.prometheus_url is not None
|
@@ -1,5 +1,6 @@
|
|
1
1
|
#!/usr/bin/env python3
|
2
2
|
"""Test a MapfishPrint server."""
|
3
|
+
|
3
4
|
import argparse
|
4
5
|
import logging
|
5
6
|
import pprint
|
@@ -23,7 +24,9 @@ def _parse_args() -> argparse.Namespace:
|
|
23
24
|
|
24
25
|
def deprecated() -> None:
|
25
26
|
"""Run the command and print a deprecated notice."""
|
26
|
-
warnings.warn(
|
27
|
+
warnings.warn(
|
28
|
+
"c2cwsgiutils_test_print.py is deprecated; use c2cwsgiutils-test-print instead", stacklevel=2
|
29
|
+
)
|
27
30
|
return main()
|
28
31
|
|
29
32
|
|
@@ -33,7 +33,7 @@ def _create_before_send_filter(tags: MutableMapping[str, str]) -> Callable[[Any,
|
|
33
33
|
|
34
34
|
def init(config: Optional[pyramid.config.Configurator] = None) -> None:
|
35
35
|
"""Initialize the Sentry integration, for backward compatibility."""
|
36
|
-
warnings.warn("init function is deprecated; use includeme instead")
|
36
|
+
warnings.warn("init function is deprecated; use includeme instead", stacklevel=2)
|
37
37
|
includeme(config)
|
38
38
|
|
39
39
|
|
@@ -55,7 +55,9 @@ def init(config_file: str = "c2c:///app/production.ini") -> None:
|
|
55
55
|
|
56
56
|
def init_logging(config_file: str = "c2c:///app/production.ini") -> None:
|
57
57
|
"""Initialize the non-WSGI application."""
|
58
|
-
warnings.warn(
|
58
|
+
warnings.warn(
|
59
|
+
"init_logging function is deprecated; use init instead so that all features are enabled", stacklevel=2
|
60
|
+
)
|
59
61
|
loader = get_config_loader(config_file)
|
60
62
|
loader.setup_logging(None)
|
61
63
|
|
@@ -18,7 +18,7 @@ _LOG = logging.getLogger(__name__)
|
|
18
18
|
|
19
19
|
def init(config: pyramid.config.Configurator) -> None:
|
20
20
|
"""Install a pyramid event handler that adds the request information, for backward compatibility."""
|
21
|
-
warnings.warn("init function is deprecated; use includeme instead")
|
21
|
+
warnings.warn("init function is deprecated; use includeme instead", stacklevel=2)
|
22
22
|
includeme(config)
|
23
23
|
|
24
24
|
|
{c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/sqlalchemylogger/handlers.py
RENAMED
@@ -11,7 +11,10 @@ from sqlalchemy.exc import SQLAlchemyError
|
|
11
11
|
from sqlalchemy.orm import sessionmaker
|
12
12
|
from sqlalchemy_utils import create_database, database_exists
|
13
13
|
|
14
|
-
from c2cwsgiutils.sqlalchemylogger._filters import
|
14
|
+
from c2cwsgiutils.sqlalchemylogger._filters import (
|
15
|
+
ContainsExpression,
|
16
|
+
DoesNotContainExpression,
|
17
|
+
)
|
15
18
|
from c2cwsgiutils.sqlalchemylogger._models import Base, create_log_class
|
16
19
|
|
17
20
|
_LOG = logging.getLogger(__name__)
|
@@ -29,12 +32,13 @@ class SQLAlchemyHandler(logging.Handler):
|
|
29
32
|
does_not_contain_expression: str = "",
|
30
33
|
contains_expression: str = "",
|
31
34
|
) -> None:
|
35
|
+
"""Initialize the SQLAlchemyHandler."""
|
32
36
|
super().__init__()
|
33
37
|
# Initialize DB session
|
34
38
|
self.engine = create_engine(sqlalchemy_url["url"])
|
35
39
|
self.Log = create_log_class( # pylint: disable=invalid-name
|
36
40
|
tablename=sqlalchemy_url.get("tablename", "logs"),
|
37
|
-
tableargs=sqlalchemy_url.get("tableargs"
|
41
|
+
tableargs=sqlalchemy_url.get("tableargs"), # type: ignore
|
38
42
|
)
|
39
43
|
Base.metadata.bind = self.engine
|
40
44
|
self.session = sessionmaker(bind=self.engine)() # noqa
|
@@ -61,15 +65,16 @@ class SQLAlchemyHandler(logging.Handler):
|
|
61
65
|
if not self.log_queue.empty():
|
62
66
|
logs.append(self.log_queue.get())
|
63
67
|
self.log_queue.task_done()
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
)
|
71
|
-
|
72
|
-
|
68
|
+
# try to reduce the number of INSERT requests to the DB
|
69
|
+
# by writing chunks of self.MAX_NB_LOGS size,
|
70
|
+
# but also do not wait forever before writing stuff (self.MAX_TIMOUT)
|
71
|
+
if (
|
72
|
+
logs
|
73
|
+
and (len(logs) >= self.MAX_NB_LOGS)
|
74
|
+
or (time.perf_counter() >= (time_since_last + self.MAX_TIMEOUT))
|
75
|
+
):
|
76
|
+
self._write_logs(logs)
|
77
|
+
break
|
73
78
|
_LOG.debug("%s: stopping processor thread", __name__)
|
74
79
|
|
75
80
|
def _write_logs(self, logs: list[Any]) -> None:
|
@@ -94,7 +99,7 @@ class SQLAlchemyHandler(logging.Handler):
|
|
94
99
|
_LOG.info("%s: creating new database", __name__)
|
95
100
|
if not database_exists(self.engine.url):
|
96
101
|
create_database(self.engine.url)
|
97
|
-
# FIXME: we should not access directly the private __table_args__
|
102
|
+
# FIXME: we should not access directly the private __table_args__ # pylint: disable=fixme
|
98
103
|
# variable, but add an accessor method in models.Log class
|
99
104
|
if not isinstance(self.Log.__table_args__, type(None)) and self.Log.__table_args__.get(
|
100
105
|
"schema", None
|
@@ -107,6 +112,7 @@ class SQLAlchemyHandler(logging.Handler):
|
|
107
112
|
Base.metadata.create_all(self.engine)
|
108
113
|
|
109
114
|
def emit(self, record: Any) -> None:
|
115
|
+
"""Emit the log."""
|
110
116
|
trace = None
|
111
117
|
exc = record.__dict__["exc_info"]
|
112
118
|
if exc:
|
{c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/stats_pyramid/__init__.py
RENAMED
@@ -10,7 +10,7 @@ from c2cwsgiutils.stats_pyramid import _pyramid_spy
|
|
10
10
|
|
11
11
|
def init(config: pyramid.config.Configurator) -> None:
|
12
12
|
"""Initialize the whole stats module, for backward compatibility."""
|
13
|
-
warnings.warn("init function is deprecated; use includeme instead")
|
13
|
+
warnings.warn("init function is deprecated; use includeme instead", stacklevel=2)
|
14
14
|
includeme(config)
|
15
15
|
|
16
16
|
|
@@ -20,6 +20,7 @@ def includeme(config: pyramid.config.Configurator) -> None:
|
|
20
20
|
|
21
21
|
Arguments:
|
22
22
|
config: The Pyramid config
|
23
|
+
|
23
24
|
"""
|
24
25
|
_pyramid_spy.init(config)
|
25
26
|
init_db_spy()
|
{c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/stats_pyramid/_pyramid_spy.py
RENAMED
@@ -99,6 +99,7 @@ def init(config: pyramid.config.Configurator) -> None: # pragma: nocover
|
|
99
99
|
|
100
100
|
Arguments:
|
101
101
|
config: The Pyramid config
|
102
|
+
|
102
103
|
"""
|
103
104
|
config.add_subscriber(_request_callback, pyramid.events.NewRequest)
|
104
105
|
config.add_subscriber(_before_rendered_callback, pyramid.events.BeforeRender)
|
@@ -37,7 +37,7 @@ _PROMETHEUS_VERSIONS_INFO = prometheus_client.Gauge(
|
|
37
37
|
|
38
38
|
def init(config: pyramid.config.Configurator) -> None:
|
39
39
|
"""Initialize the versions view, for backward compatibility."""
|
40
|
-
warnings.warn("init function is deprecated; use includeme instead")
|
40
|
+
warnings.warn("init function is deprecated; use includeme instead", stacklevel=2)
|
41
41
|
includeme(config)
|
42
42
|
|
43
43
|
|
@@ -16,7 +16,7 @@ strict = true
|
|
16
16
|
|
17
17
|
[tool.poetry]
|
18
18
|
name = "c2cwsgiutils"
|
19
|
-
version = "6.2.0.
|
19
|
+
version = "6.2.0.dev36"
|
20
20
|
description = "Common utilities for Camptocamp WSGI applications"
|
21
21
|
readme = "README.md"
|
22
22
|
authors = ["Camptocamp <info@camptocamp.com>"]
|
@@ -78,15 +78,15 @@ lxml = { version = "5.3.0", optional = true }
|
|
78
78
|
objgraph = { version = "3.6.2", optional = true }
|
79
79
|
psycopg2 = { version = "2.9.10", optional = true }
|
80
80
|
pyramid = { version = "2.0.2", optional = true }
|
81
|
-
pyramid-tm = { version = "2.
|
82
|
-
sentry-sdk = { version = "2.
|
81
|
+
pyramid-tm = { version = "2.6", optional = true }
|
82
|
+
sentry-sdk = { version = "2.19.0", optional = true }
|
83
83
|
ujson = { version = "5.10.0" }
|
84
84
|
cee_syslog_handler = { version = "0.6.0" }
|
85
85
|
SQLAlchemy = { version = "2.0.36", optional = true }
|
86
86
|
SQLAlchemy-Utils = { version = "0.41.2", optional = true }
|
87
|
-
"zope.interface" = { version = "7.
|
87
|
+
"zope.interface" = { version = "7.2", optional = true }
|
88
88
|
"zope.sqlalchemy" = { version = "3.1", optional = true }
|
89
|
-
pyjwt = { version = "2.
|
89
|
+
pyjwt = { version = "2.10.1", optional = true }
|
90
90
|
requests-oauthlib = { version = "2.0.0", optional = true }
|
91
91
|
waitress = { version = "3.0.2", optional = true }
|
92
92
|
scikit-image = { version = "0.24.0", optional = true }
|
@@ -172,9 +172,9 @@ test_images = ["scikit-image"]
|
|
172
172
|
|
173
173
|
[tool.poetry.group.dev.dependencies]
|
174
174
|
# pylint = { version = "2.15.6" }
|
175
|
-
prospector = { extras = ["with_bandit", "with_mypy", "with_pyroma"
|
176
|
-
prospector-profile-duplicated = "1.
|
177
|
-
prospector-profile-utils = "1.
|
175
|
+
prospector = { version = "1.13.3", extras = ["with_bandit", "with_mypy", "with_pyroma", "with_ruff"] }
|
176
|
+
prospector-profile-duplicated = "1.9.0"
|
177
|
+
prospector-profile-utils = "1.14.0"
|
178
178
|
coverage = "7.6.8"
|
179
179
|
junit2html = "31.0.2"
|
180
180
|
pytest = "8.3.4"
|
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
|
{c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/sqlalchemylogger/README.md
RENAMED
File without changes
|
{c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/sqlalchemylogger/__init__.py
RENAMED
File without changes
|
{c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/sqlalchemylogger/_filters.py
RENAMED
File without changes
|
{c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/sqlalchemylogger/_models.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{c2cwsgiutils-6.2.0.dev34 → c2cwsgiutils-6.2.0.dev36}/c2cwsgiutils/templates/index.html.mako
RENAMED
File without changes
|