Minimal CLI helpers for authorized penetration-testing lab organization and reporting.
Project description
reconlab
Minimal Python CLI helpers for authorized penetration-testing lab work. The project focuses on lab organization, scan parsing, and reporting workflows. It does not include exploit automation and is not intended for use against real third-party systems.
Install
From PyPI (recommended)
pipx install reconlab # isolated install, recommended for CLI tools
# or:
pip install reconlab # if you already manage your own Python env
From source (for development)
git clone https://github.com/0xsl0th/reconlab.git
cd reconlab
python -m venv .venv
source .venv/bin/activate
python -m pip install -e ".[dev]"
Commands at a glance
| Command | What it does |
|---|---|
workspace init |
Scaffold a target folder, metadata file, and a richer report scaffold. |
workspace suggest |
Generate methodology from scans/ - merges every scan file by default. |
workspace status |
Summarize a workspace - scans, methodology freshness, findings, web findings, and the next step. |
workspace ingest-web |
Merge every feroxbuster / gobuster / DirBuster output in a workspace's web/ folder into one table. |
workspace check |
Lint report.md for wrap-up readiness - unfilled findings and sections. Exits non-zero on issues. |
workspace archive |
Bundle a workspace into a portable .tar.gz for handoff or storage. Read-only on the workspace; excludes __pycache__, .pyc, .DS_Store, .venv, .git, ruff/mypy/pytest caches. |
finding add / finding list |
Capture findings into report.md; print the current findings table. |
workflow show / workflow list |
Print one workflow as Markdown / list the workflow registry - no scan or workspace needed. |
make-hosts |
Suggest an /etc/hosts entry - workspace-aware (pulls hostnames from scan output and metadata) with a manual no-workspace fallback. Read-only. |
vhost-suggest |
For each hostname discovered in scans (ssl-cert SANs, http-title redirects, SMB FQDN), print a curl probe and a gobuster enumeration command. Read-only. |
parse-nmap |
Tabular summary of open services from an nmap XML scan. |
parse-web |
Tabular summary of feroxbuster / gobuster / DirBuster output (text or JSON). |
suggest-next |
Methodology generator over an explicit scan file (underlies workspace suggest). |
Run reconlab --help (or reconlab <command> --help) for full option
lists, or reconlab --version to print the installed version.
Lab session walkthrough
End-to-end flow for a typical lab target. Replace placeholders with the real values your lab gives you.
# 1. Scaffold a workspace with metadata baked in. Init prints a suggested
# /etc/hosts line built from --ip / --host / --domain - paste the echo
# command it shows to map the hostname locally. Does NOT touch any file.
reconlab workspace init target \
--ip <ip> \
--host <host> \
--domain <domain> \
--platform lab
cd target
# 2. Run nmap into the workspace's scans/ folder.
sudo nmap -sV -sC -p- -oA scans/initial <ip>
# 3. (Optional) Re-run make-hosts to pick up hostnames discovered by the scan:
# ssl-cert SANs, http-title redirects, SMB FQDN. Skip if no new hostnames.
reconlab make-hosts
# 4. Generate prioritized, service-by-service methodology as an Obsidian vault.
# Metadata from the workspace (target IP / host / domain) is filled in
# automatically - no need to repeat the flags.
reconlab workspace suggest
# 5. Open notes/methodology/index.md in Obsidian (or any Markdown editor).
# Work through the per-service checklists; capture screenshots into
# screenshots/, recovered files into loot/, credentials into creds/.
# 6. Record findings into report.md as you go. The first call replaces the
# placeholder finding; later calls auto-increment the finding number.
reconlab finding add \
--title "SMB null session enabled" \
--severity high \
--service smb \
--port 445 \
--evidence screenshots/01-null-session.png
reconlab finding list # quick check of what is in the report so far
Layout produced by workspace init:
target/
├── .reconlab.json # target metadata (ip, host, domain, platform)
├── report.md # engagement report scaffold with frontmatter
├── scans/ # raw nmap output (xml/nmap/gnmap)
├── screenshots/ # one set per finding
├── loot/ # recovered files (sanitized before report)
├── notes/ # working notes + generated methodology vault
├── exploits/ # adapted exploit code with attribution
└── creds/ # recovered credentials - gitignored
After workspace suggest, notes/methodology/ contains an Obsidian-friendly
vault with one MOC (index.md) and one note per detected service.
Usage
Parse nmap XML
reconlab parse-nmap scans/target.xml
# JSON for piping to jq
reconlab parse-nmap scans/target.xml --output-format json | jq '.[] | select(.port=="445")'
# No header row - friendlier for awk/cut/grep pipelines
reconlab parse-nmap scans/target.xml --no-header | awk '{print $3}' # ports only
Example output:
Host Names Port Proto Service Product Version
---- ------ ---- ----- ------- ------- -------
<ip> <host> 80 tcp http nginx 1.18.0
Parse feroxbuster / gobuster / DirBuster output
parse-web ingests web content-discovery output and prints a clean
Status/Method/Size/URL table. It auto-detects feroxbuster text, feroxbuster
--json, gobuster text, and DirBuster (OWASP) report formats, strips ANSI
colours, and inlines redirect targets into the URL column.
# Auto-detect the format
reconlab parse-web outputs/feroxbuster.txt
reconlab parse-web outputs/feroxbuster.json
reconlab parse-web outputs/gobuster.txt
reconlab parse-web outputs/dirbuster.txt
# Force a specific parser
reconlab parse-web outputs/scan.txt --input-format feroxbuster
reconlab parse-web outputs/scan.txt --input-format dirbuster
# Filter to specific status codes:
# --status pre-filters BEFORE rendering (so the table widths stay aligned and the
# filter applies before --output-format json serializes). For simple table
# filtering on a single file, plain grep on the rendered output works too -
# each data row starts with the 3-digit status code.
reconlab parse-web outputs/feroxbuster.txt --status 200,301,403
reconlab parse-web outputs/feroxbuster.txt | grep -E '^200 '
reconlab parse-web outputs/feroxbuster.txt | grep -E '^[23][0-9]{2} ' # all 2xx + 3xx
reconlab parse-web outputs/feroxbuster.txt | grep -Ev '^404 ' # exclude 404 noise
# JSON for piping to jq (grep does not understand JSON - use jq or --status instead)
reconlab parse-web outputs/dirs.txt --output-format json | jq '.[] | .url'
reconlab parse-web outputs/dirs.txt --output-format json \
| jq '.[] | select(.status == "200") | .url'
# No header row - friendlier for awk/cut/grep pipelines
reconlab parse-web outputs/dirs.txt --no-header | awk '{print $6}' # URLs only
Example output:
Status Method Size Words Lines URL
------ ------ ---- ----- ----- ----------------------------------
200 GET 1234 46 4 http://<ip>/admin
301 GET 0 0 0 http://<ip>/login -> /login/
403 GET 287 12 2 http://<ip>/.git
200 GET 4567 62 8 http://<ip>/api/users
gobuster doesn't track word/line counts, so those columns show - for gobuster
input. DirBuster reports don't record size / words / lines at all, so those
three columns are all - for DirBuster input; URLs are reconstructed by
prefixing the base target URL (parsed from the report header) onto each
discovered path. Feroxbuster's --json format is parsed as newline-delimited
JSON, with non-response entries (scan-config, report) filtered out.
Make an /etc/hosts entry
make-hosts is a read-only helper. It prints the line you should add to
/etc/hosts plus a ready-to-paste shell command. It never modifies any file.
Workspace mode (default)
Run with no IP/hostname args inside (or pointed at) a workspace. The command
reads .reconlab.json for the target IP plus any target_host / domain,
walks every nmap XML scan in scans/, and pulls hostname candidates from:
<hostnames>(reverse DNS / user-supplied)ssl-certscript: subjectcommonNameand Subject Alternative Names (DNS entries; wildcards and IP SANs are filtered out)http-titlescript: hostnames in "Did not follow redirect to ..." linessmb-os-discoveryscript:fqdnfield
Candidates are deduplicated case-insensitively (first-seen casing wins) and the merged sources are shown so you can see why each hostname was suggested.
cd ~/labs/target
reconlab make-hosts
# or: reconlab make-hosts ~/labs/target
Sample output for a workspace whose scans contain ssl-cert + smb-os-discovery script results:
# Workspace: /home/you/labs/target
# Target IP: <ip>
# Hostname candidates:
# <host> (dns, ssl-cert CN, ssl-cert SAN, smb-os-discovery FQDN)
# <host-2> (http-title redirect)
# <host-3> (ssl-cert SAN)
# Add this to /etc/hosts:
<ip> <host> <host-2> <host-3>
# Or run:
echo "<ip> <host> <host-2> <host-3>" | sudo tee -a /etc/hosts
If .reconlab.json has no target_ip set, pass --target-ip <ip> to
override for this run. If no hostname candidates are found, the IP line is
still printed so you can add hostnames manually.
Manual form (no workspace)
Pass an IP followed by one or more hostnames when you just want to format a line without involving a workspace:
reconlab make-hosts <ip> <host> dev.corp.local Dev.corp.local DEV.corp.local
Or the equivalent flag form:
reconlab make-hosts \
--ip <ip> \
--host <host> \
--aliases dev.corp.local Dev.corp.local DEV.corp.local
In the flag form, the first value after --aliases is consumed by the flag and
any further positional arguments are appended as additional aliases - so the
shell-natural --aliases a b c syntax works. Repeating the flag
(--aliases a --aliases b) is also supported. Hostname casing is preserved
exactly as typed. Whether workspace mode or manual form runs is decided by the
first positional: an IPv4 address routes to manual; anything else (or no args)
routes to workspace mode.
Enumerate discovered vhosts
After make-hosts reads ssl-cert SANs, http-title redirects, and SMB FQDN
from your scan, the natural next step is to probe each newly-discovered
hostname as a virtual host. vhost-suggest prints exactly the commands you
need - one curl probe and one gobuster enumeration line per hostname -
using the Host header so the requests go to the target IP directly and
do not depend on /etc/hosts resolution.
# From inside the workspace, or pointed at one explicitly.
reconlab vhost-suggest
reconlab vhost-suggest ~/labs/target
reconlab vhost-suggest --target-ip <ip> # override metadata IP for the run
The metadata target_host (and its FQDN form when --domain is set) is
excluded - that is your primary host, already mapped. Only the newly-
discovered hostnames get suggestions. Read-only - reconlab never sends any
requests itself.
# Workspace: /home/op/labs/target
# Target IP: <ip>
# Discovered vhosts (excluding metadata target_host '<host>'):
# <host-2> (http-title redirect)
curl -I -H 'Host: <host-2>' http://<ip>/
gobuster dir -u http://<ip>/ -H 'Host: <host-2>' -w <wordlist> -o web/<host-2>.txt
# <host-3> (ssl-cert SAN)
curl -I -H 'Host: <host-3>' http://<ip>/
gobuster dir -u http://<ip>/ -H 'Host: <host-3>' -w <wordlist> -o web/<host-3>.txt
If scans/ contains only non-XML output (.nmap / .gnmap, no .xml),
the command prints the same XML-only hint as make-hosts since the script
data needed for vhost discovery only exists in XML.
Manage a lab workspace
workspace init scaffolds a target folder with a richer report template and
persists target metadata so downstream commands inherit it.
reconlab workspace init target \
--ip <ip> \
--host <host> \
--domain <domain> \
--platform lab \
-o ~/labs
workspace suggest merges every scan file in scans/ (oldest → newest) and
generates methodology into notes/methodology/ (Obsidian vault by default),
notes/methodology.md (--output-format md), or notes/methodology.json
(--output-format json):
# From inside the workspace, no flags needed.
reconlab workspace suggest
# Or explicitly point at a workspace.
reconlab workspace suggest ~/labs/target --output-format md --force
Multi-scan behavior:
- A typical engagement runs a TCP full scan, a UDP top-N scan, and a targeted
-sV -sCrescan. Drop all three intoscans/; methodology generation will union open ports across them and merge service metadata. - Records are keyed by
(host, port, proto). When the same port appears in more than one scan, the most recent non-placeholder value wins for service name, product, and version - so a later-sVoverrides an earlier banner-only scan, but an unscanned re-discovery cannot erase real data captured earlier. - Pass
--latestto revert to single-scan mode (most-recently-modified file only). Useful if older scans inscans/are stale or experimental.
Re-running refuses to overwrite the previous methodology unless --force is
passed; unrelated files in the workspace are never touched.
Check workspace status
workspace status prints a one-screen summary of where a workspace stands -
scan count, whether methodology has been generated (and whether it is stale
relative to scans/), recorded findings by severity, and a single suggested
next step.
# From inside the workspace, or point at one explicitly.
reconlab workspace status
reconlab workspace status ~/labs/target
Workspace: target
Path: /home/op/labs/target
Target <ip> · <host> · <domain>
Platform lab
Scans 1 file (latest: initial.xml)
Methodology notes/methodology/ - STALE (newer scans present)
Findings 1 recorded - 1 High
Next: methodology is stale relative to scans/. Re-run:
reconlab workspace suggest --force
The Next block is state-driven: a short description explains the
situation, and any concrete commands appear on indented lines below so
they are easy to copy-paste. It points at workspace suggest when no
methodology exists yet, flags a stale methodology once newer scans land, and
nudges toward finding add after methodology is in place. It never modifies
the workspace - workspace status is read-only.
Ingest web content-discovery output
workspace init now creates a web/ folder alongside scans/. Drop
feroxbuster (text or --json) or gobuster output there, and
workspace ingest-web merges every file into one deduplicated table -
parallel to how workspace suggest merges every nmap scan in scans/.
# After running content discovery against an HTTP service:
feroxbuster -u http://<ip> --json -o ~/labs/target/web/initial.json
gobuster dir -u http://<ip> -w wordlist.txt -o ~/labs/target/web/dir.txt
# From inside the workspace, or point at one explicitly:
reconlab workspace ingest-web
reconlab workspace ingest-web ~/labs/target
# Filter to specific status codes:
reconlab workspace ingest-web --status 200,301,403
Findings deduplicate by (method, status, URL); when the same URL+method+
status appears in multiple files, the most recent non-placeholder size /
word / line count wins. workspace status shows the merged count alongside
scans and findings, and the Next hint nudges toward ingest-web once
web outputs are present.
Check report readiness
workspace check lints the workspace's report.md and flags the scaffold
placeholders still left unfilled - per-finding fields (Severity, Description,
Evidence, Impact, Remediation) and the Executive Summary. It exits non-zero
when issues remain, so it works as a pre-handover gate or a CI step.
# From inside the workspace, or point at one explicitly.
reconlab workspace check
reconlab workspace check ~/labs/target
Report check: /home/op/labs/target/report.md
Report:
- Executive Summary is still the scaffold placeholder.
Findings:
Finding 1 - SMB null session enabled
- **Impact** is still a scaffold placeholder
- **Remediation** is still a scaffold placeholder
3 issues found - fill these in before handing the report over.
finding add fills in Severity, Affected, and (with --service) Description,
but Impact and Remediation are always left for you - workspace check is the
reminder that they, and the Executive Summary, still need attention. Like
workspace status, it is read-only.
Archive a workspace for handoff
workspace archive bundles the workspace into one .tar.gz so you can hand
it off, attach it to a report, or stash it for posterity. Reconlab never
modifies the workspace - only writes the tarball.
# From inside the workspace, or pointed at one explicitly.
reconlab workspace archive
reconlab workspace archive ~/labs/target
# Custom output path
reconlab workspace archive -o handoffs/target.tar.gz
# Overwrite an existing archive
reconlab workspace archive --force
The default output filename is <workspace-name>-archive.tar.gz in the
current directory. Inside the tarball every member lives under
<workspace-name>/ so extracting gives you one clean folder. Workspace
content is bundled verbatim - .reconlab.json, report.md, scans/,
web/, notes/, screenshots/, loot/, creds/, exploits/ - while
cache and editor junk is filtered out:
| Excluded by directory | Excluded by suffix | Excluded by name |
|---|---|---|
__pycache__, .venv, venv, env, .git, .mypy_cache, .pytest_cache, .ruff_cache |
.pyc, .pyo |
.DS_Store, Thumbs.db |
Archived workspace 'target' -> /home/op/labs/target-archive.tar.gz
files: 42
size: 1.3 MiB
The output without --force errors if the target tarball already exists,
so the command never silently overwrites a prior handoff.
Record findings into the report
finding add appends a structured finding block to report.md inside the
workspace. The first call replaces the placeholder ### Finding 1 - _Title_
left there by workspace init; subsequent calls auto-increment the finding
number after the highest existing one.
reconlab finding add \
--title "SMB null session enabled" \
--severity high \
--service smb \
--port 445 \
--evidence screenshots/01-shares.png \
--evidence loot/null-session-listing.txt
What finding add does:
- Reads
.reconlab.jsonand pre-fillsAffected:with the workspace's target IP and hostname. - If
--servicematches a known workflow (smb,http, ...), seeds theDescription:from the workflow's report-note (with[TARGET_IP]/[TARGET_HOST]/[DOMAIN]substituted) and adds a**Methodology:** see [[notes/methodology/services/<service>]]cross-link. --descriptionoverrides the workflow seed when you want custom text.- Each
--evidence PATHadds a bullet underEvidence:. Repeat the flag for multiple files (--evidence a.png --evidence b.png). - Severity is restricted to
critical | high | medium | low | info.
finding list prints the current findings as a one-line-per-finding table -
handy for sanity-checking what is captured so far without opening the file.
Severity is color-coded in the terminal (Critical bold-red, High bright-red,
Medium yellow, Low cyan, Info dim); ANSI codes are auto-stripped when output
is piped to a file or another command.
reconlab finding list
reconlab finding list ~/labs/target
# Filter by severity (comma-separated, case-insensitive)
reconlab finding list --severity high,critical
reconlab finding list --severity medium
# JSON for piping to jq (filter applies before serialization)
reconlab finding list --output-format json | jq '.[] | .title'
reconlab finding list --severity high,critical --output-format json
# No header row - friendlier for awk/cut/grep pipelines
reconlab finding list --no-header | awk '{print $2}' # severities only
# Severity Title Service:Port
- -------- --------------------------- ------------
1 High SMB null session enabled smb:445
2 Medium HTTP debug endpoint exposed http:80
Browse the workflow registry
workflow list and workflow show expose the workflow registry directly -
useful for "remind me what to check for LDAP" or for picking a starting point
on a target you haven't scanned yet. Neither command needs a workspace or a
scan file.
Workflows fall into three categories:
service-enum- per-service enumeration methodology (SMB, HTTP, LDAP, …). These are whatsuggest-next/workspace suggestauto-select from a scan.post-foothold- what to do once you have a shell or a valid credential:linux-privesc,windows-privesc,ad-foothold.lateral-movement-pivoting: tunneling and internal network access.
Post-foothold and lateral-movement workflows have no ports, so a scan never
auto-selects them - reach them with workflow show.
reconlab workflow list
# JSON for piping to jq
reconlab workflow list --output-format json | jq '.[] | select(.category=="service-enum")'
# No header row - friendlier for awk/cut/grep
reconlab workflow list --no-header | awk '{print $2}' # IDs only
Category ID Display Priority Ports
---------------- --------------- --------------- -------- --------------------
service-enum smb SMB 10 139/tcp, 445/tcp
service-enum http HTTP 15 80/tcp, 8000/tcp, …
…
post-foothold linux-privesc Linux Privesc 50 -
post-foothold windows-privesc Windows Privesc 51 -
post-foothold ad-foothold AD Foothold 52 -
lateral-movement pivoting Pivoting 60 -
# Print one workflow (Markdown) to stdout with placeholders intact
reconlab workflow show smb
reconlab workflow show linux-privesc
# Or substitute target metadata while rendering
reconlab workflow show ad-foothold --domain <domain>
The Markdown is the same per-workflow content that workspace suggest and
suggest-next write into the methodology document. Those two commands also
append an After a Foothold footer pointing at the post-foothold workflows,
so the generated methodology carries you past initial access.
Suggest the next steps from an nmap scan
suggest-next is the underlying methodology generator. For the typical case
(one workspace, drop a scan into scans/, get a vault back) prefer
reconlab workspace suggest - it picks up the latest scan and the workspace
metadata automatically. Reach for suggest-next directly when you want to
point at an arbitrary scan file or override the target metadata.
It turns parsed nmap results into a service-based, prioritized methodology
document. Each detected service gets a checklist, command table, expected output,
verification steps, troubleshooting matrix, and a draft report note. Lab placeholders
([USER], [PASS], [LHOST], [LPORT]) are preserved for the operator to fill in.
Supported input formats:
xml- nmap XML (-oXor-oA); the most reliable parser.normal- human-readable nmap output (.nmapfiles from-oNor-oA).grepable- grepable nmap output (.gnmapfiles from-oGor-oA).auto(default) - infers from the file extension; if the path has no extension, it is treated as annmap -oAbasename and the matching sibling file is probed inxml → normal → grepablepriority.
# Auto-detect: scans/target resolves to scans/target.xml if present,
# otherwise scans/target.nmap, otherwise scans/target.gnmap.
reconlab suggest-next \
-i scans/target \
--input-format auto \
--target <ip> \
--host <host> \
--domain <domain> \
-o outputs/next.md
# Force a specific parser
reconlab suggest-next -i scans/target.nmap --input-format normal --target <ip>
reconlab suggest-next -i scans/target.gnmap --input-format grepable --target <ip>
reconlab suggest-next -i scans/target.xml --input-format xml --target <ip>
The simplest invocation derives the target IP from the scan and prints Markdown to stdout:
reconlab suggest-next -i scans/target.xml
Excerpt of the default md output:
# Methodology - <ip>
## Detected Services
| Port | Proto | Service | Product | Version |
|------|-------|---------|---------|---------|
| 445 | tcp | microsoft-ds | Samba | 4.15.0 |
| 3389 | tcp | ms-wbt-server | - | - |
## SMB (139/445) - Share & RPC Enumeration
### Checklist
- [ ] Fingerprint SMB dialect and signing posture.
- [ ] Attempt null-session share listing.
...
Supported service-enum workflows in this release: SMB, HTTP, HTTPS, FTP, SSH,
DNS, SMTP, LDAP, Kerberos, MSSQL, MySQL, Oracle, RDP, WinRM, SNMP, NFS, rsync,
Redis, VNC, IMAP/POP3 (20 total), plus
three post-foothold workflows - linux-privesc, windows-privesc,
ad-foothold - and one lateral-movement workflow, pivoting. Run
reconlab workflow list for the live registry with
categories, priorities, and port mappings. Open ports without a service-enum
workflow are listed under an Unmapped Services section so nothing is
silently dropped.
Obsidian vault output
--output-format obsidian writes a small Obsidian-friendly vault folder instead of a
single Markdown file. The directory passed via -o is created (and intermediate
parents) if it does not already exist.
reconlab suggest-next \
-i scans/target \
--target <ip> \
--host <host> \
--domain <domain> \
--output-format obsidian \
-o notes/target
Generated layout:
notes/target/
├── index.md # MOC: frontmatter, scope, detected services, prioritized
│ # wikilinks to each service note, optional report draft
├── services/
│ ├── smb.md # frontmatter + Checklist / Commands / Expected output /
│ ├── http.md # Verification / Troubleshooting / Report note / Related
│ ├── rdp.md
│ └── … # one per detected & mapped service
└── unmapped.md # only present when the scan has open ports without a workflow
- Filenames use the lowercase canonical service ID (
smb.md,winrm.md). - Cross-references render as aliased wikilinks:
[[services/smb|SMB]],[[services/winrm|WinRM]]- paths are stable and machine-friendly, while the alias keeps the rendered text human-friendly. - Each note carries YAML frontmatter (
title,target,service,priority,status: in-progress, tags) so Obsidian dataview / search queries work immediately.
By default the command refuses to overwrite existing files in the vault directory.
Pass --force to overwrite, or point -o at an empty/new directory. Files in the
target directory that the tool does not generate are left untouched.
# Re-render and overwrite previously generated notes
reconlab suggest-next -i scans/target --output-format obsidian -o notes/target --force
The md default behavior (single Markdown file, optional -o) is unchanged.
JSON output
--output-format json writes a single structured JSON document instead of
Markdown or a vault: target metadata, detected and unmapped services, and the
full prioritized per-workflow methodology (checklists, commands, troubleshooting,
report notes) as data. Like md, it prints to stdout when -o is omitted.
# To a file, or piped into jq for scripting.
reconlab suggest-next -i scans/target --output-format json -o outputs/methodology.json
reconlab suggest-next -i scans/target --output-format json | jq '.workflows[].service_id'
Target placeholders ([TARGET_IP], [TARGET_HOST], [DOMAIN]) are substituted;
operator placeholders ([USER], [PASS], ...) are left intact for downstream
tooling. --output-format accepts md, json, and obsidian.
Development
Install the dev extras (pytest + ruff), then run syntax checks, lint, and
tests:
python -m pip install -e ".[dev]"
python -m compileall src tests
ruff check .
python -m pytest
GitHub Actions runs ruff check . and pytest on every push and pull request
across Python 3.11 and 3.13 (see .github/workflows/tests.yml).
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 reconlab-0.15.0.tar.gz.
File metadata
- Download URL: reconlab-0.15.0.tar.gz
- Upload date:
- Size: 104.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3c587492485f7b6c55de4b174b9b01653f2d93e7eea77cbcbd795e862b74a2df
|
|
| MD5 |
be4eb4a51b1c13177461694f242c832a
|
|
| BLAKE2b-256 |
e52d434c0b017a52db29a2b722f68c66afa16238f2924c4c0b59e0ad40bd2bb5
|
Provenance
The following attestation bundles were made for reconlab-0.15.0.tar.gz:
Publisher:
publish.yml on 0xsl0th/reconlab
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
reconlab-0.15.0.tar.gz -
Subject digest:
3c587492485f7b6c55de4b174b9b01653f2d93e7eea77cbcbd795e862b74a2df - Sigstore transparency entry: 1569343065
- Sigstore integration time:
-
Permalink:
0xsl0th/reconlab@ff7cdb4f8a053132971ffda581c3f5766e782770 -
Branch / Tag:
refs/tags/v0.15.0 - Owner: https://github.com/0xsl0th
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ff7cdb4f8a053132971ffda581c3f5766e782770 -
Trigger Event:
release
-
Statement type:
File details
Details for the file reconlab-0.15.0-py3-none-any.whl.
File metadata
- Download URL: reconlab-0.15.0-py3-none-any.whl
- Upload date:
- Size: 70.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fc7267e0d1f3a5ac5f1d62bf208cec7fdb8e29df49b02ce7b4264861adb37dc6
|
|
| MD5 |
9068e6ee83b5cc6353b9ebd0b2584c77
|
|
| BLAKE2b-256 |
d4a21e0aed1eb9907d35dfaf29960f10c6f854114842f3259d24d5c4b1f184ba
|
Provenance
The following attestation bundles were made for reconlab-0.15.0-py3-none-any.whl:
Publisher:
publish.yml on 0xsl0th/reconlab
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
reconlab-0.15.0-py3-none-any.whl -
Subject digest:
fc7267e0d1f3a5ac5f1d62bf208cec7fdb8e29df49b02ce7b4264861adb37dc6 - Sigstore transparency entry: 1569343118
- Sigstore integration time:
-
Permalink:
0xsl0th/reconlab@ff7cdb4f8a053132971ffda581c3f5766e782770 -
Branch / Tag:
refs/tags/v0.15.0 - Owner: https://github.com/0xsl0th
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ff7cdb4f8a053132971ffda581c3f5766e782770 -
Trigger Event:
release
-
Statement type: