timeout-dead 0.1.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.
- timeout_dead-0.1.0/.github/workflows/publish.yml +26 -0
- timeout_dead-0.1.0/.github/workflows/pyright.yml +26 -0
- timeout_dead-0.1.0/.github/workflows/ruff.yml +23 -0
- timeout_dead-0.1.0/.github/workflows/tests.yml +26 -0
- timeout_dead-0.1.0/.gitignore +158 -0
- timeout_dead-0.1.0/AGENTS.md +208 -0
- timeout_dead-0.1.0/CODE-STYLE.md +717 -0
- timeout_dead-0.1.0/CONTRIBUTING.md +79 -0
- timeout_dead-0.1.0/LICENSE +24 -0
- timeout_dead-0.1.0/MANIFEST.in +5 -0
- timeout_dead-0.1.0/PKG-INFO +129 -0
- timeout_dead-0.1.0/README.md +103 -0
- timeout_dead-0.1.0/icon.png +0 -0
- timeout_dead-0.1.0/pyproject.toml +59 -0
- timeout_dead-0.1.0/ruff.toml +15 -0
- timeout_dead-0.1.0/setup.cfg +4 -0
- timeout_dead-0.1.0/src/timeout_dead/__init__.py +6 -0
- timeout_dead-0.1.0/src/timeout_dead/_version.py +24 -0
- timeout_dead-0.1.0/src/timeout_dead/cli.py +302 -0
- timeout_dead-0.1.0/src/timeout_dead.egg-info/SOURCES.txt +20 -0
- timeout_dead-0.1.0/tests/conftest.py +15 -0
- timeout_dead-0.1.0/tests/test_cli.py +469 -0
- timeout_dead-0.1.0/uv.lock +714 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "*"
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
publish:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
permissions:
|
|
12
|
+
id-token: write
|
|
13
|
+
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
with:
|
|
17
|
+
fetch-depth: 0
|
|
18
|
+
|
|
19
|
+
- name: Install uv
|
|
20
|
+
uses: astral-sh/setup-uv@v5
|
|
21
|
+
|
|
22
|
+
- name: Build package
|
|
23
|
+
run: uv build
|
|
24
|
+
|
|
25
|
+
- name: Publish to PyPI
|
|
26
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name: Pyright
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
typecheck:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
strategy:
|
|
11
|
+
matrix:
|
|
12
|
+
python-version: ["3.12", "3.13"]
|
|
13
|
+
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- name: Install uv
|
|
18
|
+
uses: astral-sh/setup-uv@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: ${{ matrix.python-version }}
|
|
21
|
+
|
|
22
|
+
- name: Install dependencies
|
|
23
|
+
run: uv sync --extra dev
|
|
24
|
+
|
|
25
|
+
- name: Run pyright
|
|
26
|
+
run: uv run pyright src/timeout_dead/
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
name: Ruff
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
lint:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
strategy:
|
|
11
|
+
matrix:
|
|
12
|
+
python-version: ["3.12", "3.13"]
|
|
13
|
+
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- name: Install uv
|
|
18
|
+
uses: astral-sh/setup-uv@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: ${{ matrix.python-version }}
|
|
21
|
+
|
|
22
|
+
- name: Run ruff
|
|
23
|
+
run: uvx ruff check src/timeout_dead/ tests/
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
test:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
strategy:
|
|
11
|
+
matrix:
|
|
12
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
13
|
+
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- name: Install uv
|
|
18
|
+
uses: astral-sh/setup-uv@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: ${{ matrix.python-version }}
|
|
21
|
+
|
|
22
|
+
- name: Install dependencies
|
|
23
|
+
run: uv sync --extra dev
|
|
24
|
+
|
|
25
|
+
- name: Run tests
|
|
26
|
+
run: uv run pytest
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
*.manifest
|
|
31
|
+
|
|
32
|
+
# Installer logs
|
|
33
|
+
pip-log.txt
|
|
34
|
+
pip-delete-this-directory.txt
|
|
35
|
+
|
|
36
|
+
# Unit test / coverage reports
|
|
37
|
+
htmlcov/
|
|
38
|
+
.tox/
|
|
39
|
+
.nox/
|
|
40
|
+
.coverage
|
|
41
|
+
.coverage.*
|
|
42
|
+
.cache
|
|
43
|
+
nosetests.xml
|
|
44
|
+
coverage.xml
|
|
45
|
+
*.cover
|
|
46
|
+
*.py,cover
|
|
47
|
+
.hypothesis/
|
|
48
|
+
.pytest_cache/
|
|
49
|
+
cover/
|
|
50
|
+
|
|
51
|
+
# Translations
|
|
52
|
+
*.mo
|
|
53
|
+
*.pot
|
|
54
|
+
|
|
55
|
+
# Django stuff:
|
|
56
|
+
*.log
|
|
57
|
+
local_settings.py
|
|
58
|
+
db.sqlite3
|
|
59
|
+
db.sqlite3-journal
|
|
60
|
+
|
|
61
|
+
# Flask stuff:
|
|
62
|
+
instance/
|
|
63
|
+
.webassets-cache
|
|
64
|
+
|
|
65
|
+
# Scrapy stuff:
|
|
66
|
+
.scrapy
|
|
67
|
+
|
|
68
|
+
# Sphinx documentation
|
|
69
|
+
docs/_build/
|
|
70
|
+
|
|
71
|
+
# PyBuilder
|
|
72
|
+
.pybuilder/
|
|
73
|
+
target/
|
|
74
|
+
|
|
75
|
+
# Jupyter Notebook
|
|
76
|
+
.ipynb_checkpoints
|
|
77
|
+
|
|
78
|
+
# IPython
|
|
79
|
+
profile_default/
|
|
80
|
+
ipython_config.py
|
|
81
|
+
|
|
82
|
+
# PDM
|
|
83
|
+
.pdm.toml
|
|
84
|
+
.pdm-python
|
|
85
|
+
.pdm-build/
|
|
86
|
+
|
|
87
|
+
# PEP 582
|
|
88
|
+
__pypackages__/
|
|
89
|
+
|
|
90
|
+
# Celery stuff
|
|
91
|
+
celerybeat-schedule
|
|
92
|
+
celerybeat.pid
|
|
93
|
+
|
|
94
|
+
# SageMath parsed files
|
|
95
|
+
*.sage.py
|
|
96
|
+
|
|
97
|
+
# Environments
|
|
98
|
+
.env
|
|
99
|
+
.venv
|
|
100
|
+
env/
|
|
101
|
+
venv/
|
|
102
|
+
ENV/
|
|
103
|
+
env.bak/
|
|
104
|
+
venv.bak/
|
|
105
|
+
|
|
106
|
+
# Spyder project settings
|
|
107
|
+
.spyderproject
|
|
108
|
+
.spyproject
|
|
109
|
+
|
|
110
|
+
# Rope project settings
|
|
111
|
+
.ropeproject
|
|
112
|
+
|
|
113
|
+
# mkdocs
|
|
114
|
+
/site
|
|
115
|
+
|
|
116
|
+
# mypy
|
|
117
|
+
.mypy_cache/
|
|
118
|
+
.dmypy.json
|
|
119
|
+
dmypy.json
|
|
120
|
+
|
|
121
|
+
# Pyre type checker
|
|
122
|
+
.pyre/
|
|
123
|
+
|
|
124
|
+
# pytype static type analyzer
|
|
125
|
+
.pytype/
|
|
126
|
+
|
|
127
|
+
# Cython debug symbols
|
|
128
|
+
cython_debug/
|
|
129
|
+
|
|
130
|
+
# PyCharm
|
|
131
|
+
.idea/
|
|
132
|
+
|
|
133
|
+
# VS Code
|
|
134
|
+
.vscode/*
|
|
135
|
+
!.vscode/settings.json
|
|
136
|
+
|
|
137
|
+
# Solution data
|
|
138
|
+
*solved.ipynb
|
|
139
|
+
*solved.py
|
|
140
|
+
*solved
|
|
141
|
+
|
|
142
|
+
# Other files
|
|
143
|
+
*.docx
|
|
144
|
+
*.doc
|
|
145
|
+
*.exe
|
|
146
|
+
*.rtf
|
|
147
|
+
*.xlsx
|
|
148
|
+
*.env*
|
|
149
|
+
temp.*
|
|
150
|
+
|
|
151
|
+
# Ruff
|
|
152
|
+
.ruff_cache/
|
|
153
|
+
|
|
154
|
+
# PyPI config
|
|
155
|
+
.pypirc
|
|
156
|
+
|
|
157
|
+
# Auto-generated by setuptools-scm
|
|
158
|
+
src/timeout_dead/_version.py
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
## Project & Profile
|
|
4
|
+
|
|
5
|
+
`timeout-dead` — lightweight command timeout utility with zero external dependencies. Runs any shell command with a configurable timeout and signal, terminating the process if it exceeds the limit. Works on Unix (Linux/macOS) and Windows (with Git Bash or WSL).
|
|
6
|
+
|
|
7
|
+
### Code style
|
|
8
|
+
|
|
9
|
+
You MUST strictly follow the project's coding standards, naming conventions, and language-specific rules.
|
|
10
|
+
|
|
11
|
+
Before generating, refactoring, or modifying any code, you are REQUIRED to read and apply the guidelines defined in the external style guide:
|
|
12
|
+
|
|
13
|
+
- **File Path:** [`./CODE-STYLE.md`](./CODE-STYLE.md)
|
|
14
|
+
|
|
15
|
+
_Instruction for Agent:_ If you haven't read `./CODE-STYLE.md` in the current session, use your file-reading tool to fetch its content before writing any code. Do not hallucinate styles.
|
|
16
|
+
|
|
17
|
+
## Operational Rules & Critical Restrictions
|
|
18
|
+
|
|
19
|
+
**UNDER NO CIRCUMSTANCES may you commit, push, amend, rebase, or modify the git history without an EXPLICIT instruction to do so.** This is the most important rule in this document. Violating it may result in lost work and broken branches.
|
|
20
|
+
|
|
21
|
+
This specifically includes:
|
|
22
|
+
|
|
23
|
+
- `git commit` / `git commit --amend` / `git commit -m "..."`
|
|
24
|
+
- `git push` / `git push --force` / `git push --force-with-lease`
|
|
25
|
+
- `git add` (stage for commit — prefer working-tree-only edits)
|
|
26
|
+
- `git rebase` / `git reset` / `git checkout` (to modify branches)
|
|
27
|
+
- Any other command that creates or alters commits
|
|
28
|
+
|
|
29
|
+
If the user asks "what should the commit message be?" — **suggest a message but do NOT commit**. Wait for an explicit directive such as:
|
|
30
|
+
|
|
31
|
+
- "commit"
|
|
32
|
+
- "commit and push"
|
|
33
|
+
- "закоммить"
|
|
34
|
+
- "сделай коммит"
|
|
35
|
+
|
|
36
|
+
**If the user says "обнови AGENTS.md" or similar — this is NOT a commit instruction. Do NOT add or commit files unless told to.**
|
|
37
|
+
|
|
38
|
+
## Workflow & Verification Commands
|
|
39
|
+
|
|
40
|
+
### Time limit (HARD REQUIREMENT)
|
|
41
|
+
|
|
42
|
+
**Every bash command MUST complete within 60 seconds.** All commands must be invoked through the timeout wrapper:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
timeout-dead --sec 60 "<your command>"
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Long-running daemons must use `nohup ... >/dev/null 2>&1 &` so the wrapper returns immediately.
|
|
49
|
+
|
|
50
|
+
### Setup
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
timeout-dead --sec 60 "uv sync"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Verify after changes
|
|
57
|
+
|
|
58
|
+
Run **all** checks in this order — treat errors as blockers:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
timeout-dead --sec 60 "ruff check ."
|
|
62
|
+
timeout-dead --sec 60 "ruff format --check ."
|
|
63
|
+
timeout-dead --sec 60 "pyright ."
|
|
64
|
+
timeout-dead --sec 60 "python -m pytest tests/ -v"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Fix formatting & imports
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
timeout-dead --sec 60 "ruff check --fix . && ruff format ."
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**LSP is mandatory.** Configure `pyright-langserver` and `ruff server` in your editor. After every change, confirm lint, format, and type-check show **0 errors**. `ruff format` is the single source of truth for formatting — no `black`, no `isort`.
|
|
74
|
+
|
|
75
|
+
### Run a single test
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
timeout-dead --sec 60 "python -m pytest tests/test_file.py::test_name -v"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Mandatory testing
|
|
82
|
+
|
|
83
|
+
**Every change must be verified by running the test suite.** No exceptions. If any test fails, fix the issue before considering the change complete.
|
|
84
|
+
|
|
85
|
+
## Software Architecture & Design Patterns
|
|
86
|
+
|
|
87
|
+
### Documentation
|
|
88
|
+
|
|
89
|
+
- **Standalone Markdown documentation pages** → `SCREAMING_SNAKE_CASE` names (e.g., `CONFIG.md`, `ARCHITECTURE.md`, `CODE-STYLE.md`). Keep conventional repository files such as `README.md` unchanged unless explicitly requested.
|
|
90
|
+
|
|
91
|
+
### Package Layout
|
|
92
|
+
|
|
93
|
+
- Source code lives under `src/<project_name>/` (or directly in `<project_name>/` depending on preference). Choose one convention and stick to it.
|
|
94
|
+
- Separate packages by concern — do not dump all classes in a single flat directory.
|
|
95
|
+
- Example layout for a typical project:
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
src/myproject/
|
|
99
|
+
__init__.py ← exports public API via __all__
|
|
100
|
+
core/ ← domain logic, entities, services
|
|
101
|
+
cli/ ← CLI entry points (typer/click)
|
|
102
|
+
api/ ← HTTP API layer (if applicable)
|
|
103
|
+
config/ ← configuration models (pydantic/dataclass)
|
|
104
|
+
constants.py ← shared constants
|
|
105
|
+
utils/ ← shared utility functions
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
- **Never create a `model.py` dumping ground.** Split types into explicit purpose modules (e.g., `entities.py`, `dto.py`, `enums.py`).
|
|
109
|
+
|
|
110
|
+
### Separation of Concerns
|
|
111
|
+
|
|
112
|
+
- **Core logic** lives in `core/` and has zero dependencies on CLI, HTTP, or file I/O. Pure domain logic only.
|
|
113
|
+
- **CLI layer** delegates to core services — never contains business logic.
|
|
114
|
+
- **Configuration** uses `pydantic.BaseModel` or `dataclasses.dataclass` for typed, validated settings loaded from environment, config files, or CLI arguments.
|
|
115
|
+
|
|
116
|
+
### Dependency Management
|
|
117
|
+
|
|
118
|
+
- Use **`uv`** for dependency management (recommended). Alternatives: `pip` with `requirements.txt`.
|
|
119
|
+
- **Never edit `uv.lock` manually.** It is regenerated by `uv lock` or `uv sync` when dependencies change.
|
|
120
|
+
- Dependencies are declared in `pyproject.toml`.
|
|
121
|
+
|
|
122
|
+
### CLI Design
|
|
123
|
+
|
|
124
|
+
- Use `typer` or `click` for CLI tools. For web APIs, use `fastapi` or `flask`.
|
|
125
|
+
- Each command groups related operations — use subcommands for modularity.
|
|
126
|
+
- CLI entry points handle argument parsing, then delegate to core services.
|
|
127
|
+
- For CLI testing, use the appropriate test harness (e.g., `CliRunner`) and verify that output is captured correctly.
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
# src/myproject/cli/main.py
|
|
131
|
+
import typer
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
app = typer.Typer()
|
|
135
|
+
|
|
136
|
+
# ------------------------------------------------
|
|
137
|
+
|
|
138
|
+
@app.command()
|
|
139
|
+
def process(file: str):
|
|
140
|
+
"""Process a file."""
|
|
141
|
+
result = service.process(file)
|
|
142
|
+
print(result)
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Exceptions
|
|
146
|
+
|
|
147
|
+
- Define a custom exception hierarchy rooted in a `BaseError` (or use a library like `pydantic_core` for validation errors).
|
|
148
|
+
- For HTTP APIs: return structured error responses, never let bare tracebacks leak to clients.
|
|
149
|
+
- CLI entry points catch exceptions, log the error, and return a non-zero exit code.
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
class BaseError(Exception):
|
|
153
|
+
"""Base exception for application errors."""
|
|
154
|
+
|
|
155
|
+
# ------------------------------------------------
|
|
156
|
+
|
|
157
|
+
class NotFoundError(BaseError):
|
|
158
|
+
"""Resource not found."""
|
|
159
|
+
|
|
160
|
+
# ------------------------------------------------
|
|
161
|
+
|
|
162
|
+
class ConflictError(BaseError):
|
|
163
|
+
"""Resource conflict."""
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Testing Strategy
|
|
167
|
+
|
|
168
|
+
- Use `pytest` as the test framework. See [`./CODE-STYLE.md`](./CODE-STYLE.md) for style rules (fixtures, parametrize, mocking, skipping, naming).
|
|
169
|
+
|
|
170
|
+
### Unit Tests
|
|
171
|
+
|
|
172
|
+
- Tests live in `tests/` mirroring the source structure.
|
|
173
|
+
- Run unit tests: `timeout-dead --sec 60 "pytest tests/ -v --ignore=tests/integration"`.
|
|
174
|
+
|
|
175
|
+
### Integration Tests
|
|
176
|
+
|
|
177
|
+
- Place integration tests in `tests/integration/`. Use `@pytest.mark.integration` marker.
|
|
178
|
+
- Run integration tests: `timeout-dead --sec 60 "pytest tests/integration/ -v -m \"integration\""`.
|
|
179
|
+
- Run unit tests only: `timeout-dead --sec 60 "pytest tests/ -v -m \"not integration\""`.
|
|
180
|
+
|
|
181
|
+
### Coverage
|
|
182
|
+
|
|
183
|
+
- Aim for high coverage of core business logic. Use `pytest-cov` to measure:
|
|
184
|
+
```bash
|
|
185
|
+
timeout-dead --sec 60 "pytest tests/ --cov=src/timeout_dead --cov-report=term-missing"
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Environment & Configuration
|
|
189
|
+
|
|
190
|
+
- Use `pydantic.BaseModel` or `dataclasses.dataclass` for typed configuration classes. Use `pydantic-settings` to load `.env` into typed models.
|
|
191
|
+
- Load settings from environment variables (`.env`) — never hardcode environment-specific values.
|
|
192
|
+
- `.env.example` is a **committed template** — never use it directly in scripts or at runtime. It exists solely as documentation for developers.
|
|
193
|
+
- `.env` is the **actual runtime file** (git-ignored). Developers copy `.env.example` to `.env` and fill in their local values.
|
|
194
|
+
|
|
195
|
+
```python
|
|
196
|
+
from pydantic import BaseModel
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
class DatabaseConfig(BaseModel):
|
|
200
|
+
url: str
|
|
201
|
+
pool_size: int = 10
|
|
202
|
+
|
|
203
|
+
# ------------------------------------------------
|
|
204
|
+
|
|
205
|
+
class AppConfig(BaseModel):
|
|
206
|
+
db: DatabaseConfig
|
|
207
|
+
log_level: str = "INFO"
|
|
208
|
+
```
|