c2cwsgiutils 6.1.7.dev4__py3-none-any.whl → 6.1.8__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.
@@ -152,50 +152,75 @@
152
152
  "license": "Apache-2.0"
153
153
  },
154
154
  "node_modules/bare-events": {
155
- "version": "2.5.0",
156
- "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.0.tgz",
157
- "integrity": "sha512-/E8dDe9dsbLyh2qrZ64PEPadOQ0F4gbl1sUJOrmph7xOiIxfY8vwab/4bFLh4Y88/Hk/ujKcrQKc+ps0mv873A==",
155
+ "version": "2.5.4",
156
+ "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.4.tgz",
157
+ "integrity": "sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==",
158
158
  "license": "Apache-2.0",
159
159
  "optional": true
160
160
  },
161
161
  "node_modules/bare-fs": {
162
- "version": "2.3.5",
163
- "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-2.3.5.tgz",
164
- "integrity": "sha512-SlE9eTxifPDJrT6YgemQ1WGFleevzwY+XAP1Xqgl56HtcrisC2CHCZ2tq6dBpcH2TnNxwUEUGhweo+lrQtYuiw==",
162
+ "version": "4.0.2",
163
+ "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.0.2.tgz",
164
+ "integrity": "sha512-S5mmkMesiduMqnz51Bfh0Et9EX0aTCJxhsI4bvzFFLs8Z1AV8RDHadfY5CyLwdoLHgXbNBEN1gQcbEtGwuvixw==",
165
165
  "license": "Apache-2.0",
166
166
  "optional": true,
167
167
  "dependencies": {
168
- "bare-events": "^2.0.0",
169
- "bare-path": "^2.0.0",
170
- "bare-stream": "^2.0.0"
168
+ "bare-events": "^2.5.4",
169
+ "bare-path": "^3.0.0",
170
+ "bare-stream": "^2.6.4"
171
+ },
172
+ "engines": {
173
+ "bare": ">=1.16.0"
174
+ },
175
+ "peerDependencies": {
176
+ "bare-buffer": "*"
177
+ },
178
+ "peerDependenciesMeta": {
179
+ "bare-buffer": {
180
+ "optional": true
181
+ }
171
182
  }
172
183
  },
173
184
  "node_modules/bare-os": {
174
- "version": "2.4.4",
175
- "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-2.4.4.tgz",
176
- "integrity": "sha512-z3UiI2yi1mK0sXeRdc4O1Kk8aOa/e+FNWZcTiPB/dfTWyLypuE99LibgRaQki914Jq//yAWylcAt+mknKdixRQ==",
185
+ "version": "3.6.1",
186
+ "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.6.1.tgz",
187
+ "integrity": "sha512-uaIjxokhFidJP+bmmvKSgiMzj2sV5GPHaZVAIktcxcpCyBFFWO+YlikVAdhmUo2vYFvFhOXIAlldqV29L8126g==",
177
188
  "license": "Apache-2.0",
178
- "optional": true
189
+ "optional": true,
190
+ "engines": {
191
+ "bare": ">=1.14.0"
192
+ }
179
193
  },
180
194
  "node_modules/bare-path": {
181
- "version": "2.1.3",
182
- "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-2.1.3.tgz",
183
- "integrity": "sha512-lh/eITfU8hrj9Ru5quUp0Io1kJWIk1bTjzo7JH1P5dWmQ2EL4hFUlfI8FonAhSlgIfhn63p84CDY/x+PisgcXA==",
195
+ "version": "3.0.0",
196
+ "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz",
197
+ "integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==",
184
198
  "license": "Apache-2.0",
185
199
  "optional": true,
186
200
  "dependencies": {
187
- "bare-os": "^2.1.0"
201
+ "bare-os": "^3.0.1"
188
202
  }
189
203
  },
