Structural-honesty checks for Python, powered by Furqan
Project description
furqan-lint
Structural-honesty checks for Python, powered by Furqan.
furqan-lint translates Python source into the Furqan AST and runs the
subset of Furqan checkers whose semantics carry across language boundaries
into idiomatic Python. Phase 1 ships two checks:
- D24 (all-paths-return) every control-flow path through a typed function reaches a return statement.
- D11 (status-coverage) when a function returns
Optional[X], every caller either propagates the optionality or explicitly handlesNone. A caller that silently collapsesOptional[X]into a non-optional return type is the structural equivalent of dropping theIncompletearm of Furqan'sIntegrity | Incompleteunion.
Install
pip install furqan-lint
Requires Python 3.10+ and furqan>=0.10.1.
Usage
furqan-lint check path/to/file.py
furqan-lint check path/to/directory/
furqan-lint version
Example
# example.py
from typing import Optional
def find_record(id: int) -> Optional[dict]:
if id <= 0:
return None
return {"id": id}
def get_name(id: int) -> str:
record = find_record(id)
if record is not None:
return record["name"]
# Missing else: falls through with no return
$ furqan-lint check example.py
MARAD example.py
2 violation(s):
[all_paths_return] Function 'get_name' at line 8 declares
-> str but not every control-flow path reaches a return
statement.
fix: Add a return statement to the else branch or after
the if block.
[status_coverage] Function 'get_name' at line 8 calls
'find_record' (returns Optional[dict]) but declares -> str.
The Optional is silently collapsed.
fix: Change return type to Optional[str].
Phase 1 scope and known gaps
Phase 1 wires two of Furqan's ten checkers to Python. The remaining eight
require Python-specific conventions (scope declarations, layer annotations,
calibration bounds, dependency mapping) that do not exist in standard
Python. Documented gaps in Section 8 of the implementation prompt:
return Nonewith a non-Optional declared return type is treated as a satisfied path by D24. Phase 2 adds D22 (return-type match) which closes this gap.- The D11 producer detection uses a scoped monkey-patch on
status_coverage._is_integrity_incomplete_union. Phase 2 adds aproducer_predicateparameter tocheck_status_coverageupstream. - Class methods are extracted as top-level functions; calls written as
self.validate()are matched on the attribute namevalidateonly. - Only D24 and D11 run. The other eight checkers require language-level constructs Python does not have.
- Calls inside nested functions are attributed to the enclosing function.
License
Apache-2.0.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file furqan_lint-0.1.0.tar.gz.
File metadata
- Download URL: furqan_lint-0.1.0.tar.gz
- Upload date:
- Size: 16.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5e7cd02fd288627d802fd16f1a1fd1c6920c87fbda6bcecaeb8d48f15abb3a8e
|
|
| MD5 |
7e774450e275dfa92cdaa7bc37c3ad06
|
|
| BLAKE2b-256 |
c8f3f22ab1b7320c268f3c79073c4119ba539d74daf3d5d8e63470a9d2803c9b
|
File details
Details for the file furqan_lint-0.1.0-py3-none-any.whl.
File metadata
- Download URL: furqan_lint-0.1.0-py3-none-any.whl
- Upload date:
- Size: 13.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4ff9ee0d6b52b3e594d28f6cd33c88821907705f83091a9c3983de8bb830b38b
|
|
| MD5 |
4d3105051a38f24262154c97137746bc
|
|
| BLAKE2b-256 |
128d781ecd0ef050dca0cfd7579505a57ee1e2d3f5b055dc237f1176b1f3e55e
|