c2cwsgiutils 6.1.0.dev105__py3-none-any.whl → 6.1.7.dev4__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 (56) hide show
  1. c2cwsgiutils/__init__.py +14 -11
  2. c2cwsgiutils/acceptance/__init__.py +2 -3
  3. c2cwsgiutils/acceptance/connection.py +1 -2
  4. c2cwsgiutils/acceptance/image.py +17 -11
  5. c2cwsgiutils/acceptance/package-lock.json +306 -213
  6. c2cwsgiutils/acceptance/package.json +2 -2
  7. c2cwsgiutils/acceptance/print.py +7 -3
  8. c2cwsgiutils/acceptance/utils.py +1 -3
  9. c2cwsgiutils/auth.py +27 -25
  10. c2cwsgiutils/broadcast/__init__.py +15 -16
  11. c2cwsgiutils/broadcast/interface.py +3 -3
  12. c2cwsgiutils/broadcast/local.py +1 -0
  13. c2cwsgiutils/broadcast/redis.py +13 -12
  14. c2cwsgiutils/client_info.py +19 -1
  15. c2cwsgiutils/coverage_setup.py +4 -3
  16. c2cwsgiutils/db.py +35 -41
  17. c2cwsgiutils/db_maintenance_view.py +13 -13
  18. c2cwsgiutils/debug/__init__.py +2 -2
  19. c2cwsgiutils/debug/_listeners.py +2 -7
  20. c2cwsgiutils/debug/_views.py +20 -12
  21. c2cwsgiutils/debug/utils.py +9 -9
  22. c2cwsgiutils/errors.py +13 -15
  23. c2cwsgiutils/health_check.py +24 -30
  24. c2cwsgiutils/index.py +34 -13
  25. c2cwsgiutils/loader.py +21 -2
  26. c2cwsgiutils/logging_view.py +12 -12
  27. c2cwsgiutils/models_graph.py +0 -1
  28. c2cwsgiutils/pretty_json.py +0 -1
  29. c2cwsgiutils/prometheus.py +1 -7
  30. c2cwsgiutils/pyramid.py +0 -1
  31. c2cwsgiutils/pyramid_logging.py +1 -1
  32. c2cwsgiutils/redis_stats.py +9 -9
  33. c2cwsgiutils/redis_utils.py +19 -18
  34. c2cwsgiutils/request_tracking/__init__.py +13 -13
  35. c2cwsgiutils/request_tracking/_sql.py +0 -1
  36. c2cwsgiutils/scripts/genversion.py +5 -5
  37. c2cwsgiutils/scripts/stats_db.py +19 -17
  38. c2cwsgiutils/scripts/test_print.py +5 -5
  39. c2cwsgiutils/sentry.py +55 -20
  40. c2cwsgiutils/services.py +2 -2
  41. c2cwsgiutils/setup_process.py +0 -1
  42. c2cwsgiutils/sql_profiler/__init__.py +5 -6
  43. c2cwsgiutils/sql_profiler/_impl.py +18 -17
  44. c2cwsgiutils/sqlalchemylogger/README.md +30 -13
  45. c2cwsgiutils/sqlalchemylogger/handlers.py +12 -11
  46. c2cwsgiutils/stats_pyramid/__init__.py +1 -5
  47. c2cwsgiutils/stats_pyramid/_db_spy.py +2 -2
  48. c2cwsgiutils/stats_pyramid/_pyramid_spy.py +12 -1
  49. c2cwsgiutils/templates/index.html.mako +4 -1
  50. c2cwsgiutils/version.py +11 -5
  51. {c2cwsgiutils-6.1.0.dev105.dist-info → c2cwsgiutils-6.1.7.dev4.dist-info}/LICENSE +1 -1
  52. {c2cwsgiutils-6.1.0.dev105.dist-info → c2cwsgiutils-6.1.7.dev4.dist-info}/METADATA +18 -6
  53. c2cwsgiutils-6.1.7.dev4.dist-info/RECORD +67 -0
  54. {c2cwsgiutils-6.1.0.dev105.dist-info → c2cwsgiutils-6.1.7.dev4.dist-info}/WHEEL +1 -1
  55. c2cwsgiutils-6.1.0.dev105.dist-info/RECORD +0 -67
  56. {c2cwsgiutils-6.1.0.dev105.dist-info → c2cwsgiutils-6.1.7.dev4.dist-info}/entry_points.txt +0 -0
@@ -2,22 +2,39 @@ This module is used to ship logging records to an SQL database.
2
2
 
3
3
  Currently only `sqlite` and `postgres_psycopg2` are fully supported.
4
4
 
5
- To add the logger in a pyramid ini file use something like:
5
+ To add the handler, setup it directly in your app's main function. You
6
+ can add it to an existing logger (setup in you `.ini` file),
7
+ or create a new logger by calling the `logging.getlogger` method.
6
8
 
9
+ ```python
10
+ import logging
11
+ from c2cwsgiutils.sqlalchemylogger.handlers import SQLAlchemyHandler
12
+
13
+ def _setup_sqlalchemy_logger():
14
+ """
15
+ Setup sqlalchemy logger.
16
+ """
17
+ logger = logging.getLogger("A_LOGGER")
18
+ handler = SQLAlchemyHandler(
19
+ sqlalchemy_url={
20
+ # "url": "sqlite:///logger_db.sqlite3",
21
+ "url": "postgresql://postgres:password@localhost:5432/test",
22
+ "tablename": "test",
23
+ "tableargs": {"schema": "xyz"},
24
+ },
25
+ does_not_contain_expression="curl",
26
+ )
27
+ logger.addHandler(handler)
28
+
29
+ def main(_, **settings):
30
+ _setup_sqlalchemy_logger ()
31
+ ...
7
32
  ```
