c2cwsgiutils 6.2.0.dev35__py3-none-any.whl → 6.2.0.dev39__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.
Files changed (48) hide show
  1. c2cwsgiutils/acceptance/__init__.py +1 -0
  2. c2cwsgiutils/acceptance/connection.py +3 -2
  3. c2cwsgiutils/acceptance/image.py +5 -3
  4. c2cwsgiutils/acceptance/package-lock.json +13 -13
  5. c2cwsgiutils/acceptance/package.json +1 -1
  6. c2cwsgiutils/acceptance/print.py +1 -0
  7. c2cwsgiutils/acceptance/utils.py +2 -1
  8. c2cwsgiutils/auth.py +9 -8
  9. c2cwsgiutils/broadcast/__init__.py +1 -1
  10. c2cwsgiutils/broadcast/local.py +4 -0
  11. c2cwsgiutils/broadcast/redis.py +8 -2
  12. c2cwsgiutils/client_info.py +2 -0
  13. c2cwsgiutils/coverage_setup.py +2 -2
  14. c2cwsgiutils/db.py +11 -2
  15. c2cwsgiutils/db_maintenance_view.py +1 -1
  16. c2cwsgiutils/debug/__init__.py +4 -2
  17. c2cwsgiutils/debug/_views.py +2 -3
  18. c2cwsgiutils/errors.py +7 -2
  19. c2cwsgiutils/health_check.py +39 -29
  20. c2cwsgiutils/index.py +1 -1
  21. c2cwsgiutils/loader.py +20 -2
  22. c2cwsgiutils/logging_view.py +1 -1
  23. c2cwsgiutils/models_graph.py +1 -1
  24. c2cwsgiutils/pretty_json.py +1 -1
  25. c2cwsgiutils/profiler.py +1 -0
  26. c2cwsgiutils/prometheus.py +58 -0
  27. c2cwsgiutils/pyramid.py +1 -0
  28. c2cwsgiutils/pyramid_logging.py +4 -0
  29. c2cwsgiutils/redis_stats.py +1 -1
  30. c2cwsgiutils/redis_utils.py +2 -0
  31. c2cwsgiutils/request_tracking/__init__.py +1 -1
  32. c2cwsgiutils/scripts/genversion.py +4 -2
  33. c2cwsgiutils/scripts/stats_db.py +1 -0
  34. c2cwsgiutils/scripts/test_print.py +4 -1
  35. c2cwsgiutils/sentry.py +1 -1
  36. c2cwsgiutils/setup_process.py +5 -1
  37. c2cwsgiutils/sql_profiler/__init__.py +1 -1
  38. c2cwsgiutils/sql_profiler/_impl.py +1 -1
  39. c2cwsgiutils/sqlalchemylogger/handlers.py +18 -12
  40. c2cwsgiutils/stats_pyramid/__init__.py +2 -1
  41. c2cwsgiutils/stats_pyramid/_pyramid_spy.py +1 -0
  42. c2cwsgiutils/version.py +1 -1
  43. {c2cwsgiutils-6.2.0.dev35.dist-info → c2cwsgiutils-6.2.0.dev39.dist-info}/METADATA +73 -12
  44. c2cwsgiutils-6.2.0.dev39.dist-info/RECORD +67 -0
  45. c2cwsgiutils-6.2.0.dev35.dist-info/RECORD +0 -67
  46. {c2cwsgiutils-6.2.0.dev35.dist-info → c2cwsgiutils-6.2.0.dev39.dist-info}/LICENSE +0 -0
  47. {c2cwsgiutils-6.2.0.dev35.dist-info → c2cwsgiutils-6.2.0.dev39.dist-info}/WHEEL +0 -0
  48. {c2cwsgiutils-6.2.0.dev35.dist-info → c2cwsgiutils-6.2.0.dev39.dist-info}/entry_points.txt +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) # nosec
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)) # nosec
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 typing import TypeAlias
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 ((0 < mask) & (mask < 255)).sum() == 0, "Mask should be only black and white image"
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
- assert False, "Expected image not found: " + expected_filename
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 = {}
@@ -6,7 +6,7 @@
6
6
  "": {
7
7
  "dependencies": {
8
8
  "commander": "12.1.0",
9
- "puppeteer": "23.7.1"
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.1354347",
383
- "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1354347.tgz",
384
- "integrity": "sha512-BlmkSqV0V84E2WnEnoPnwyix57rQxAM5SKJjf4TbYOCGLAWtz8CDH8RIaGOjPgPCXo2Mce3kxSY497OySidY3Q==",
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.7.1",
872
- "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-23.7.1.tgz",
873
- "integrity": "sha512-jS6XehagMvxQ12etwY/4EOYZ0Sm8GAsrtGhdQn4AqpJAyHc3RYl7tGd4QYh/MmShDw8sF9FWYQqGidhoXaqokQ==",
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.1354347",
881
- "puppeteer-core": "23.7.1",
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.7.1",
893
- "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-23.7.1.tgz",
894
- "integrity": "sha512-Om/qCZhd+HLoAr7GltrRAZpS3uOXwHu7tXAoDbNcJADHjG2zeAlDArgyIPXYGG4QB/EQUHk13Q6RklNxGM73Pg==",
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.1354347",
900
+ "devtools-protocol": "0.0.1367902",
901
901
  "typed-query-selector": "^2.12.0",
902
902
  "ws": "^8.18.0"
903
903
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "dependencies": {
3
3
  "commander": "12.1.0",
4
- "puppeteer": "23.7.1"
4
+ "puppeteer": "23.9.0"
5
5
  },
6
6
  "type": "module"
7
7
  }
@@ -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
- assert False, "Timeout: " + error
50
+ raise AssertionError("Timeout: " + error)
50
51
  time.sleep(interval)
51
52
 
52
53
 
c2cwsgiutils/auth.py CHANGED
@@ -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" # nosec # noqa
16
- SECRET_ENV = "C2C_SECRET" # nosec # noqa
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" # nosec
24
- GITHUB_TOKEN_URL_ENV = "C2C_AUTH_GITHUB_TOKEN_URL" # nosec
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" # nosec # noqa
32
- GITHUB_CLIENT_SECRET_ENV = "C2C_AUTH_GITHUB_CLIENT_SECRET" # nosec # noqa
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" # nosec # noqa
40
- GITHUB_AUTH_SECRET_ENV = "C2C_AUTH_GITHUB_SECRET" # nosec # noqa
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) for _ in range(10) # nosec
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: # pragma: no cover
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" # nosec
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"),
c2cwsgiutils/db.py CHANGED
@@ -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("setup_session function is deprecated; use init and request.dbsession instead")
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("create_session function is deprecated; use init and request.dbsession instead")
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 _listeners # pylint: disable=import-outside-toplevel
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: # nosec # pylint: disable=broad-except
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
- else:
155
- return result
154
+ return result
156
155
 
