python-surveyor 0.3.0__tar.gz → 0.4.0__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.
- {python_surveyor-0.3.0/python_surveyor.egg-info → python_surveyor-0.4.0}/PKG-INFO +3 -1
- {python_surveyor-0.3.0 → python_surveyor-0.4.0}/pyproject.toml +3 -1
- {python_surveyor-0.3.0 → python_surveyor-0.4.0/python_surveyor.egg-info}/PKG-INFO +3 -1
- {python_surveyor-0.3.0 → python_surveyor-0.4.0}/python_surveyor.egg-info/requires.txt +2 -0
- {python_surveyor-0.3.0 → python_surveyor-0.4.0}/tests/test_optional_params.py +147 -0
- {python_surveyor-0.3.0 → python_surveyor-0.4.0}/LICENSE +0 -0
- {python_surveyor-0.3.0 → python_surveyor-0.4.0}/README.md +0 -0
- {python_surveyor-0.3.0 → python_surveyor-0.4.0}/python_surveyor/__init__.py +0 -0
- {python_surveyor-0.3.0 → python_surveyor-0.4.0}/python_surveyor/__main__.py +0 -0
- {python_surveyor-0.3.0 → python_surveyor-0.4.0}/python_surveyor/cli.py +0 -0
- {python_surveyor-0.3.0 → python_surveyor-0.4.0}/python_surveyor/model.py +0 -0
- {python_surveyor-0.3.0 → python_surveyor-0.4.0}/python_surveyor/report.py +0 -0
- {python_surveyor-0.3.0 → python_surveyor-0.4.0}/python_surveyor/scanner.py +0 -0
- {python_surveyor-0.3.0 → python_surveyor-0.4.0}/python_surveyor.egg-info/SOURCES.txt +0 -0
- {python_surveyor-0.3.0 → python_surveyor-0.4.0}/python_surveyor.egg-info/dependency_links.txt +0 -0
- {python_surveyor-0.3.0 → python_surveyor-0.4.0}/python_surveyor.egg-info/entry_points.txt +0 -0
- {python_surveyor-0.3.0 → python_surveyor-0.4.0}/python_surveyor.egg-info/top_level.txt +0 -0
- {python_surveyor-0.3.0 → python_surveyor-0.4.0}/setup.cfg +0 -0
- {python_surveyor-0.3.0 → python_surveyor-0.4.0}/tests/test_broad_except.py +0 -0
- {python_surveyor-0.3.0 → python_surveyor-0.4.0}/tests/test_cli.py +0 -0
- {python_surveyor-0.3.0 → python_surveyor-0.4.0}/tests/test_fixture_naming.py +0 -0
- {python_surveyor-0.3.0 → python_surveyor-0.4.0}/tests/test_future_annotations.py +0 -0
- {python_surveyor-0.3.0 → python_surveyor-0.4.0}/tests/test_nontoplevel_imports.py +0 -0
- {python_surveyor-0.3.0 → python_surveyor-0.4.0}/tests/test_scanner.py +0 -0
- {python_surveyor-0.3.0 → python_surveyor-0.4.0}/tests/test_suppressions.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-surveyor
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Use python introspection to survey source code for final LLM judgement
|
|
5
5
|
Author: Dave Cunningham
|
|
6
6
|
License-Expression: MIT
|
|
@@ -9,6 +9,8 @@ Requires-Python: >=3.12
|
|
|
9
9
|
License-File: LICENSE
|
|
10
10
|
Requires-Dist: click>=8.1.0
|
|
11
11
|
Provides-Extra: dev
|
|
12
|
+
Requires-Dist: fastapi>=0.115.0; extra == "dev"
|
|
13
|
+
Requires-Dist: flask>=3.0.0; extra == "dev"
|
|
12
14
|
Requires-Dist: pyright==1.1.411; extra == "dev"
|
|
13
15
|
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
14
16
|
Requires-Dist: pytest-cov; extra == "dev"
|
|
@@ -8,7 +8,7 @@ include = ["python_surveyor"]
|
|
|
8
8
|
|
|
9
9
|
[project]
|
|
10
10
|
name = "python-surveyor"
|
|
11
|
-
version = "0.
|
|
11
|
+
version = "0.4.0"
|
|
12
12
|
description = "Use python introspection to survey source code for final LLM judgement"
|
|
13
13
|
requires-python = ">=3.12"
|
|
14
14
|
license = "MIT"
|
|
@@ -24,6 +24,8 @@ dependencies = [
|
|
|
24
24
|
|
|
25
25
|
[project.optional-dependencies]
|
|
26
26
|
dev = [
|
|
27
|
+
"fastapi>=0.115.0",
|
|
28
|
+
"flask>=3.0.0",
|
|
27
29
|
"pyright==1.1.411",
|
|
28
30
|
"pytest>=8.0.0",
|
|
29
31
|
"pytest-cov",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-surveyor
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Use python introspection to survey source code for final LLM judgement
|
|
5
5
|
Author: Dave Cunningham
|
|
6
6
|
License-Expression: MIT
|
|
@@ -9,6 +9,8 @@ Requires-Python: >=3.12
|
|
|
9
9
|
License-File: LICENSE
|
|
10
10
|
Requires-Dist: click>=8.1.0
|
|
11
11
|
Provides-Extra: dev
|
|
12
|
+
Requires-Dist: fastapi>=0.115.0; extra == "dev"
|
|
13
|
+
Requires-Dist: flask>=3.0.0; extra == "dev"
|
|
12
14
|
Requires-Dist: pyright==1.1.411; extra == "dev"
|
|
13
15
|
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
14
16
|
Requires-Dist: pytest-cov; extra == "dev"
|
|
@@ -140,3 +140,150 @@ def test_signature_elides_with_multiline_def(make_source_file, empty_corpus):
|
|
|
140
140
|
excerpt = findings[0].excerpts[0]
|
|
141
141
|
assert excerpt.start_line == 4
|
|
142
142
|
assert excerpt.end_line == 5
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
# --- FastAPI / Flask route-handler exclusion ------------------------------
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def test_fastapi_app_get_handler_excluded(make_source_file, empty_corpus):
|
|
149
|
+
source = (
|
|
150
|
+
"from fastapi import FastAPI\n"
|
|
151
|
+
"app = FastAPI()\n"
|
|
152
|
+
"@app.get('/x')\n"
|
|
153
|
+
"def handler(q: str = 'a'):\n"
|
|
154
|
+
" return q\n"
|
|
155
|
+
)
|
|
156
|
+
source_file = make_source_file("a.py", source)
|
|
157
|
+
findings = run(source_file, empty_corpus)
|
|
158
|
+
assert findings == []
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def test_fastapi_router_post_handler_excluded(make_source_file, empty_corpus):
|
|
162
|
+
source = (
|
|
163
|
+
"from fastapi import APIRouter as AR\n"
|
|
164
|
+
"router = AR()\n"
|
|
165
|
+
"@router.post('/x')\n"
|
|
166
|
+
"async def create(q: int = 0):\n"
|
|
167
|
+
" return q\n"
|
|
168
|
+
)
|
|
169
|
+
source_file = make_source_file("a.py", source)
|
|
170
|
+
findings = run(source_file, empty_corpus)
|
|
171
|
+
assert findings == []
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def test_fastapi_module_import_form_excluded(make_source_file, empty_corpus):
|
|
175
|
+
source = (
|
|
176
|
+
"import fastapi\n"
|
|
177
|
+
"app = fastapi.FastAPI()\n"
|
|
178
|
+
"@app.get('/x')\n"
|
|
179
|
+
"def handler(q: str = 'a'):\n"
|
|
180
|
+
" return q\n"
|
|
181
|
+
)
|
|
182
|
+
source_file = make_source_file("a.py", source)
|
|
183
|
+
findings = run(source_file, empty_corpus)
|
|
184
|
+
assert findings == []
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def test_fastapi_api_route_handler_excluded(make_source_file, empty_corpus):
|
|
188
|
+
source = (
|
|
189
|
+
"from fastapi import FastAPI\n"
|
|
190
|
+
"app = FastAPI()\n"
|
|
191
|
+
"@app.api_route('/x', methods=['GET'])\n"
|
|
192
|
+
"def handler(q: str = 'a'):\n"
|
|
193
|
+
" return q\n"
|
|
194
|
+
)
|
|
195
|
+
source_file = make_source_file("a.py", source)
|
|
196
|
+
findings = run(source_file, empty_corpus)
|
|
197
|
+
assert findings == []
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def test_fastapi_websocket_handler_excluded(make_source_file, empty_corpus):
|
|
201
|
+
source = (
|
|
202
|
+
"from fastapi import FastAPI\n"
|
|
203
|
+
"app = FastAPI()\n"
|
|
204
|
+
"@app.websocket('/ws')\n"
|
|
205
|
+
"async def ws_handler(q: str = 'a'):\n"
|
|
206
|
+
" pass\n"
|
|
207
|
+
)
|
|
208
|
+
source_file = make_source_file("a.py", source)
|
|
209
|
+
findings = run(source_file, empty_corpus)
|
|
210
|
+
assert findings == []
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def test_flask_app_route_handler_excluded(make_source_file, empty_corpus):
|
|
214
|
+
source = (
|
|
215
|
+
"from flask import Flask\n"
|
|
216
|
+
"app = Flask(__name__)\n"
|
|
217
|
+
"@app.route('/x')\n"
|
|
218
|
+
"def handler(q='a'):\n"
|
|
219
|
+
" return q\n"
|
|
220
|
+
)
|
|
221
|
+
source_file = make_source_file("a.py", source)
|
|
222
|
+
findings = run(source_file, empty_corpus)
|
|
223
|
+
assert findings == []
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def test_flask_blueprint_get_handler_excluded(make_source_file, empty_corpus):
|
|
227
|
+
source = (
|
|
228
|
+
"from flask import Blueprint\n"
|
|
229
|
+
"bp = Blueprint('bp', __name__)\n"
|
|
230
|
+
"@bp.get('/x')\n"
|
|
231
|
+
"def handler(q='a'):\n"
|
|
232
|
+
" return q\n"
|
|
233
|
+
)
|
|
234
|
+
source_file = make_source_file("a.py", source)
|
|
235
|
+
findings = run(source_file, empty_corpus)
|
|
236
|
+
assert findings == []
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
def test_fastapi_handler_and_plain_function_mixed(make_source_file, empty_corpus):
|
|
240
|
+
"""A route handler is excluded but a plain defaulted function still flagged."""
|
|
241
|
+
source = (
|
|
242
|
+
"from fastapi import FastAPI\n"
|
|
243
|
+
"app = FastAPI()\n"
|
|
244
|
+
"@app.get('/x')\n"
|
|
245
|
+
"def handler(q: str = 'a'):\n"
|
|
246
|
+
" return q\n"
|
|
247
|
+
"def plain(x=1):\n"
|
|
248
|
+
" return x\n"
|
|
249
|
+
)
|
|
250
|
+
source_file = make_source_file("a.py", source)
|
|
251
|
+
findings = run(source_file, empty_corpus)
|
|
252
|
+
assert len(findings) == 1
|
|
253
|
+
assert findings[0].line == 6
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def test_non_framework_decorator_still_flagged(make_source_file, empty_corpus):
|
|
257
|
+
"""A custom .get() decorator with no fastapi/flask import is still flagged."""
|
|
258
|
+
source = (
|
|
259
|
+
"class MyAPI:\n"
|
|
260
|
+
" def get(self, *a, **k):\n"
|
|
261
|
+
" def deco(f):\n"
|
|
262
|
+
" return f\n"
|
|
263
|
+
" return deco\n"
|
|
264
|
+
"api = MyAPI()\n"
|
|
265
|
+
"@api.get()\n"
|
|
266
|
+
"def handler(q=1):\n"
|
|
267
|
+
" return q\n"
|
|
268
|
+
)
|
|
269
|
+
source_file = make_source_file("a.py", source)
|
|
270
|
+
findings = run(source_file, empty_corpus)
|
|
271
|
+
assert len(findings) == 1
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
def test_no_framework_import_still_flagged(make_source_file, empty_corpus):
|
|
275
|
+
"""Decorator shaped like a route but with no fastapi/flask import is flagged."""
|
|
276
|
+
source = (
|
|
277
|
+
"app = object()\n" "@app.get('/x')\n" "def handler(q=1):\n" " return q\n"
|
|
278
|
+
)
|
|
279
|
+
source_file = make_source_file("a.py", source)
|
|
280
|
+
findings = run(source_file, empty_corpus)
|
|
281
|
+
assert len(findings) == 1
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def test_staticmethod_decorator_still_flagged(make_source_file, empty_corpus):
|
|
285
|
+
"""Unrelated decorators (staticmethod) don't cause exclusion."""
|
|
286
|
+
source = "class C:\n" " @staticmethod\n" " def f(a=1):\n" " return a\n"
|
|
287
|
+
source_file = make_source_file("a.py", source)
|
|
288
|
+
findings = run(source_file, empty_corpus)
|
|
289
|
+
assert len(findings) == 1
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_surveyor-0.3.0 → python_surveyor-0.4.0}/python_surveyor.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|