8
- [handlers]
9
- keys = sqlalchemy_logger
10
-
11
- [handler_sqlalchemy_logger]
12
- class = c2cwsgiutils.sqlalchemylogger.handlers.SQLAlchemyHandler
13
- #args = ({'url':'sqlite:///logger_db.sqlite3','tablename':'test'},'curl')
14
- args = ({'url':'postgresql://postgres:password@localhost:5432/test','tablename':'test','tableargs': {'schema':'xyz'}},'curl')
15
- level = NOTSET
16
- formatter = generic
17
- propagate = 0
18
- ```
19
33
 
20
- if the credentials given in `args = ` section are sufficient, the handler will
34
+ Do not set up this sqlalchemy logger in you `.ini` file directly.
35
+ It won't work (multi process issue).
36
+
37
+ if the given credentials are sufficient, the handler will
21
38
  create the DB, schema and table it needs directly.
22
39
 
23
40
  In the above example the second parameter provided `'curl'` is a negative
@@ -14,7 +14,7 @@ from sqlalchemy_utils import create_database, database_exists
14
14
  from c2cwsgiutils.sqlalchemylogger._filters import ContainsExpression, DoesNotContainExpression
15
15
  from c2cwsgiutils.sqlalchemylogger._models import Base, create_log_class
16
16
 
17
- LOG = logging.getLogger(__name__)
17
+ _LOG = logging.getLogger(__name__)
18
18
 
19
19
 
20
20
  class SQLAlchemyHandler(logging.Handler):
@@ -30,28 +30,28 @@ class SQLAlchemyHandler(logging.Handler):
30
30
  contains_expression: str = "",
31
31
  ) -> None:
32
32
  super().__init__()
33
- # initialize DB session
33
+ # Initialize DB session
34
34
  self.engine = create_engine(sqlalchemy_url["url"])
35
- self.Log = create_log_class(
35
+ self.Log = create_log_class( # pylint: disable=invalid-name
36
36
  tablename=sqlalchemy_url.get("tablename", "logs"),
37
37
  tableargs=sqlalchemy_url.get("tableargs", None), # type: ignore
38
38
  )
39
39
  Base.metadata.bind = self.engine
40
40
  self.session = sessionmaker(bind=self.engine)() # noqa
41
- # initialize log queue
41
+ # Initialize log queue
42
42
  self.log_queue: Any = queue.Queue()
43
- # initialize a thread to process the logs Asynchronously
43
+ # Initialize a thread to process the logs Asynchronously
44
44
  self.condition = threading.Condition()
45
45
  self.processor_thread = threading.Thread(target=self._processor, daemon=True)
46
46
  self.processor_thread.start()
47
- # initialize filters
47
+ # Initialize filters
48
48
  if does_not_contain_expression:
49
49
  self.addFilter(DoesNotContainExpression(does_not_contain_expression))
50
50
  if contains_expression:
51
51
  self.addFilter(ContainsExpression(contains_expression))
52
52
 
53
53
  def _processor(self) -> None:
54
- LOG.debug("%s: starting processor thread", __name__)
54
+ _LOG.debug("%s: starting processor thread", __name__)
55
55
  while True:
56
56
  logs = []
57
57
  time_since_last = time.perf_counter()
@@ -70,7 +70,7 @@ class SQLAlchemyHandler(logging.Handler):
70
70
  ):
71
71
  self._write_logs(logs)
72
72
  break
73
- LOG.debug("%s: stopping processor thread", __name__)
73
+ _LOG.debug("%s: stopping processor thread", __name__)
74
74
 
75
75
  def _write_logs(self, logs: list[Any]) -> None:
76
76
  try:
@@ -85,12 +85,13 @@ class SQLAlchemyHandler(logging.Handler):
85
85
  except Exception as e: # pylint: disable=broad-except
86
86
  # if we really cannot commit the log to DB, do not lock the
87
87
  # thread and do not crash the application
88
- LOG.critical(e)
88
+ _LOG.critical(e)
89
89
  finally:
90
90
  self.session.expunge_all()
91
91
 
92
92
  def create_db(self) -> None:
93
- LOG.info("%s: creating new database", __name__)
93
+ """Create the database if it does not exist."""
94
+ _LOG.info("%s: creating new database", __name__)
94
95
  if not database_exists(self.engine.url):
95
96
  create_database(self.engine.url)
96
97
  # FIXME: we should not access directly the private __table_args__
@@ -101,7 +102,7 @@ class SQLAlchemyHandler(logging.Handler):
101
102
  with self.engine.begin() as connection:
102
103
  if not self.engine.dialect.has_schema(connection, self.Log.__table_args__["schema"]):
103
104
  connection.execute(
104
- sqlalchemy.schema.CreateSchema(self.Log.__table_args__["schema"]), # type: ignore
105
+ sqlalchemy.schema.CreateSchema(self.Log.__table_args__["schema"]),
105
106
  )
106
107
  Base.metadata.create_all(self.engine)
107
108
 
@@ -10,7 +10,6 @@ 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
-
14
13
  warnings.warn("init function is deprecated; use includeme instead")
15
14
  includeme(config)
16
15
 
@@ -20,17 +19,14 @@ def includeme(config: pyramid.config.Configurator) -> None:
20
19
  Initialize the whole stats pyramid module.
21
20
 
22
21
  Arguments:
23
-
24
22
  config: The Pyramid config
25
23
  """
26
-
27
24
  _pyramid_spy.init(config)
28
25
  init_db_spy()
29
26
 
30
27
 
31
28
  def init_db_spy() -> None:
32
29
  """Initialize the database spy."""
33
-
34
- from . import _db_spy
30
+ from . import _db_spy # pylint: disable=import-outside-toplevel
35
31
 
36
32
  _db_spy.init()
@@ -10,7 +10,7 @@ from sqlalchemy.orm import Session
10
10
 
11
11
  from c2cwsgiutils import prometheus
12
12
 
13
- LOG = logging.getLogger(__name__)
13
+ _LOG = logging.getLogger(__name__)
14
14
 
15
15
  _PROMETHEUS_DB_SUMMARY = prometheus_client.Summary(
16
16
  prometheus.build_metric_name("database"),
@@ -71,7 +71,7 @@ def _create_sqlalchemy_timer_cb(what: str) -> Callable[..., Any]:
71
71
 
72
72
  def after(*_args: Any, **_kwargs: Any) -> None:
73
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)
74
+ _LOG.debug("Execute statement '%s' in %d.", what, time.perf_counter() - start)
75
75
 
76
76
  return after
77
77
 
@@ -1,3 +1,4 @@
1
+ import logging
1
2
  import time
2
3
  from typing import Callable, Optional
3
4
 
@@ -9,6 +10,8 @@ from pyramid.httpexceptions import HTTPException
9
10
 
10
11
  from c2cwsgiutils import prometheus
11
12
 
13
+ _LOG = logging.getLogger(__name__)
14
+
12
15
  _PROMETHEUS_PYRAMID_ROUTES_SUMMARY = prometheus_client.Summary(
13
16
  prometheus.build_metric_name("pyramid_routes"),
14
17
  "Pyramid routes",
@@ -61,6 +64,15 @@ def _create_finished_cb(
61
64
  name = request.matched_route.name
62
65
  if kind == "route":
63
66
  _add_server_metric(request, "route", description=name)
67
+ if status >= 500:
68
+ _LOG.warning(
69
+ "Request %s %s %s route %s return status %s",
70
+ request.method,
71
+ request.path,
72
+ kind,
73
+ name,
74
+ status,
75
+ )
64
76
  measure.labels(
65
77
  method=request.method, route=name, status=status, group=str(status // 100 * 100)
66
78
  ).observe(time.process_time() - start)
@@ -86,7 +98,6 @@ def init(config: pyramid.config.Configurator) -> None: # pragma: nocover
86
98
  Subscribe to Pyramid events in order to get some stats on route time execution.
87
99
 
88
100
  Arguments:
89
-
90
101
  config: The Pyramid config
91
102
  """
92
103
  config.add_subscriber(_request_callback, pyramid.events.NewRequest)
@@ -24,7 +24,7 @@
24
24
  crossorigin="anonymous"
25
25
  referrerpolicy="no-referrer"
26
26
  />
27
- <title>c2cwsgiutils tools</title>
27
+ <title>C2C WSGI Utils tools</title>
28
28
  <style>
29
29
  body {
30
30
  margin-top: 0.5rem;
@@ -32,6 +32,9 @@
32
32
  button, p {
33
33
  margin-bottom: 0.5rem;
34
34
  }
35
+ .row > h2 {
36
+ margin-top: 1rem;
37
+ }
35
38
  </style>
36
39
  </head>
37
40
  <body>
c2cwsgiutils/version.py CHANGED
@@ -8,7 +8,7 @@ from typing import Optional, cast
8
8
  import prometheus_client
9
9
  import pyramid.config
10
10
 
11
- from c2cwsgiutils import config_utils, prometheus
11
+ from c2cwsgiutils import auth, config_utils, prometheus
12
12
 
13
13
  _VERSIONS_PATH = "/app/versions.json"
14
14
  _LOG = logging.getLogger(__name__)
@@ -41,17 +41,23 @@ def init(config: pyramid.config.Configurator) -> None:
41
41
  includeme(config)
42
42
 
43
43
 
44
+ class _View:
45
+ def __init__(self, versions: dict[str, dict[str, str]]) -> None:
46
+ self.versions = versions
47
+
48
+ def __call__(self, request: pyramid.request.Request) -> dict[str, dict[str, str]]:
49
+ auth.auth_view(request)
50
+ return self.versions
51
+
52
+
44
53
  def includeme(config: pyramid.config.Configurator) -> None:
45
54
  """Initialize the versions view."""
46
-
47
55
  if os.path.isfile(_VERSIONS_PATH):
48
56
  versions = _read_versions()
49
57
  config.add_route(
50
58
  "c2c_versions", config_utils.get_base_path(config) + r"/versions.json", request_method="GET"
51
59
  )
52
- config.add_view(
53
- lambda request: versions, route_name="c2c_versions", renderer="fast_json", http_cache=0
54
- )
60
+ config.add_view(_View(versions), route_name="c2c_versions", renderer="fast_json", http_cache=0)
55
61
  _LOG.info("Installed the /versions.json service")
56
62
  git_hash = versions["main"]["git_hash"]
57
63
 
@@ -1,4 +1,4 @@
1
- Copyright (c) 2015-2023, Camptocamp SA
1
+ Copyright (c) 2015-2025, Camptocamp SA
2
2
  All rights reserved.
3
3
 
4
4
  Redistribution and use in source and binary forms, with or without
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: c2cwsgiutils
3
- Version: 6.1.0.dev105
3
+ Version: 6.1.7.dev4
4
4
  Summary: Common utilities for Camptocamp WSGI applications
5
5
  Home-page: https://github.com/camptocamp/c2cwsgiutils
6
6
  License: BSD-2-Clause
7
7
  Keywords: geo,gis,sqlalchemy,orm,wsgi
8
8
  Author: Camptocamp
9
9
  Author-email: info@camptocamp.com
10
- Requires-Python: >=3.9
10
+ Requires-Python: >=3.10
11
11
  Classifier: Development Status :: 5 - Production/Stable
12
12
  Classifier: Environment :: Plugins
13
13
  Classifier: Framework :: Pyramid
@@ -17,10 +17,10 @@ Classifier: License :: OSI Approved :: BSD License
17
17
  Classifier: Operating System :: OS Independent
18
18
  Classifier: Programming Language :: Python
19
19
  Classifier: Programming Language :: Python :: 3
20
- Classifier: Programming Language :: Python :: 3.9
21
20
  Classifier: Programming Language :: Python :: 3.10
22
21
  Classifier: Programming Language :: Python :: 3.11
23
22
  Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Programming Language :: Python :: 3.13
24
24
  Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application
25
25
  Classifier: Typing :: Typed
26
26
  Provides-Extra: alembic
@@ -64,7 +64,7 @@ Description-Content-Type: text/markdown
64
64
 
65
65
  # Camptocamp WSGI utilities
66
66
 
67
- This is a Python 3 library (>=3.5) providing common tools for Camptocamp WSGI
67
+ This is a Python 3 library providing common tools for Camptocamp WSGI
68
68
  applications:
69
69
 
70
70
  - Provide prometheus metrics
@@ -725,11 +725,16 @@ A few other environment variables can be used to tune the info sent with each re
725
725
  - `SENTRY_CLIENT_IGNORE_EXCEPTIONS`: list (coma separated) of exceptions to ignore (defaults to SystemExit)
726
726
  - `SENTRY_TAG_...`: to add other custom tags
727
727
  - `SENTRY_LEVEL`: starting from what logging level to send events to Sentry (defaults to ERROR)
728
- - `SENTRY_TRACES_SAMPLE_RATE`: The percentage of events to send to sentry in order to compute the performance. Value between 0 and 1, default is 0.
728
+ - `SENTRY_TRACES_SAMPLE_RATE`: The percentage of events to send to sentry in order to compute the performance. Value between 0 and 1 (default is 0)
729
+ - `SENTRY_INTEGRATION_LOGGING`: If set to 0, the Sentry integration will not log anything (default is 1)
730
+ - `SENTRY_INTEGRATION_PYRAMID`: If set to 0, the Sentry integration with Pyramid will not be enabled (default is 1)
731
+ - `SENTRY_INTEGRATION_SQLALCHEMY`: If set to 0, the Sentry integration with SQLAlchemy will not be enabled (default is 1)
732
+ - `SENTRY_INTEGRATION_REDIS`: If set to 0, the Sentry integration with Redis will not be enabled (default is 1)
733
+ - `SENTRY_INTEGRATION_ASYNCIO`: If set to 0, the Sentry integration with asyncio will not be enabled (default is 1)
729
734
 
730
735
  # Developer info
731
736
 
732
- You will need `docker` (>=1.12.0), `docker-compose` (>=1.10.0) and
737
+ You will need `docker` (>=1.12.0), `docker compose` and
733
738
  `make` installed on the machine to play with this project.
734
739
  Check available versions of `docker-engine` with
735
740
  `apt-get policy docker-engine` and eventually force install the
@@ -758,6 +763,13 @@ To make a release:
758
763
  - Add the new branch name in the `.github/workflows/rebuild.yaml` and
759
764
  `.github/workflows/audit.yaml` files.
760
765
 
766
+ ## Pserve
767
+
768
+ Pserve will not set the headers in the environment then if you are behind a reverse proxy, you will have
769
+ wrong values in client information, you can force them by using the environment variables:
770
+ `C2CWSGIUTILS_FORCE_PROTO`, `C2CWSGIUTILS_FORCE_HOST` `C2CWSGIUTILS_FORCE_SERVER_NAME` and
771
+ `C2CWSGIUTILS_FORCE_REMOTE_ADDR`.
772
+
761
773
  ## Testing
762
774
 
763
775
  ### Screenshots
@@ -0,0 +1,67 @@
1
+ c2cwsgiutils/__init__.py,sha256=HVSc-4O8i2aB0ozEI4AI8Xsb-4S6fAwhl8uRhv-DsFg,4057
2
+ c2cwsgiutils/acceptance/__init__.py,sha256=TJA1yzmyPujkg80oj-LBj2ueOQVYL8HLW87pejWTIDY,1501
3
+ c2cwsgiutils/acceptance/connection.py,sha256=yqChhHBpYhQL0Cb7K8FqeP16jg1UtmxGAi6Tw1TXEbI,9783
4
+ c2cwsgiutils/acceptance/image.py,sha256=Wi4EXDTKZ-uyIIQFn8SpRpUTzbpj5LlCwSkLjcYRGTk,9269
5
+ c2cwsgiutils/acceptance/package-lock.json,sha256=uiNM1L8_IsK7G8A8f2qKpUF0za-tO6_RvgNN3cEDKwg,47777
6
+ c2cwsgiutils/acceptance/package.json,sha256=DiJUVhci1sP-qu71s3RzxcsF4GsZdo2ZOUeqX3148ss,101
7
+ c2cwsgiutils/acceptance/print.py,sha256=qdh6pqlHgkIjUCJxS3rcgpOV4fDk9RxFlkfH5aAwDsQ,2567
8
+ c2cwsgiutils/acceptance/screenshot.js,sha256=FAJYIWOLJFMm0MNggKzo3mIybtN-VtKLdMzPhQ9pO1g,2041
9
+ c2cwsgiutils/acceptance/utils.py,sha256=zLvWqqPLBGCzGAtmIqidao66BKmER_Du1AfKCEhoc-I,1892
10
+ c2cwsgiutils/auth.py,sha256=ljTUPYGpEkkDg6ifOegXS1Q1JlcRth0P5vbMCs7VK6k,9585
11
+ c2cwsgiutils/broadcast/__init__.py,sha256=mYiTVL34QkJkEjxURlDIE7bmwZaEPT9Lw9zMwbiVtL0,4470
12
+ c2cwsgiutils/broadcast/interface.py,sha256=AkDT_m0eXTQp3mmMLf9KRtpXnWoVhJpb_UNjCbHM-3I,665
13
+ c2cwsgiutils/broadcast/local.py,sha256=kQp6OWcRU-nx7uEBAXwdMum_rOz3LSj6fyL_R12QrMY,1139
14
+ c2cwsgiutils/broadcast/redis.py,sha256=xCcGSr7jr6QdFM-YZzFFaySQis1xKb0HqqbGR8qjSNM,5202
15
+ c2cwsgiutils/broadcast/utils.py,sha256=0fQZXPu3p_5LEJpGenJwiiMxECQjJhjZBjIkBk8h-ng,272
16
+ c2cwsgiutils/client_info.py,sha256=rvXQLyhma0kPoWQINwUzrxfG2gGIjQDNrxPUDRGJxpA,3916
17
+ c2cwsgiutils/config_utils.py,sha256=vkBu-3GQsE94NOBOvT5FE-Ij29EUrKnDsmdUdtu_yzo,1524
18
+ c2cwsgiutils/coverage_setup.py,sha256=BrdjYUmqYl1C-gHuKA7EI5gbQs8Dtdeb2eZKtzr-5L0,909
19
+ c2cwsgiutils/db.py,sha256=JT5F9Dqm2r0Jsh3w3CX79ngAUtakMLpf1secfN1nQnk,16106
20
+ c2cwsgiutils/db_maintenance_view.py,sha256=58F-p9drkhCI99GoLRPIqT5U-Pm8ckSSUEl-tNxMmjU,3088
21
+ c2cwsgiutils/debug/__init__.py,sha256=GkYNt2fU5PFykw9HmqPEwZrF2mTJumjSu54pp38EhOM,1325
22
+ c2cwsgiutils/debug/_listeners.py,sha256=-fk3KFeB_E4m_YFXJ5MfxuqfA1sWCje9p3FH_93WfXM,4248
23
+ c2cwsgiutils/debug/_views.py,sha256=EY-reJAs68wZu3D1DosNBE_DnY3vbD55k-jkCNOZ9MU,7751
24
+ c2cwsgiutils/debug/utils.py,sha256=sIKZHQ8empzxE2OI3h7Uce8cvv4O7AD1y_VYeZfLVCA,2320
25
+ c2cwsgiutils/errors.py,sha256=-hWLQ1qDlh9kn06-33U2c39BbOxuCvJIkBkdxriE5mo,6644
26
+ c2cwsgiutils/health_check.py,sha256=OhfPcApBht1qtBOX8e8pdeq3QwF4FbgGkofjqpl8GvQ,20068
27
+ c2cwsgiutils/index.py,sha256=zQTp2dlb50DZy0TZOPYDxJv84kivcYirswz7rFMbSDA,17988
28
+ c2cwsgiutils/loader.py,sha256=aDs_YOoiEc_vr94fnc3TjUklIGgIOBZdoYLAjQHgTpo,1393
29
+ c2cwsgiutils/logging_view.py,sha256=d0UkvYRGkVUMY9_vbjEzXmm8-6CCec2B43a3mJAqWyw,3370
30
+ c2cwsgiutils/models_graph.py,sha256=q5dW_gZ5iUZCzBya5Kpy57y9oqsG-rGi9AvrXCDgYqs,2679
31
+ c2cwsgiutils/pretty_json.py,sha256=WQlgNVeWPD_QMEjkNq5rFVGdFwQ7xDyICf0uxj0Hu2U,1697
32
+ c2cwsgiutils/profiler.py,sha256=3tIwoDSzOKQ06ug_U6j5VDR1BQ9auUOqdJRRLRhDoHw,739
33
+ c2cwsgiutils/prometheus.py,sha256=XV_SSm0nT09MD8EEl2a4xtd2busO3r--JyboU9OvWaQ,6576
34
+ c2cwsgiutils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
+ c2cwsgiutils/pyramid.py,sha256=MnVMskHMlJ4KQDjDR7CQdYaH70YXOtJ-1ThTPBqa03c,1387
36
+ c2cwsgiutils/pyramid_logging.py,sha256=M4XtWQZStreEoyC5qlwxcDDKCp4PZOr9SN05GnaYvvA,3732
37
+ c2cwsgiutils/redis_stats.py,sha256=8OTVRcElESgM6qjN944MOjoYRb0FGcQgo3JmDglfpPw,1632
38
+ c2cwsgiutils/redis_utils.py,sha256=02QoBGSjfBwKsWk-4DrXT8119HuUJuV_ezW7bc-Rv8s,4734
39
+ c2cwsgiutils/request_tracking/__init__.py,sha256=9Fp505q5zKjqfm9MuM7BDiYsx_pdg4vViNAr43OWYuk,4132
40
+ c2cwsgiutils/request_tracking/_sql.py,sha256=ZOQ3hD5z-WasfBzNig75fjrCvw4tGr1rhWOv97iLYws,572
41
+ c2cwsgiutils/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
42
+ c2cwsgiutils/scripts/genversion.py,sha256=lpGqU5wNSKdoOMDwVjFvWJVPEzdk0P8Tpfk7NLcrTok,1990
43
+ c2cwsgiutils/scripts/stats_db.py,sha256=kGCWBpG6gp_yDH3eZwEOujrvlyM0g97po6-EyjV8SXU,10413
44
+ c2cwsgiutils/scripts/test_print.py,sha256=NSXc0a2DZvKXjZYc2yr6oF72PCpeyL3GJthNFxGErEA,2101
45
+ c2cwsgiutils/sentry.py,sha256=su_t2SHxx_zK-gQfotmDbgbSdwTQdFvkgJnqcrQU7ps,6494
46
+ c2cwsgiutils/services.py,sha256=AxdiH2S8gfEQpOY36R4WqKtJ-3P4OXhx0srTm5G5070,1569
47
+ c2cwsgiutils/setup_process.py,sha256=VSiyVaQ65btIEBql1sBCZpOjCr0QQjRbcVDY2I7GbLM,3426
48
+ c2cwsgiutils/sql_profiler/__init__.py,sha256=2bh5s4xqPLUl7EPnm75R1RDKtc098PgZLHkwHGfS-94,907
49
+ c2cwsgiutils/sql_profiler/_impl.py,sha256=6qkXMhDGcheCDwOH09gFJDrtXRsngkvm29icZWZMtMI,3797
50
+ c2cwsgiutils/sqlalchemylogger/README.md,sha256=qXfyhGC4Kbt-Ye_geTPm_1InpclhthmKZpc66rqB4as,2018
51
+ c2cwsgiutils/sqlalchemylogger/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
+ c2cwsgiutils/sqlalchemylogger/_filters.py,sha256=OJQ9_WA-fd9fMZ7TUNFzHHTPI6msw2NVBl5RoeYFnGw,752
53
+ c2cwsgiutils/sqlalchemylogger/_models.py,sha256=A9SQ8AqUazCMemVjp5p_1x4bZG3LAYW9pOXT84FdNkE,1471
54
+ c2cwsgiutils/sqlalchemylogger/examples/example.py,sha256=n48dJdUi1FH1hfBMAbfHLGPSb1bOVD8pXMxXB57PnpQ,460
55
+ c2cwsgiutils/sqlalchemylogger/handlers.py,sha256=nr9-eQsZ5d0DHbtc4Ym0_faa7qg1dF44CsdoZtuuRZM,4878
56
+ c2cwsgiutils/static/favicon-16x16.png,sha256=LKk6RFvb3NlPIZdDfAodE8H9IN8KM6CMGnMx4vOHlUQ,887
57
+ c2cwsgiutils/static/favicon-32x32.png,sha256=i4ucx08zAZARd8e7JTMGK-gb5WcOmyuDN6IN4brsEOo,1216
58
+ c2cwsgiutils/stats_pyramid/__init__.py,sha256=alSRhpCa5Kh9JnMnR5XqcMqr5wyL8ogROprrfsIl_qU,786
59
+ c2cwsgiutils/stats_pyramid/_db_spy.py,sha256=A61t6VKIrRRIjbyZTldmAUl_Q3ZDVFYqyxjuntzmllc,2919
60
+ c2cwsgiutils/stats_pyramid/_pyramid_spy.py,sha256=mRiOmQXV9x8JjkGV4MsaC7sD3qO6dWUTog0bharLLD0,3517
61
+ c2cwsgiutils/templates/index.html.mako,sha256=cK8qGBDeQG5SiJJCfvL0oKpgacr7dPKx634AAQivmjA,1416
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,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.9.0
2
+ Generator: poetry-core 1.9.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,67 +0,0 @@
1
- c2cwsgiutils/__init__.py,sha256=YHZ6OY8BvFrZAoBpbEWmAZ-60nqDer_CKHgY-LSHAKs,3986
2
- c2cwsgiutils/acceptance/__init__.py,sha256=vjtpPfu0kbXUOYMx15Z8713IfPFZA9XnkUKkIFtVj_M,1500
3
- c2cwsgiutils/acceptance/connection.py,sha256=w478x_UiPNebOX-IC7UBgpSGbUYRZBjHsA-Vpqvtic0,9742
4
- c2cwsgiutils/acceptance/image.py,sha256=5dVng5TaCGMYDl-ajZ5WkZdxo7_y2b8Jk7eJZJhPUZ4,8769
5
- c2cwsgiutils/acceptance/package-lock.json,sha256=8LPXP_SEWSRAVNGPeS28bXsf6qqRUjtmeXgL3kAUtWM,45501
6
- c2cwsgiutils/acceptance/package.json,sha256=COQIxLJd3AKXwHSqvr4sseQaE0mgA9Wxg0gkc7uh_3Q,101
7
- c2cwsgiutils/acceptance/print.py,sha256=j5K1c2Kn0eEnhgdbZNBVkdscK02pQhtPIh6lJzHMJcM,2323
8
- c2cwsgiutils/acceptance/screenshot.js,sha256=FAJYIWOLJFMm0MNggKzo3mIybtN-VtKLdMzPhQ9pO1g,2041
9
- c2cwsgiutils/acceptance/utils.py,sha256=-NgLlG_oQj3P_ZiK293RG7ZHPumg0WrDwo_APOI3WG4,1851
10
- c2cwsgiutils/auth.py,sha256=xHUOHQf2UL6xnplbZBa4KObC7Fn7kR6tWsETo6h79-w,9453
11
- c2cwsgiutils/broadcast/__init__.py,sha256=5xxEhGnOJmq-bEbUUmNyvz_DAfrHG0ZNQgeTQFGYFCo,4361
12
- c2cwsgiutils/broadcast/interface.py,sha256=jE8BSy9N7xnPmq5U0m852sFFhx46c7Uo9SyFJTCde9o,636
13
- c2cwsgiutils/broadcast/local.py,sha256=24aIRdFOR2CXZfp_F2R_S1QW-yon3EyTM6TvljWVlP0,1083
14
- c2cwsgiutils/broadcast/redis.py,sha256=sxBsYZtMNXMOck6a_Mcb3QZjjW4lPTxnImTfL1vv14g,5085
15
- c2cwsgiutils/broadcast/utils.py,sha256=0fQZXPu3p_5LEJpGenJwiiMxECQjJhjZBjIkBk8h-ng,272
16
- c2cwsgiutils/client_info.py,sha256=RsC2yT7NcHQNICO3WQNXayHkqi0rC85AvI6qNRXFTWw,3028
17
- c2cwsgiutils/config_utils.py,sha256=vkBu-3GQsE94NOBOvT5FE-Ij29EUrKnDsmdUdtu_yzo,1524
18
- c2cwsgiutils/coverage_setup.py,sha256=fES0sdhFy6oaeOCuP1qjjm7PQL9l_O8rUKZhRvRBRwQ,839
19
- c2cwsgiutils/db.py,sha256=vDRxhmUy-hLs5EAfYFGUg0nzH0tiWWo5ZejpmdlutS4,16175
20
- c2cwsgiutils/db_maintenance_view.py,sha256=ejSNCv7vZIDjXctDTWTXEYTnUYFVVNIecFLeDlCkDBA,3076
21
- c2cwsgiutils/debug/__init__.py,sha256=80zdAZnE9cwgQW1odE2aOauIxYsG5CQpWvHPcslRue8,1239
22
- c2cwsgiutils/debug/_listeners.py,sha256=sXXHbPHQaSRMrzUC2ryiSDsBXuTdVbpQOxmMmhZ3n90,4378
23
- c2cwsgiutils/debug/_views.py,sha256=zUeIshxBshBrlTz0p1I1LUi6HiJBOAAiDPrlOJsziQA,7522
24
- c2cwsgiutils/debug/utils.py,sha256=TPlJC5qKeFnvbgq1xjlfrrRgDcV5kIR69IPJgNcIZQY,2311
25
- c2cwsgiutils/errors.py,sha256=xAJghvSBRH_KOQFcYrItGrCLIFVri60ohq_z1dyG63I,6725
26
- c2cwsgiutils/health_check.py,sha256=elVgCf2HQd7GpL7j4NEipb4crYl_pEYMZZP03x1xuYc,19978
27
- c2cwsgiutils/index.py,sha256=7kgL4U_SN8boNHpnpB18v4ofScp-fJunsbnHpxbWlow,16707
28
- c2cwsgiutils/loader.py,sha256=x_yHRTDzzlQ61fHonWnnG01xdqFuXpbGZMNN--tN25U,622
29
- c2cwsgiutils/logging_view.py,sha256=W6-dFTz00hLt6BGJ8V3-4ip4AdxTyPG2W5vQjIuKiQs,3357
30
- c2cwsgiutils/models_graph.py,sha256=laip8EdhI2hoGZVAotdrsgMwiNbwsJPjknKkRq1eEq0,2680
31
- c2cwsgiutils/pretty_json.py,sha256=f1-oecFX9hub1nD32mmZRjOTIxhV8bVSt3Meqw68sNU,1698
32
- c2cwsgiutils/profiler.py,sha256=3tIwoDSzOKQ06ug_U6j5VDR1BQ9auUOqdJRRLRhDoHw,739
33
- c2cwsgiutils/prometheus.py,sha256=ZjHMG0zIKKJaadNp6pkSjXVTLAQS9AjlNwBH8HNJnfY,6558
34
- c2cwsgiutils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
- c2cwsgiutils/pyramid.py,sha256=H-b5abZvxt9MkMFjyWOjWzPa02YRhZR6LDiMCaYLq5s,1388
36
- c2cwsgiutils/pyramid_logging.py,sha256=1PoEBzmCelAmLVSeyLeeYr87ZIi1g9_oisiwH6p-7P4,3731
37
- c2cwsgiutils/redis_stats.py,sha256=triLtzryGXJKvCUw4TreYpF22BpUKPdrMp30ZGKsXwU,1545
38
- c2cwsgiutils/redis_utils.py,sha256=OkgUqbZcuCa-LjcFXZ-cDN94dYi746P1FHRWExdYP8U,4615
39
- c2cwsgiutils/request_tracking/__init__.py,sha256=YHNVB6GaAu175qC1L9GOFu99W0Xnt4kMNZIMTc34P0M,4040
40
- c2cwsgiutils/request_tracking/_sql.py,sha256=47OtVn3g5QpCCWyl8w6V1xVjbf0ahrw4r9ijjRKXDz4,573
41
- c2cwsgiutils/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
42
- c2cwsgiutils/scripts/genversion.py,sha256=GKmD08-H83hiKqXxy4odABuWqD5gADs_YEzM3TzHxEA,1985
43
- c2cwsgiutils/scripts/stats_db.py,sha256=QNwtEKznCgOKg4ZsAFED9ISS-THgdwD2km_oVoII5XU,10317
44
- c2cwsgiutils/scripts/test_print.py,sha256=UeOZa7jTazgEq5BRJD6lq-u9K6G4movf-sOVKTEs1cQ,2096
45
- c2cwsgiutils/sentry.py,sha256=-IzACZWI7YNi-dWtNrYlhdTysm8gRVzJSqK94wg3maU,5031
46
- c2cwsgiutils/services.py,sha256=qz51oCZOC0Lj2_ig4UuHIm0ZZO3FfpFTxrXBWZ_oaNo,1567
47
- c2cwsgiutils/setup_process.py,sha256=Ia9mVYnjiNPt1n3ue8j3SqAoaJUwhDuFlfya2kEubJI,3427
48
- c2cwsgiutils/sql_profiler/__init__.py,sha256=_Zw5BO-0sN2tVbSwtyHwi8gkmhCtGW-F6agkENhYILM,877
49
- c2cwsgiutils/sql_profiler/_impl.py,sha256=bNK16vRBHnaNQo5JfSdT-nXZ8WBUUJ5BvtCrINg0Aws,3703
50
- c2cwsgiutils/sqlalchemylogger/README.md,sha256=WEyJSrBjedtX1FFrYiq4oMaWMt1fNxRkJYmJWnAoz3g,1552
51
- c2cwsgiutils/sqlalchemylogger/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
- c2cwsgiutils/sqlalchemylogger/_filters.py,sha256=OJQ9_WA-fd9fMZ7TUNFzHHTPI6msw2NVBl5RoeYFnGw,752
53
- c2cwsgiutils/sqlalchemylogger/_models.py,sha256=A9SQ8AqUazCMemVjp5p_1x4bZG3LAYW9pOXT84FdNkE,1471
54
- c2cwsgiutils/sqlalchemylogger/examples/example.py,sha256=n48dJdUi1FH1hfBMAbfHLGPSb1bOVD8pXMxXB57PnpQ,460
55
- c2cwsgiutils/sqlalchemylogger/handlers.py,sha256=Qul-Bebmxqt4KvFU4TqjUGnbmpAVBviF5pSV3duUqG0,4801
56
- c2cwsgiutils/static/favicon-16x16.png,sha256=LKk6RFvb3NlPIZdDfAodE8H9IN8KM6CMGnMx4vOHlUQ,887
57
- c2cwsgiutils/static/favicon-32x32.png,sha256=i4ucx08zAZARd8e7JTMGK-gb5WcOmyuDN6IN4brsEOo,1216
58
- c2cwsgiutils/stats_pyramid/__init__.py,sha256=7P10LjLv3c-ObEDGuYmRF_RFt7fRmO80ruqTGQAyC6w,747
59
- c2cwsgiutils/stats_pyramid/_db_spy.py,sha256=ZGRdrI17Bdl3mzaLjfPyAaEW3KK8Pikrgi-0WmH7zCs,2917
60
- c2cwsgiutils/stats_pyramid/_pyramid_spy.py,sha256=P212MGGl2VV_7UU4AXZA-rOuF7ouaONRklZwpas2wc8,3209
61
- c2cwsgiutils/templates/index.html.mako,sha256=Ey9ppHLe-eFGYXYPV5Z2WbMBSif86sYPiTviksnG7TI,1362
62
- c2cwsgiutils/version.py,sha256=z4of1DDr6J7PDw4AUOz31Gp63khgXf3JfiIaoWUM-9I,2870
63
- c2cwsgiutils-6.1.0.dev105.dist-info/LICENSE,sha256=rM6IWxociA3daRkXnNLYOxGndT5fbs3BfVZCA2Xgt-g,1304
64
- c2cwsgiutils-6.1.0.dev105.dist-info/METADATA,sha256=oe493srEHdNM9rxmpZ49TnWmUpJKyfh5KQC8M2s8ilY,33516
65
- c2cwsgiutils-6.1.0.dev105.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
66
- c2cwsgiutils-6.1.0.dev105.dist-info/entry_points.txt,sha256=ujgqMTL1awN9qDg8WXmrF7m0fgR-hslUM6zKH86pvy0,703
67
- c2cwsgiutils-6.1.0.dev105.dist-info/RECORD,,