tracepanel 0.0.1a1__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.
Files changed (75) hide show
  1. tracepanel-0.0.1a1/LICENSE +21 -0
  2. tracepanel-0.0.1a1/PKG-INFO +206 -0
  3. tracepanel-0.0.1a1/README.md +146 -0
  4. tracepanel-0.0.1a1/pyproject.toml +272 -0
  5. tracepanel-0.0.1a1/pyproject.toml.orig +246 -0
  6. tracepanel-0.0.1a1/tracepanel/__init__.py +10 -0
  7. tracepanel-0.0.1a1/tracepanel/__main__.py +3 -0
  8. tracepanel-0.0.1a1/tracepanel/_agent.py +19 -0
  9. tracepanel-0.0.1a1/tracepanel/_bootstrap/sitecustomize.py +25 -0
  10. tracepanel-0.0.1a1/tracepanel/_cli.py +156 -0
  11. tracepanel-0.0.1a1/tracepanel/_compat.py +17 -0
  12. tracepanel-0.0.1a1/tracepanel/_run.py +173 -0
  13. tracepanel-0.0.1a1/tracepanel/_setup.py +36 -0
  14. tracepanel-0.0.1a1/tracepanel/api.py +154 -0
  15. tracepanel-0.0.1a1/tracepanel/asgi/__init__.py +43 -0
  16. tracepanel-0.0.1a1/tracepanel/asgi/middleware.py +260 -0
  17. tracepanel-0.0.1a1/tracepanel/console/__init__.py +1 -0
  18. tracepanel-0.0.1a1/tracepanel/console/app.py +95 -0
  19. tracepanel-0.0.1a1/tracepanel/console/messages.py +27 -0
  20. tracepanel-0.0.1a1/tracepanel/console/proxy.py +84 -0
  21. tracepanel-0.0.1a1/tracepanel/console/terminal.py +73 -0
  22. tracepanel-0.0.1a1/tracepanel/console/widget.py +164 -0
  23. tracepanel-0.0.1a1/tracepanel/core/__init__.py +1 -0
  24. tracepanel-0.0.1a1/tracepanel/core/conf.py +264 -0
  25. tracepanel-0.0.1a1/tracepanel/core/context.py +111 -0
  26. tracepanel-0.0.1a1/tracepanel/core/errors.py +82 -0
  27. tracepanel-0.0.1a1/tracepanel/core/explain.py +144 -0
  28. tracepanel-0.0.1a1/tracepanel/core/frames.py +143 -0
  29. tracepanel-0.0.1a1/tracepanel/core/ids.py +24 -0
  30. tracepanel-0.0.1a1/tracepanel/core/model.py +154 -0
  31. tracepanel-0.0.1a1/tracepanel/core/patching.py +63 -0
  32. tracepanel-0.0.1a1/tracepanel/core/registry.py +81 -0
  33. tracepanel-0.0.1a1/tracepanel/core/runtime.py +57 -0
  34. tracepanel-0.0.1a1/tracepanel/core/services.py +104 -0
  35. tracepanel-0.0.1a1/tracepanel/core/sql.py +163 -0
  36. tracepanel-0.0.1a1/tracepanel/django/__init__.py +90 -0
  37. tracepanel-0.0.1a1/tracepanel/django/apps.py +17 -0
  38. tracepanel-0.0.1a1/tracepanel/django/auth.py +18 -0
  39. tracepanel-0.0.1a1/tracepanel/django/cache.py +85 -0
  40. tracepanel-0.0.1a1/tracepanel/django/channels.py +204 -0
  41. tracepanel-0.0.1a1/tracepanel/django/commands.py +49 -0
  42. tracepanel-0.0.1a1/tracepanel/django/console.py +49 -0
  43. tracepanel-0.0.1a1/tracepanel/django/drf.py +223 -0
  44. tracepanel-0.0.1a1/tracepanel/django/errors.py +17 -0
  45. tracepanel-0.0.1a1/tracepanel/django/explain.py +29 -0
  46. tracepanel-0.0.1a1/tracepanel/django/mail.py +105 -0
  47. tracepanel-0.0.1a1/tracepanel/django/middleware.py +158 -0
  48. tracepanel-0.0.1a1/tracepanel/django/ninja.py +154 -0
  49. tracepanel-0.0.1a1/tracepanel/django/services.py +50 -0
  50. tracepanel-0.0.1a1/tracepanel/django/signals.py +177 -0
  51. tracepanel-0.0.1a1/tracepanel/django/sql.py +43 -0
  52. tracepanel-0.0.1a1/tracepanel/django/structure.py +81 -0
  53. tracepanel-0.0.1a1/tracepanel/django/sync_to_async.py +34 -0
  54. tracepanel-0.0.1a1/tracepanel/django/tasks.py +174 -0
  55. tracepanel-0.0.1a1/tracepanel/django/transactions.py +132 -0
  56. tracepanel-0.0.1a1/tracepanel/django/users.py +145 -0
  57. tracepanel-0.0.1a1/tracepanel/django/widget.py +24 -0
  58. tracepanel-0.0.1a1/tracepanel/falcon/__init__.py +138 -0
  59. tracepanel-0.0.1a1/tracepanel/fastapi/__init__.py +16 -0
  60. tracepanel-0.0.1a1/tracepanel/flask/__init__.py +141 -0
  61. tracepanel-0.0.1a1/tracepanel/integrations/__init__.py +6 -0
  62. tracepanel-0.0.1a1/tracepanel/integrations/_tasks.py +35 -0
  63. tracepanel-0.0.1a1/tracepanel/integrations/celery.py +248 -0
  64. tracepanel-0.0.1a1/tracepanel/integrations/dramatiq.py +207 -0
  65. tracepanel-0.0.1a1/tracepanel/integrations/htmx.py +79 -0
  66. tracepanel-0.0.1a1/tracepanel/integrations/logging.py +115 -0
  67. tracepanel-0.0.1a1/tracepanel/integrations/otel.py +176 -0
  68. tracepanel-0.0.1a1/tracepanel/integrations/rq.py +170 -0
  69. tracepanel-0.0.1a1/tracepanel/integrations/sqlalchemy.py +213 -0
  70. tracepanel-0.0.1a1/tracepanel/integrations/strawberry.py +172 -0
  71. tracepanel-0.0.1a1/tracepanel/py.typed +0 -0
  72. tracepanel-0.0.1a1/tracepanel/storage/__init__.py +1 -0
  73. tracepanel-0.0.1a1/tracepanel/storage/agent.py +277 -0
  74. tracepanel-0.0.1a1/tracepanel/storage/transport.py +133 -0
  75. tracepanel-0.0.1a1/tracepanel/wsgi/__init__.py +181 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 DevRealm OÜ
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,206 @@
1
+ Metadata-Version: 2.4
2
+ Name: tracepanel
3
+ Version: 0.0.1a1
4
+ Summary: Traces and logs for Python apps: every request, task and command with its SQL and log lines, N+1 queries found
5
+ Keywords: debug toolbar,django,fastapi,flask,n+1,sql,tracing,profiling
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Environment :: Web Environment
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Framework :: FastAPI
12
+ Classifier: Framework :: Flask
13
+ Classifier: Framework :: Django
14
+ Classifier: Framework :: Django :: 5.2
15
+ Classifier: Framework :: Django :: 6.0
16
+ Classifier: Framework :: Django :: 6.1
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Programming Language :: Python :: 3.14
22
+ Classifier: Programming Language :: Python :: 3.15
23
+ Classifier: Topic :: Software Development :: Debuggers
24
+ Classifier: Typing :: Typed
25
+ Requires-Dist: tracepanel-agent==0.0.1a1 ; (platform_machine == 'aarch64' and sys_platform == 'linux') or (platform_machine == 'armv6l' and sys_platform == 'linux') or (platform_machine == 'armv7l' and sys_platform == 'linux') or (platform_machine == 'i686' and sys_platform == 'linux') or (platform_machine == 'ppc64le' and sys_platform == 'linux') or (platform_machine == 'riscv64' and sys_platform == 'linux') or (platform_machine == 's390x' and sys_platform == 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux') or (platform_machine == 'AMD64' and sys_platform == 'win32') or (platform_machine == 'ARM64' and sys_platform == 'win32') or (platform_machine == 'x86' and sys_platform == 'win32') or sys_platform == 'darwin'
26
+ Requires-Dist: celery>=5.3 ; extra == 'celery'
27
+ Requires-Dist: channels>=4.2 ; extra == 'channels'
28
+ Requires-Dist: django>=5.2 ; extra == 'django'
29
+ Requires-Dist: dramatiq>=1.17 ; extra == 'dramatiq'
30
+ Requires-Dist: djangorestframework>=3.15 ; extra == 'drf'
31
+ Requires-Dist: falcon>=4.0 ; extra == 'falcon'
32
+ Requires-Dist: fastapi>=0.142 ; extra == 'fastapi'
33
+ Requires-Dist: flask>=3.0 ; extra == 'flask'
34
+ Requires-Dist: django-ninja>=1.4 ; extra == 'ninja'
35
+ Requires-Dist: opentelemetry-sdk>=1.45 ; extra == 'otel'
36
+ Requires-Dist: rq>=2.0 ; extra == 'rq'
37
+ Requires-Dist: sqlalchemy>=2.0 ; extra == 'sqlalchemy'
38
+ Requires-Dist: starlette>=0.40 ; extra == 'starlette'
39
+ Requires-Dist: strawberry-graphql>=0.250 ; extra == 'strawberry'
40
+ Requires-Python: >=3.11
41
+ Project-URL: Homepage, https://github.com/tracepanel/tracepanel
42
+ Project-URL: Repository, https://github.com/tracepanel/tracepanel-python
43
+ Project-URL: Issues, https://github.com/tracepanel/tracepanel-python/issues
44
+ Project-URL: Changelog, https://github.com/tracepanel/tracepanel-python/blob/main/CHANGELOG.md
45
+ Provides-Extra: celery
46
+ Provides-Extra: channels
47
+ Provides-Extra: django
48
+ Provides-Extra: dramatiq
49
+ Provides-Extra: drf
50
+ Provides-Extra: falcon
51
+ Provides-Extra: fastapi
52
+ Provides-Extra: flask
53
+ Provides-Extra: ninja
54
+ Provides-Extra: otel
55
+ Provides-Extra: rq
56
+ Provides-Extra: sqlalchemy
57
+ Provides-Extra: starlette
58
+ Provides-Extra: strawberry
59
+ Description-Content-Type: text/markdown
60
+
61
+ # Tracepanel
62
+
63
+ **See what your app does on every request.** Tracepanel records each request,
64
+ background task and command of your Python app with its SQL queries, logs and
65
+ errors. It points out N+1 queries, duplicate queries and slow SQL, and names the
66
+ line of code to fix. You read it in a panel on your pages and in a console.
67
+
68
+ It runs while you develop, and everything stays on your machine.
69
+
70
+ ## Install
71
+
72
+ ```bash
73
+ pip install tracepanel
74
+ ```
75
+
76
+ Tracepanel is on only in development: when `DEBUG` is on, in a debug server,
77
+ or under `tracepanel run`. Add it to your app:
78
+
79
+ ```python
80
+ # Django: settings.py
81
+ INSTALLED_APPS += ["tracepanel.django"]
82
+ ```
83
+
84
+ ```python
85
+ # FastAPI
86
+ from fastapi import FastAPI
87
+
88
+ import tracepanel.fastapi
89
+
90
+ app = FastAPI(debug=True)
91
+ tracepanel.fastapi.install(app)
92
+ ```
93
+
94
+ ```python
95
+ # Flask, started with `flask run --debug`
96
+ from flask import Flask
97
+
98
+ import tracepanel.flask
99
+
100
+ app = Flask(__name__)
101
+ tracepanel.flask.install(app)
102
+ ```
103
+
104
+ Open a page of your app and click the badge in the corner. On a page that
105
+ loads each post's author in its own query, the panel shows
106
+ `SELECT auth_user ×50` marked N+1, the line of code that ran it, and the
107
+ `select_related()` that turns 50 queries into one. The console at
108
+ `/__tracepanel__/` holds every request, task and command the app ran.
109
+
110
+ Tracepanel also traces Celery, Dramatiq, RQ, SQLAlchemy, Strawberry, Django REST
111
+ framework, Django Ninja, Channels and htmx when they are installed. It reads the
112
+ log lines you write with `logging` and attaches each one to the request, task
113
+ or command that wrote it. Your logging configuration stays as it is.
114
+
115
+ For Django, `pip install django-tracepanel` installs the same package.
116
+
117
+ ## Run without changing your code
118
+
119
+ `tracepanel run` turns Tracepanel on for one command. The project stays as it
120
+ is:
121
+
122
+ ```bash
123
+ tracepanel run python manage.py runserver # Django
124
+ tracepanel run uvicorn app.main:app # FastAPI, Starlette
125
+ tracepanel run flask --app app run # Flask
126
+ tracepanel run gunicorn app:app # Falcon
127
+ tracepanel run celery -A app worker # a worker
128
+ ```
129
+
130
+ ## Configure
131
+
132
+ Every setting has a default. To change one, set it in one of these places, and
133
+ a later place wins:
134
+
135
+ 1. `tracepanel.toml`, or `[tool.tracepanel]` in `pyproject.toml`
136
+ 2. the `TRACEPANEL` dict in Django's settings
137
+ 3. a `TRACEPANEL_<NAME>` variable, such as `TRACEPANEL_SLOW_SQL_MS=50`
138
+
139
+ ```toml
140
+ # pyproject.toml
141
+ [tool.tracepanel]
142
+ slow_sql_ms = 50
143
+ n_plus_one_threshold = 5
144
+ ignore_paths = ["/health*", "/static/*"]
145
+ ```
146
+
147
+ `tracepanel config` prints each setting, its value and where it comes from.
148
+
149
+ ## Trace your own code
150
+
151
+ To add your own steps to a request or a task, or to trace a script or a
152
+ scheduled job:
153
+
154
+ ```python
155
+ import time
156
+
157
+ import tracepanel
158
+
159
+
160
+ @tracepanel.traced
161
+ def rebuild_index() -> None:
162
+ with tracepanel.span("index.load", source="db") as span:
163
+ time.sleep(0.01)
164
+ span.set("rows", 120)
165
+ tracepanel.event("index rebuilt", rows=120)
166
+
167
+
168
+ with tracepanel.trace("rebuild-index"):
169
+ tracepanel.set_attr("tenant", "acme", on_trace=True)
170
+ rebuild_index()
171
+ ```
172
+
173
+ `span()` adds a step to the current trace, and `@traced` does the same for a
174
+ function. `trace()` starts a new trace. Tracepanel stores keyword attributes
175
+ under `app.`, so `source` becomes `app.source`. SQL, logs and errors inside a
176
+ span belong to that span. Outside development these calls do nothing, so you
177
+ can leave them in.
178
+
179
+ ## Command line
180
+
181
+ | Command | What it does |
182
+ | --- | --- |
183
+ | `tracepanel run <command>` | runs a command with Tracepanel on |
184
+ | `tracepanel dev` | runs the agent in the foreground, with the console on http://127.0.0.1:8765/ |
185
+ | `tracepanel config` | prints the settings in effect and where each comes from |
186
+ | `tracepanel clear` | deletes every stored trace, log, query, email and issue |
187
+ | `tracepanel mcp` | gives an AI coding agent your traces over MCP |
188
+
189
+ ## Supported versions
190
+
191
+ | Python | Django |
192
+ | --- | --- |
193
+ | 3.11 | 5.2 |
194
+ | 3.12, 3.13, 3.14 | 5.2, 6.0, 6.1 |
195
+ | 3.15 | 6.1 |
196
+
197
+ ## Links
198
+
199
+ - [tracepanel](https://github.com/tracepanel/tracepanel): what Tracepanel finds,
200
+ how it works, privacy, and the agent this package installs
201
+ - [CHANGELOG.md](CHANGELOG.md): what changed in each version
202
+ - [CONTRIBUTING.md](CONTRIBUTING.md): developing this package
203
+
204
+ ## License
205
+
206
+ Licensed under the [MIT License](LICENSE).
@@ -0,0 +1,146 @@
1
+ # Tracepanel
2
+
3
+ **See what your app does on every request.** Tracepanel records each request,
4
+ background task and command of your Python app with its SQL queries, logs and
5
+ errors. It points out N+1 queries, duplicate queries and slow SQL, and names the
6
+ line of code to fix. You read it in a panel on your pages and in a console.
7
+
8
+ It runs while you develop, and everything stays on your machine.
9
+
10
+ ## Install
11
+
12
+ ```bash
13
+ pip install tracepanel
14
+ ```
15
+
16
+ Tracepanel is on only in development: when `DEBUG` is on, in a debug server,
17
+ or under `tracepanel run`. Add it to your app:
18
+
19
+ ```python
20
+ # Django: settings.py
21
+ INSTALLED_APPS += ["tracepanel.django"]
22
+ ```
23
+
24
+ ```python
25
+ # FastAPI
26
+ from fastapi import FastAPI
27
+
28
+ import tracepanel.fastapi
29
+
30
+ app = FastAPI(debug=True)
31
+ tracepanel.fastapi.install(app)
32
+ ```
33
+
34
+ ```python
35
+ # Flask, started with `flask run --debug`
36
+ from flask import Flask
37
+
38
+ import tracepanel.flask
39
+
40
+ app = Flask(__name__)
41
+ tracepanel.flask.install(app)
42
+ ```
43
+
44
+ Open a page of your app and click the badge in the corner. On a page that
45
+ loads each post's author in its own query, the panel shows
46
+ `SELECT auth_user ×50` marked N+1, the line of code that ran it, and the
47
+ `select_related()` that turns 50 queries into one. The console at
48
+ `/__tracepanel__/` holds every request, task and command the app ran.
49
+
50
+ Tracepanel also traces Celery, Dramatiq, RQ, SQLAlchemy, Strawberry, Django REST
51
+ framework, Django Ninja, Channels and htmx when they are installed. It reads the
52
+ log lines you write with `logging` and attaches each one to the request, task
53
+ or command that wrote it. Your logging configuration stays as it is.
54
+
55
+ For Django, `pip install django-tracepanel` installs the same package.
56
+
57
+ ## Run without changing your code
58
+
59
+ `tracepanel run` turns Tracepanel on for one command. The project stays as it
60
+ is:
61
+
62
+ ```bash
63
+ tracepanel run python manage.py runserver # Django
64
+ tracepanel run uvicorn app.main:app # FastAPI, Starlette
65
+ tracepanel run flask --app app run # Flask
66
+ tracepanel run gunicorn app:app # Falcon
67
+ tracepanel run celery -A app worker # a worker
68
+ ```
69
+
70
+ ## Configure
71
+
72
+ Every setting has a default. To change one, set it in one of these places, and
73
+ a later place wins:
74
+
75
+ 1. `tracepanel.toml`, or `[tool.tracepanel]` in `pyproject.toml`
76
+ 2. the `TRACEPANEL` dict in Django's settings
77
+ 3. a `TRACEPANEL_<NAME>` variable, such as `TRACEPANEL_SLOW_SQL_MS=50`
78
+
79
+ ```toml
80
+ # pyproject.toml
81
+ [tool.tracepanel]
82
+ slow_sql_ms = 50
83
+ n_plus_one_threshold = 5
84
+ ignore_paths = ["/health*", "/static/*"]
85
+ ```
86
+
87
+ `tracepanel config` prints each setting, its value and where it comes from.
88
+
89
+ ## Trace your own code
90
+
91
+ To add your own steps to a request or a task, or to trace a script or a
92
+ scheduled job:
93
+
94
+ ```python
95
+ import time
96
+
97
+ import tracepanel
98
+
99
+
100
+ @tracepanel.traced
101
+ def rebuild_index() -> None:
102
+ with tracepanel.span("index.load", source="db") as span:
103
+ time.sleep(0.01)
104
+ span.set("rows", 120)
105
+ tracepanel.event("index rebuilt", rows=120)
106
+
107
+
108
+ with tracepanel.trace("rebuild-index"):
109
+ tracepanel.set_attr("tenant", "acme", on_trace=True)
110
+ rebuild_index()
111
+ ```
112
+
113
+ `span()` adds a step to the current trace, and `@traced` does the same for a
114
+ function. `trace()` starts a new trace. Tracepanel stores keyword attributes
115
+ under `app.`, so `source` becomes `app.source`. SQL, logs and errors inside a
116
+ span belong to that span. Outside development these calls do nothing, so you
117
+ can leave them in.
118
+
119
+ ## Command line
120
+
121
+ | Command | What it does |
122
+ | --- | --- |
123
+ | `tracepanel run <command>` | runs a command with Tracepanel on |
124
+ | `tracepanel dev` | runs the agent in the foreground, with the console on http://127.0.0.1:8765/ |
125
+ | `tracepanel config` | prints the settings in effect and where each comes from |
126
+ | `tracepanel clear` | deletes every stored trace, log, query, email and issue |
127
+ | `tracepanel mcp` | gives an AI coding agent your traces over MCP |
128
+
129
+ ## Supported versions
130
+
131
+ | Python | Django |
132
+ | --- | --- |
133
+ | 3.11 | 5.2 |
134
+ | 3.12, 3.13, 3.14 | 5.2, 6.0, 6.1 |
135
+ | 3.15 | 6.1 |
136
+
137
+ ## Links
138
+
139
+ - [tracepanel](https://github.com/tracepanel/tracepanel): what Tracepanel finds,
140
+ how it works, privacy, and the agent this package installs
141
+ - [CHANGELOG.md](CHANGELOG.md): what changed in each version
142
+ - [CONTRIBUTING.md](CONTRIBUTING.md): developing this package
143
+
144
+ ## License
145
+
146
+ Licensed under the [MIT License](LICENSE).
@@ -0,0 +1,272 @@
1
+ [project]
2
+ name = "tracepanel"
3
+ version = "0.0.1a1"
4
+ description = "Traces and logs for Python apps: every request, task and command with its SQL and log lines, N+1 queries found"
5
+ readme = "README.md"
6
+ license = "MIT"
7
+ license-files = ["LICENSE"]
8
+ requires-python = ">=3.11"
9
+ dependencies = ['tracepanel-agent==0.0.1a1; (sys_platform == "linux" and (platform_machine == "x86_64" or platform_machine == "aarch64" or platform_machine == "armv7l" or platform_machine == "armv6l" or platform_machine == "i686" or platform_machine == "ppc64le" or platform_machine == "s390x" or platform_machine == "riscv64")) or sys_platform == "darwin" or (sys_platform == "win32" and (platform_machine == "AMD64" or platform_machine == "ARM64" or platform_machine == "x86"))']
10
+ keywords = [
11
+ "debug toolbar",
12
+ "django",
13
+ "fastapi",
14
+ "flask",
15
+ "n+1",
16
+ "sql",
17
+ "tracing",
18
+ "profiling",
19
+ ]
20
+ classifiers = [
21
+ "Development Status :: 3 - Alpha",
22
+ "Environment :: Web Environment",
23
+ "Intended Audience :: Developers",
24
+ "Framework :: FastAPI",
25
+ "Framework :: Flask",
26
+ "Framework :: Django",
27
+ "Framework :: Django :: 5.2",
28
+ "Framework :: Django :: 6.0",
29
+ "Framework :: Django :: 6.1",
30
+ "Programming Language :: Python :: 3",
31
+ "Programming Language :: Python :: 3.11",
32
+ "Programming Language :: Python :: 3.12",
33
+ "Programming Language :: Python :: 3.13",
34
+ "Programming Language :: Python :: 3.14",
35
+ "Programming Language :: Python :: 3.15",
36
+ "Topic :: Software Development :: Debuggers",
37
+ "Typing :: Typed",
38
+ ]
39
+
40
+ [project.optional-dependencies]
41
+ django = ["django>=5.2"]
42
+ celery = ["celery>=5.3"]
43
+ dramatiq = ["dramatiq>=1.17"]
44
+ rq = ["rq>=2.0"]
45
+ channels = ["channels>=4.2"]
46
+ strawberry = ["strawberry-graphql>=0.250"]
47
+ fastapi = ["fastapi>=0.142"]
48
+ starlette = ["starlette>=0.40"]
49
+ flask = ["flask>=3.0"]
50
+ falcon = ["falcon>=4.0"]
51
+ sqlalchemy = ["sqlalchemy>=2.0"]
52
+ ninja = ["django-ninja>=1.4"]
53
+ drf = ["djangorestframework>=3.15"]
54
+ otel = ["opentelemetry-sdk>=1.45"]
55
+
56
+ [project.scripts]
57
+ tracepanel = "tracepanel._cli:main"
58
+
59
+ [project.urls]
60
+ Homepage = "https://github.com/tracepanel/tracepanel"
61
+ Repository = "https://github.com/tracepanel/tracepanel-python"
62
+ Issues = "https://github.com/tracepanel/tracepanel-python/issues"
63
+ Changelog = "https://github.com/tracepanel/tracepanel-python/blob/main/CHANGELOG.md"
64
+
65
+ [dependency-groups]
66
+ celery = ["celery>=5.6.3"]
67
+ channels = [
68
+ "channels>=4.3.2",
69
+ "daphne>=4.2.3",
70
+ ]
71
+ dev = [
72
+ "django>=5.2",
73
+ "pytest",
74
+ "pytest-django",
75
+ "jsonschema",
76
+ "types-jsonschema",
77
+ "ruff>=0.16",
78
+ "pyrefly>=1.3",
79
+ "poethepoet>=0.48",
80
+ "django-stubs>=5.2",
81
+ "dirty-equals>=0.11",
82
+ "pyyaml>=6.0.3",
83
+ "types-pyyaml>=6.0.12.20260906",
84
+ "celery-types>=0.26.0",
85
+ "import-linter>=2.15",
86
+ ]
87
+ django-tasks = [
88
+ "django-tasks>=0.12.0",
89
+ "django-tasks-db>=0.13.0",
90
+ ]
91
+ postgres = ["psycopg[binary]>=3.2"]
92
+ strawberry = ["strawberry-graphql>=0.332.0"]
93
+ dramatiq = [
94
+ "dramatiq>=2.2.1",
95
+ "redis>=8.1.0",
96
+ ]
97
+ rq = [
98
+ "rq>=2.12.0",
99
+ "fakeredis>=2.39.0",
100
+ ]
101
+ fastapi = [
102
+ "fastapi>=0.142.4",
103
+ "httpx2>=2.13.1",
104
+ "sqlalchemy>=2.1.4",
105
+ ]
106
+ ninja = ["django-ninja>=1.7.1"]
107
+ drf = ["djangorestframework>=3.18.3"]
108
+ otel = ["opentelemetry-sdk>=1.45.1"]
109
+ flask = [
110
+ "flask>=3.1.3",
111
+ "flask-sqlalchemy>=3.1.1",
112
+ "sqlalchemy>=2.1.4",
113
+ ]
114
+ falcon = ["falcon>=4.2"]
115
+
116
+ [build-system]
117
+ requires = ["uv_build>=0.12,<0.13"]
118
+ build-backend = "uv_build"
119
+
120
+ [tool.uv.sources.tracepanel-agent]
121
+ path = "../tracepanel"
122
+
123
+ [tool.uv.build-backend]
124
+ module-name = "tracepanel"
125
+ module-root = ""
126
+
127
+ [tool.ruff]
128
+ line-length = 120
129
+ target-version = "py311"
130
+
131
+ [tool.ruff.lint]
132
+ select = ["ALL"]
133
+ ignore = [
134
+ "COM812",
135
+ "CPY",
136
+ "D1",
137
+ ]
138
+
139
+ [tool.ruff.lint.flake8-tidy-imports]
140
+ ban-relative-imports = "all"
141
+
142
+ [tool.ruff.lint.isort]
143
+ known-third-party = [
144
+ "celery",
145
+ "channels",
146
+ "strawberry",
147
+ "ninja",
148
+ "rest_framework",
149
+ "django",
150
+ "fastapi",
151
+ "flask",
152
+ "falcon",
153
+ "starlette",
154
+ "sqlalchemy",
155
+ "opentelemetry",
156
+ ]
157
+
158
+ [tool.ruff.lint.pydocstyle]
159
+ convention = "google"
160
+
161
+ [tool.ruff.lint.per-file-ignores]
162
+ "tests/**" = [
163
+ "S101",
164
+ "PLR2004",
165
+ "ARG001",
166
+ "ARG002",
167
+ "S105",
168
+ "S106",
169
+ ]
170
+ "**/migrations/**" = ["RUF012"]
171
+ "tracepanel/_cli.py" = ["T201"]
172
+ "tracepanel/_bootstrap/sitecustomize.py" = ["INP001"]
173
+ "scripts/*.py" = ["INP001"]
174
+ "scripts/bench.py" = [
175
+ "INP001",
176
+ "T201",
177
+ ]
178
+ "scripts/test_matrix.py" = [
179
+ "INP001",
180
+ "T201",
181
+ ]
182
+
183
+ [tool.poe.tasks.build]
184
+ help = "Build the wheel and sdist into dist/, and check what they hold"
185
+ sequence = [
186
+ "uv build",
187
+ "python scripts/check_dist.py",
188
+ ]
189
+ default_item_type = "cmd"
190
+
191
+ [tool.poe.tasks.test-matrix]
192
+ help = "Tests on every supported Python x Django pair, as CI runs them (scripts/test_matrix.py)"
193
+ cmd = "python scripts/test_matrix.py"
194
+
195
+ [tool.poe.tasks.bench]
196
+ help = "Overhead per request, memory over many requests (scripts/bench.py)"
197
+ cmd = "python scripts/bench.py"
198
+
199
+ [tool.poe.tasks.test]
200
+ help = "Run the test suite"
201
+ cmd = "pytest"
202
+
203
+ [tool.poe.tasks.fmt]
204
+ help = "Fix lint issues and format code"
205
+ sequence = [
206
+ "ruff check --fix .",
207
+ "ruff format .",
208
+ ]
209
+ default_item_type = "cmd"
210
+
211
+ [tool.poe.tasks.lint]
212
+ help = "Check linting, formatting, types, imports and the docs (runs every check, fails if any fails)"
213
+ sequence = [
214
+ "ruff check .",
215
+ "ruff format --check .",
216
+ "pyrefly check",
217
+ "lint-imports",
218
+ "python scripts/lint_docs.py",
219
+ ]
220
+ default_item_type = "cmd"
221
+ ignore_fail = "return_non_zero"
222
+
223
+ [tool.pytest.ini_options]
224
+ DJANGO_SETTINGS_MODULE = "tests.project.settings"
225
+ pythonpath = ["."]
226
+ django_debug_mode = true
227
+
228
+ [tool.pyrefly]
229
+ preset = "strict"
230
+ python-version = "3.11"
231
+ project-includes = [
232
+ "tracepanel",
233
+ "tests",
234
+ "scripts",
235
+ ]
236
+
237
+ [tool.importlinter]
238
+ root_package = "tracepanel"
239
+ include_external_packages = true
240
+
241
+ [[tool.importlinter.contracts]]
242
+ name = "Only the framework integrations (tracepanel.django, .fastapi, .flask, .falcon) import their framework"
243
+ type = "forbidden"
244
+ source_modules = [
245
+ "tracepanel.core",
246
+ "tracepanel.storage",
247
+ "tracepanel.console",
248
+ "tracepanel.integrations",
249
+ "tracepanel.api",
250
+ "tracepanel.asgi",
251
+ "tracepanel.wsgi",
252
+ ]
253
+ forbidden_modules = [
254
+ "django",
255
+ "channels",
256
+ "fastapi",
257
+ "starlette",
258
+ "flask",
259
+ "werkzeug",
260
+ "falcon",
261
+ ]
262
+
263
+ [[tool.importlinter.contracts]]
264
+ name = "Layers: the framework integration on top, the core at the bottom"
265
+ type = "layers"
266
+ layers = [
267
+ "tracepanel.django | tracepanel.fastapi | tracepanel.flask | tracepanel.falcon",
268
+ "tracepanel.asgi | tracepanel.wsgi",
269
+ "tracepanel.integrations | tracepanel.console | tracepanel.api",
270
+ "tracepanel.storage",
271
+ "tracepanel.core",
272
+ ]