190
204
  "node_modules/bare-stream": {
191
- "version": "2.3.0",
192
- "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.3.0.tgz",
193
- "integrity": "sha512-pVRWciewGUeCyKEuRxwv06M079r+fRjAQjBEK2P6OYGrO43O+Z0LrPZZEjlc4mB6C2RpZ9AxJ1s7NLEtOHO6eA==",
205
+ "version": "2.6.5",
206
+ "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.6.5.tgz",
207
+ "integrity": "sha512-jSmxKJNJmHySi6hC42zlZnq00rga4jjxcgNZjY9N5WlOe/iOoGRtdwGsHzQv2RlH2KOYMwGUXhf2zXd32BA9RA==",
194
208
  "license": "Apache-2.0",
195
209
  "optional": true,
196
210
  "dependencies": {
197
- "b4a": "^1.6.6",
198
- "streamx": "^2.20.0"
211
+ "streamx": "^2.21.0"
212
+ },
213
+ "peerDependencies": {
214
+ "bare-buffer": "*",
215
+ "bare-events": "*"
216
+ },
217
+ "peerDependenciesMeta": {
218
+ "bare-buffer": {
219
+ "optional": true
220
+ },
221
+ "bare-events": {
222
+ "optional": true
223
+ }
199
224
  }
200
225
  },
201
226
  "node_modules/base64-js": {
@@ -946,12 +971,6 @@
946
971
  "node": ">=18"
947
972
  }
948
973
  },
949
- "node_modules/queue-tick": {
950
- "version": "1.0.1",
951
- "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz",
952
- "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==",
953
- "license": "MIT"
954
- },
955
974
  "node_modules/require-directory": {
956
975
  "version": "2.1.1",
957
976
  "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
@@ -1037,13 +1056,12 @@
1037
1056
  "license": "BSD-3-Clause"
1038
1057
  },
1039
1058
  "node_modules/streamx": {
1040
- "version": "2.20.1",
1041
- "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.20.1.tgz",
1042
- "integrity": "sha512-uTa0mU6WUC65iUvzKH4X9hEdvSW7rbPxPtwfWiLMSj3qTdQbAiUboZTxauKfpFuGIGa1C2BYijZ7wgdUXICJhA==",
1059
+ "version": "2.22.0",
1060
+ "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.22.0.tgz",
1061
+ "integrity": "sha512-sLh1evHOzBy/iWRiR6d1zRcLao4gGZr3C1kzNz4fopCOKJb6xD9ub8Mpi9Mr1R6id5o43S+d93fI48UC5uM9aw==",
1043
1062
  "license": "MIT",
1044
1063
  "dependencies": {
1045
1064
  "fast-fifo": "^1.3.2",
1046
- "queue-tick": "^1.0.1",
1047
1065
  "text-decoder": "^1.1.0"
1048
1066
  },
1049
1067
  "optionalDependencies": {
@@ -1089,17 +1107,17 @@
1089
1107
  }
1090
1108
  },
1091
1109
  "node_modules/tar-fs": {
1092
- "version": "3.0.6",
1093
- "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.6.tgz",
1094
- "integrity": "sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==",
1110
+ "version": "3.0.9",
1111
+ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.9.tgz",
1112
+ "integrity": "sha512-XF4w9Xp+ZQgifKakjZYmFdkLoSWd34VGKcsTCwlNWM7QG3ZbaxnTsaBwnjFZqHRf/rROxaR8rXnbtwdvaDI+lA==",
1095
1113
  "license": "MIT",
1096
1114
  "dependencies": {
1097
1115
  "pump": "^3.0.0",
1098
1116
  "tar-stream": "^3.1.5"
1099
1117
  },
1100
1118
  "optionalDependencies": {
1101
- "bare-fs": "^2.1.1",
1102
- "bare-path": "^2.1.0"
1119
+ "bare-fs": "^4.0.1",
1120
+ "bare-path": "^3.0.0"
1103
1121
  }
1104
1122
  },
