Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
name: Bug report
about: Something returns a wrong answer or crashes
labels: bug
---

**Command**

```
netprobe ...
```

**What happened**

Paste the output. If it is a crash, include the whole traceback.

**What you expected instead**

For a wrong-answer bug, say what the correct value is and why - a reference
(RFC, vendor doc, another tool's output) helps a lot.

**Environment**

- `netprobe --version`:
- `python --version`:
- OS:
19 changes: 19 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
name: Feature request
about: Propose a new command or option
labels: enhancement
---

**The diagnostic question you are trying to answer**

Describe the situation, not the flag. "I need to know which of these 40 hosts
answers on 8080" is more useful than "add a --parallel option".

**How you solve it today**

Which tool, and what is awkward about it.

**Would this need a dependency?**

The project is standard-library only. If the feature needs something from PyPI,
say what and why nothing in the stdlib covers it.
14 changes: 14 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
**What changed**

**Why**

If you made a non-obvious choice, explain the reasoning here - that is the part
nobody can reconstruct from the diff later.

**Checklist**

- [ ] `python -m unittest discover -s tests` passes
- [ ] `ruff check .` is clean
- [ ] New behaviour has tests, and boundary cases are covered
- [ ] Exit status follows the convention (`0` ok, `1` check failed, `2` usage)
- [ ] README updated if a user-visible flag or output changed
30 changes: 30 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Changelog

All notable changes to this project are documented here. The format follows
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project uses
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [0.1.0]

First release. Six commands, no dependencies.

### Added

- `subnet` - CIDR description, splitting, membership tests and summarisation,
with correct `/31` (RFC 3021 point-to-point) and `/32` host counts
- `scan` - threaded TCP port sweep over a host or a whole CIDR block, with
flexible port specs (`22`, `22,80`, `1-1024`) and service annotation
- `latency` - TCP connect timing with min/avg/p95/max, packet loss and jitter
- `dns` - forward, reverse and round-trip resolution through `getaddrinfo`
- `http` - endpoint health with hop-by-hop redirect chain walking
- `mac` - MAC normalisation across notations, OUI vendor lookup, and decoding
of the locally-administered and multicast flag bits
- Global `--json` flag on every command
- Optional `netprobe.ini` for per-command defaults, applied as argparse
defaults so explicit flags always win
- 84 tests and a CI matrix over ubuntu/windows/macos on Python 3.9 and 3.12

[Unreleased]: https://github.com/saeed205/netprobe-cli/compare/v0.1.0...HEAD
[0.1.0]: https://github.com/saeed205/netprobe-cli/releases/tag/v0.1.0
72 changes: 72 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Contributing

## Setup

No dependencies to install for the library or the tests:

```bash
git clone https://github.com/saeed205/netprobe-cli
cd netprobe-cli
python -m unittest discover -s tests -v
```

Only the linter needs installing:

```bash
pip install ruff
ruff check .
```

## Adding a command

Commands self-register, so nothing in the argument parser needs editing.

1. Create `netprobe/yourcommand.py`.
2. Write the logic as **plain functions that take and return data** - no
printing, no `argparse` types in the signature. That is what makes it
testable without a network.
3. Add a `_handle(args)` that calls those functions and hands the rows to
`output.emit()`.
4. Register the parser:

```python
from .cli import register

@register
def _add_parser(subparsers):
p = subparsers.add_parser("yourcommand", help="one line of help")
p.add_argument("target")
p.set_defaults(handler=_handle)
```

5. Import the module in `netprobe/commands.py` and add it to `_MODULES`,
keeping both alphabetical.

## House rules

- **Standard library only.** A diagnostics tool that cannot be installed on a
locked-down jump box is not much use. A dependency needs a strong argument.
- **Python 3.9 is the floor.** Typing-module spellings (`Dict`, `Optional`)
are used deliberately - see the comment in `ruff.toml` before "modernising"
them.
- **Exit status is an interface.** `0` success, `1` the check failed, `2`
usage error. People put these commands in monitoring checks; do not return
`0` for a failed probe.
- **Never print from a helper.** Rendering belongs in `output.py` so that
`--json` keeps working everywhere for free.

## Tests

Plain `unittest`. Anything that opens a socket does not belong in the suite -
CI runs on sandboxed runners with no egress. Test the parsing, the arithmetic
and the precedence rules; those are where the bugs actually live.

Worth testing explicitly: boundary values (`/31`, `/32`, empty input, single
element), and anything where a plausible-looking implementation gives a wrong
answer.

## Pull requests

Say what changed and why. If you made a non-obvious choice, put the reasoning
in the description - that is the part nobody can reconstruct from the diff six
months later.
Loading