157
156
 
158
157
  def _error(request: pyramid.request.Request) -> Any:
c2cwsgiutils/errors.py CHANGED
@@ -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 HTTPError, HTTPException, HTTPRedirection, HTTPSuccessful
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 binding as binded_session:
291
- with _PROMETHEUS_DB_SUMMARY.labels(
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
- result = binded_session.execute(
295
- sqlalchemy.text(
296
- "SELECT version_num FROM " # nosec
297
- f"{sqlalchemy.sql.quoted_name(version_schema, True)}."
298
- f"{sqlalchemy.sql.quoted_name(version_table, True)}"
299
- )
300
- ).fetchone()
301
- assert result is not None
302
- (actual_version,) = result
303
- _PROMETHEUS_ALEMBIC_VERSION.labels(
304
- version=actual_version, name=name, configuration=alembic_ini_path
305
- ).set(1)
306
- if actual_version != version_:
307
- raise Exception( # pylint: disable=broad-exception-raised
308
- f"Invalid alembic version (db: {actual_version}, code: {version_})"
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
- [pyramid.request.Request, requests.Response], Any
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
- if request.params["checks"] != "":
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 binding as session:
502
- with _PROMETHEUS_DB_SUMMARY.labels(
509
+ with (
510
+ binding as session,
511
+ _PROMETHEUS_DB_SUMMARY.labels(
503
512
  connection=binding.name(), check="database", configuration="<default>"
504
- ).time():
505
- return query_cb(session)
513
+ ).time(),
514
+ ):
515
+ return query_cb(session)
506
516
 
507
517
  return "db_engine_" + binding.name(), check
508
518
 
c2cwsgiutils/index.py CHANGED
@@ -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