1105
1123
  "node_modules/tar-stream": {
c2cwsgiutils/db.py CHANGED
@@ -51,7 +51,7 @@ def setup_session(
51
51
  With an accompanying tween that switches between the master and the slave DB
52
52
  connection. Uses prefixed entries in the application's settings.
53
53
 
54
- The slave DB will be used for anything that is GET and OPTIONS queries. The master DB will be used for
54
+ The slave DB will be used for anything that is GET, HEAD and OPTIONS queries. The master DB will be used for
55
55
  all the other queries. You can tweak this behavior with the force_master and force_slave parameters.
56
56
  Those parameters are lists of regex that are going to be matched against "{VERB} {PATH}". Warning, the
57
57
  path includes the route_prefix.
@@ -107,7 +107,7 @@ def create_session(
107
107
  With an accompanying tween that switches between the master and the slave DB
108
108
  connection.
109
109
 
110
- The slave DB will be used for anything that is GET and OPTIONS queries. The master DB will be used for
110
+ The slave DB will be used for anything that is GET, HEAD and OPTIONS queries. The master DB will be used for
111
111
  all the other queries. You can tweak this behavior with the force_master and force_slave parameters.
112
112
  Those parameters are lists of regex that are going to be matched against "{VERB} {PATH}". Warning, the
113
113
  path includes the route_prefix.
@@ -178,7 +178,10 @@ def _add_tween(
178
178
  has_force_master = any(r.match(method_path) for r in master_paths)
179
179
  if FORCE_READONLY or (
180
180
  not has_force_master
181
- and (request.method in ("GET", "OPTIONS") or any(r.match(method_path) for r in slave_paths))
181
+ and (
182
+ request.method in ("GET", "HEAD", "OPTIONS")
183
+ or any(r.match(method_path) for r in slave_paths)
184
+ )
182
185
  ):
183
186
  _LOG.debug(
184
187
  "Using %s database for: %s",
@@ -246,7 +249,7 @@ class SessionFactory(_sessionmaker):
246
249
  if FORCE_READONLY or (
247
250
  not has_force_master
248
251
  and (
249
- request.method in ("GET", "OPTIONS")
252
+ request.method in ("GET", "OPTIONS", "HEAD")
250
253
  or any(r.match(method_path) for r in self.slave_paths)
251
254
  )
252
255
  ):
@@ -1,5 +1,6 @@
1
1
  """Every thing we needs to have the metrics in Prometheus."""
2
2
 
3
+ import logging
3
4
  import os
4
5
  import re
5
6
  from collections.abc import Generator, Iterable
@@ -11,10 +12,12 @@ import prometheus_client.metrics_core
11
12
  import prometheus_client.multiprocess
12
13
  import prometheus_client.registry
13
14
  import pyramid.config
15
+ import redis.exceptions
14
16
 
15
17
  from c2cwsgiutils import broadcast, redis_utils
16
18
  from c2cwsgiutils.debug.utils import dump_memory_maps
17
19
 
20
+ _LOG = logging.getLogger(__name__)
18
21
  _NUMBER_RE = re.compile(r"^[0-9]+$")
19
22
  MULTI_PROCESS_COLLECTOR_BROADCAST_CHANNELS = [
20
23
  "c2cwsgiutils_prometheus_collector_gc",
@@ -117,9 +120,12 @@ class MultiProcessCustomCollector(prometheus_client.registry.Collector):
117
120
  def collect(self) -> Generator[prometheus_client.core.Metric, None, None]:
118
121
  results: list[list[SerializedMetric]] = []
119
122
  for channel in MULTI_PROCESS_COLLECTOR_BROADCAST_CHANNELS:
120
- result = broadcast.broadcast(channel, expect_answers=True)
121
- if result is not None:
122
- results.extend(cast(Iterable[list[SerializedMetric]], result))
123
+ try:
124
+ result = broadcast.broadcast(channel, expect_answers=True)
125
+ if result is not None:
126
+ results.extend(cast(Iterable[list[SerializedMetric]], result))
127
+ except redis.exceptions.ConnectionError:
128
+ _LOG.error("Failed to get the metrics from the other processes")
123
129
  return _deserialize_collected_data(results)
124
130
 
125
131
 
@@ -15,7 +15,7 @@ _LOG = logging.getLogger(__name__)
15
15
  _PROMETHEUS_DB_SUMMARY = prometheus_client.Summary(
16
16
  prometheus.build_metric_name("database"),
17
17
  "Database requests",
18
- ["what"],
18
+ ["what", "engine"],
19
19
  unit="seconds",
20
20
  )
21
21
 
@@ -66,12 +66,14 @@ def _simplify_sql(sql: str) -> str:
66
66
  return re.sub(r"%\(\w+\)\w", "?", sql)
67
67
 
68
68
 
69
- def _create_sqlalchemy_timer_cb(what: str) -> Callable[..., Any]:
69
+ def _create_sqlalchemy_timer_cb(what: str, engine_name: str | None = None) -> Callable[..., Any]:
70
70
  start = time.perf_counter()
71
71
 
72
72
  def after(*_args: Any, **_kwargs: Any) -> None:
73
- _PROMETHEUS_DB_SUMMARY.labels({"query": what}).observe(time.perf_counter() - start)
74
- _LOG.debug("Execute statement '%s' in %d.", what, time.perf_counter() - start)
73
+ elapsed_time = time.perf_counter() - start
74
+ _PROMETHEUS_DB_SUMMARY.labels(what=what, engine=engine_name).observe(elapsed_time)
75
+ engine_suffix = f", on {engine_name}" if engine_name else ""
76
+ _LOG.debug("Execute statement '%s' in %.3f%ss.", what, elapsed_time, engine_suffix)
75
77
 
76
78
  return after
77
79
 
@@ -79,8 +81,12 @@ def _create_sqlalchemy_timer_cb(what: str) -> Callable[..., Any]:
79
81
  def _before_cursor_execute(
80
82
  conn: Connection, _cursor: Any, statement: str, _parameters: Any, _context: Any, _executemany: Any
81
83
  ) -> None:
84
+ engine_name = getattr(conn.engine, "c2c_name", None)
82
85
  sqlalchemy.event.listen(
83
- conn, "after_cursor_execute", _create_sqlalchemy_timer_cb(_simplify_sql(statement)), once=True
86
+ conn,
87
+ "after_cursor_execute",
88
+ _create_sqlalchemy_timer_cb(_simplify_sql(statement), engine_name),
89
+ once=True,
84
90
  )
85
91
 
86
92
 
@@ -19,8 +19,8 @@
19
19
  />
20
20
  <link
21
21
  rel="stylesheet"
22
- href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/css/bootstrap.min.css"
23
- integrity="sha512-jnSuA4Ss2PkkikSOLtYs8BlYIeeIK1h99ty4YfvRPAlzr377vr3CXDb7sb7eEEBYjDtcYj+AjBH3FLv5uSJuXg=="
22
+ href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.7/css/bootstrap.min.css"
23
+ integrity="sha512-fw7f+TcMjTb7bpbLJZlP8g2Y4XcCyFZW8uy8HsRZsH/SwbMw0plKHFHr99DN3l04VsYNwvzicUX/6qurvIxbxw=="
24
24
  crossorigin="anonymous"
25
25
  referrerpolicy="no-referrer"
26
26
  />
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: c2cwsgiutils
3
- Version: 6.1.7.dev4
3
+ Version: 6.1.8
4
4
  Summary: Common utilities for Camptocamp WSGI applications
5
5
  Home-page: https://github.com/camptocamp/c2cwsgiutils
6
6
  License: BSD-2-Clause
@@ -56,6 +56,7 @@ Requires-Dist: requests-oauthlib ; extra == "standard" or extra == "oauth2" or e
56
56
  Requires-Dist: scikit-image ; extra == "test-images"
57
57
  Requires-Dist: sentry-sdk ; extra == "standard" or extra == "sentry" or extra == "all"
58
58
  Requires-Dist: ujson
59
+ Requires-Dist: urllib3
59
60
  Requires-Dist: waitress ; extra == "dev" or extra == "all"
60
61
  Requires-Dist: zope.interface ; extra == "standard" or extra == "webserver" or extra == "all"
61
62
  Requires-Dist: zope.sqlalchemy ; extra == "standard" or extra == "webserver" or extra == "all"
@@ -2,7 +2,7 @@ c2cwsgiutils/__init__.py,sha256=HVSc-4O8i2aB0ozEI4AI8Xsb-4S6fAwhl8uRhv-DsFg,4057
2
2
  c2cwsgiutils/acceptance/__init__.py,sha256=TJA1yzmyPujkg80oj-LBj2ueOQVYL8HLW87pejWTIDY,1501
3
3
  c2cwsgiutils/acceptance/connection.py,sha256=yqChhHBpYhQL0Cb7K8FqeP16jg1UtmxGAi6Tw1TXEbI,9783
4
4
  c2cwsgiutils/acceptance/image.py,sha256=Wi4EXDTKZ-uyIIQFn8SpRpUTzbpj5LlCwSkLjcYRGTk,9269
5
- c2cwsgiutils/acceptance/package-lock.json,sha256=uiNM1L8_IsK7G8A8f2qKpUF0za-tO6_RvgNN3cEDKwg,47777
5
+ c2cwsgiutils/acceptance/package-lock.json,sha256=AH-kvpzij3RePKw75pATymZsRtpE_nK_3zbRktfLrNY,47966
6
6
  c2cwsgiutils/acceptance/package.json,sha256=DiJUVhci1sP-qu71s3RzxcsF4GsZdo2ZOUeqX3148ss,101
7
7
  c2cwsgiutils/acceptance/print.py,sha256=qdh6pqlHgkIjUCJxS3rcgpOV4fDk9RxFlkfH5aAwDsQ,2567
8
8
  c2cwsgiutils/acceptance/screenshot.js,sha256=FAJYIWOLJFMm0MNggKzo3mIybtN-VtKLdMzPhQ9pO1g,2041
@@ -16,7 +16,7 @@ c2cwsgiutils/broadcast/utils.py,sha256=0fQZXPu3p_5LEJpGenJwiiMxECQjJhjZBjIkBk8h-
16
16
  c2cwsgiutils/client_info.py,sha256=rvXQLyhma0kPoWQINwUzrxfG2gGIjQDNrxPUDRGJxpA,3916
17
17
  c2cwsgiutils/config_utils.py,sha256=vkBu-3GQsE94NOBOvT5FE-Ij29EUrKnDsmdUdtu_yzo,1524
18
18
  c2cwsgiutils/coverage_setup.py,sha256=BrdjYUmqYl1C-gHuKA7EI5gbQs8Dtdeb2eZKtzr-5L0,909
19
- c2cwsgiutils/db.py,sha256=JT5F9Dqm2r0Jsh3w3CX79ngAUtakMLpf1secfN1nQnk,16106
19
+ c2cwsgiutils/db.py,sha256=zdlZ81hHCuPCdO7WoX5dM46NjZnvebyl9-DHf6oV8t8,16192
20
20
  c2cwsgiutils/db_maintenance_view.py,sha256=58F-p9drkhCI99GoLRPIqT5U-Pm8ckSSUEl-tNxMmjU,3088
21
21
  c2cwsgiutils/debug/__init__.py,sha256=GkYNt2fU5PFykw9HmqPEwZrF2mTJumjSu54pp38EhOM,1325
22
22
  c2cwsgiutils/debug/_listeners.py,sha256=-fk3KFeB_E4m_YFXJ5MfxuqfA1sWCje9p3FH_93WfXM,4248
@@ -30,7 +30,7 @@ c2cwsgiutils/logging_view.py,sha256=d0UkvYRGkVUMY9_vbjEzXmm8-6CCec2B43a3mJAqWyw,
30
30
  c2cwsgiutils/models_graph.py,sha256=q5dW_gZ5iUZCzBya5Kpy57y9oqsG-rGi9AvrXCDgYqs,2679
31
31
  c2cwsgiutils/pretty_json.py,sha256=WQlgNVeWPD_QMEjkNq5rFVGdFwQ7xDyICf0uxj0Hu2U,1697
32
32
  c2cwsgiutils/profiler.py,sha256=3tIwoDSzOKQ06ug_U6j5VDR1BQ9auUOqdJRRLRhDoHw,739
33
- c2cwsgiutils/prometheus.py,sha256=XV_SSm0nT09MD8EEl2a4xtd2busO3r--JyboU9OvWaQ,6576
33
+ c2cwsgiutils/prometheus.py,sha256=5oNG9UzTxiyE_UdLV70PuPs-NqrvLWfvdYb82KC0JT8,6813
34
34
  c2cwsgiutils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
35
  c2cwsgiutils/pyramid.py,sha256=MnVMskHMlJ4KQDjDR7CQdYaH70YXOtJ-1ThTPBqa03c,1387
36
36
  c2cwsgiutils/pyramid_logging.py,sha256=M4XtWQZStreEoyC5qlwxcDDKCp4PZOr9SN05GnaYvvA,3732
@@ -56,12 +56,12 @@ c2cwsgiutils/sqlalchemylogger/handlers.py,sha256=nr9-eQsZ5d0DHbtc4Ym0_faa7qg1dF4
56
56
  c2cwsgiutils/static/favicon-16x16.png,sha256=LKk6RFvb3NlPIZdDfAodE8H9IN8KM6CMGnMx4vOHlUQ,887
57
57
  c2cwsgiutils/static/favicon-32x32.png,sha256=i4ucx08zAZARd8e7JTMGK-gb5WcOmyuDN6IN4brsEOo,1216
58
58
  c2cwsgiutils/stats_pyramid/__init__.py,sha256=alSRhpCa5Kh9JnMnR5XqcMqr5wyL8ogROprrfsIl_qU,786
59
- c2cwsgiutils/stats_pyramid/_db_spy.py,sha256=A61t6VKIrRRIjbyZTldmAUl_Q3ZDVFYqyxjuntzmllc,2919
59
+ c2cwsgiutils/stats_pyramid/_db_spy.py,sha256=T6q26_6Q-ObjXPNUip5TsX-YkBl11v8vfFL1_9m_dHw,3180
60
60
  c2cwsgiutils/stats_pyramid/_pyramid_spy.py,sha256=mRiOmQXV9x8JjkGV4MsaC7sD3qO6dWUTog0bharLLD0,3517
61
- c2cwsgiutils/templates/index.html.mako,sha256=cK8qGBDeQG5SiJJCfvL0oKpgacr7dPKx634AAQivmjA,1416
61
+ c2cwsgiutils/templates/index.html.mako,sha256=Yqf6xkq-RtlUnHBAmJFMCJO_XwqGVDQfSjOTx3p70_o,1416
62
62
  c2cwsgiutils/version.py,sha256=1ghPu-aKMJdfCSUrxgBENNqNQ-7JMKJr6tS14dDmW4Q,3110
63
- c2cwsgiutils-6.1.7.dev4.dist-info/LICENSE,sha256=6bEOU0n7ued3SA-DQCsHQaACONMMRzGHmH5XhDVeD-U,1304
64
- c2cwsgiutils-6.1.7.dev4.dist-info/METADATA,sha256=bNxv5REJhQ1RiSYrsuk-h7s28UfeJTZIIuoFWUXfHO0,34401
65
- c2cwsgiutils-6.1.7.dev4.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
66
- c2cwsgiutils-6.1.7.dev4.dist-info/entry_points.txt,sha256=ujgqMTL1awN9qDg8WXmrF7m0fgR-hslUM6zKH86pvy0,703
67
- c2cwsgiutils-6.1.7.dev4.dist-info/RECORD,,
63
+ c2cwsgiutils-6.1.8.dist-info/LICENSE,sha256=6bEOU0n7ued3SA-DQCsHQaACONMMRzGHmH5XhDVeD-U,1304
64
+ c2cwsgiutils-6.1.8.dist-info/METADATA,sha256=KQWTZJdjQ56u2O2RRQOqqYPMd9IJEX9-k27F2IdrC9g,34419
65
+ c2cwsgiutils-6.1.8.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
66
+ c2cwsgiutils-6.1.8.dist-info/entry_points.txt,sha256=ujgqMTL1awN9qDg8WXmrF7m0fgR-hslUM6zKH86pvy0,703
67
+ c2cwsgiutils-6.1.8.dist-info/RECORD,,