Skip to content

Commit 3e7c3bf

Browse files
committed
Enhance GitHub Actions workflow for improved artifact management
- Updated the GitHub Actions workflow to include additional metadata in the artifact name, improving clarity and traceability of build artifacts.
1 parent b3f00b2 commit 3e7c3bf

6 files changed

Lines changed: 471 additions & 0 deletions

File tree

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
---
2+
alwaysApply: true
3+
---
4+
# The fundamental development guideline for making any changes
5+
6+
# Running command in terminal
7+
8+
This project uses Nix to manage the development environment. Run `nix develop` once in every new terminal window to start the Nix environment. For AI agents, prefix terminal commands with `nix develop -c`:
9+
10+
```
11+
nix develop -c <command>
12+
```
13+
14+
**Git exception:** Run `git` directly (`git status`, `git diff`, `git commit`, etc.) — no Nix prefix.
15+
16+
## Run Tests
17+
18+
Always run all tests instead of just one test file:
19+
20+
```bash
21+
nix develop -c pytest # Run all tests
22+
nix develop -c make test # Same via Makefile
23+
```
24+
25+
## Run Tests and Format Checking
26+
27+
```bash
28+
nix develop -c make lint # pre-commit hooks (flake8, etc.)
29+
```
30+
31+
## Automated Test Practices
32+
33+
* All code and logic need to be covered by unit tests
34+
* Prefer end-to-end tests that exercise observable behavior (CLI output, translation results) over tests that mirror internal structure
35+
* Use VCR cassettes in `tests/fixtures/cassettes/` for HTTP-based provider tests; do not mock code unless it is about the file system

‎.cursor/rules/issue.mdc‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
description:
3+
globs:
4+
alwaysApply: true
5+
---
6+
7+
# When fixing an issue (e.g. from GitHub issues) please:
8+
9+
1. find where is the right place to add a new unit test to reproduce the issue
10+
2. add a new unit test
11+
3. run all tests to see if the test really fails
12+
4. fix the issue until all tests pass
13+
5. clean up
14+
6. run all unit tests at last to confirm things are still working.
15+
16+
follow [basic-development.mdc](mdc:.cursor/rules/basic-development.mdc)

‎.cursor/rules/translate-rule.mdc‎

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
---
2+
description:
3+
globs:
4+
alwaysApply: true
5+
---
6+
7+
# Adding a Translation Provider to Translate CLI
8+
9+
This guide explains how to add or modify support for translation providers in the translate-python CLI.
10+
11+
## Overview
12+
13+
Each provider is a class that inherits from `BaseProvider` and implements HTTP calls to a translation API. Integration points:
14+
15+
1. Provider class in `translate/providers/`
16+
2. Registration in `translate/providers/__init__.py`
17+
3. Mapping in `translate/translate.py` (`PROVIDERS_CLASS`)
18+
4. CLI options in `translate/main.py` (if the provider needs extra config)
19+
5. Tests in `tests/test_provider.py` and VCR cassettes in `tests/fixtures/cassettes/`
20+
21+
## Step-by-Step Guide
22+
23+
### 1. Create Provider Class
24+
25+
Create a new file in `translate/providers/` (e.g. `myprovider.py`):
26+
27+
```python
28+
from .base import BaseProvider
29+
from ..exceptions import TranslationError
30+
31+
class MyProvider(BaseProvider):
32+
name = 'MyProvider'
33+
base_url = 'https://api.example.com/translate'
34+
35+
def get_translation(self, text):
36+
response = self._make_request(text)
37+
# parse response and return translated string
38+
return translated_text
39+
```
40+
41+
Use `self.session` (a `requests.Session`) from `BaseProvider` for HTTP calls. Raise `TranslationError` for API failures.
42+
43+
### 2. Register the Provider
44+
45+
Add to `translate/providers/__init__.py`:
46+
47+
```python
48+
from .myprovider import MyProvider
49+
__all__ = [..., 'MyProvider']
50+
```
51+
52+
Add to `PROVIDERS_CLASS` in `translate/translate.py`:
53+
54+
```python
55+
PROVIDERS_CLASS = {
56+
...
57+
'myprovider': MyProvider,
58+
}
59+
```
60+
61+
### 3. Add CLI Support (if needed)
62+
63+
If the provider needs API keys or extra options, add Click options in `translate/main.py` and pass them through to `Translator`. Config file keys go in `get_config_info` options tuple and `sample-python-translate.cfg`.
64+
65+
### 4. Add Tests
66+
67+
Add unit tests in `tests/test_provider.py` for request construction and response parsing. For integration-style tests, add VCR cassettes under `tests/fixtures/cassettes/` and use the existing `vcr_conf.py` setup (see `tests/test_translate.py` for examples).
68+
69+
## Key Concepts
70+
71+
### BaseProvider
72+
73+
- Constructor accepts `to_lang`, `from_lang`, `secret_access_key`, `region`, `folder_id`, and `**kwargs`
74+
- Provides `self.session` for HTTP and default headers
75+
76+
### Translator
77+
78+
- Splits long text into chunks (`TRANSLATION_API_MAX_LENGTH`) before calling the provider
79+
- Selects provider by name from `PROVIDERS_CLASS`; defaults to MyMemory
80+
81+
### CLI Entry Point
82+
83+
- `translate-cli` is defined in `setup.py` as `translate.__main__:cli`
84+
- Tests for CLI behavior live in `tests/test_main.py`
85+
86+
## Best Practices
87+
88+
1. **Inheritance**: Extend `BaseProvider`; reuse `self.session` and constructor args
89+
2. **Testing**: Cover request params, error handling, and autodetect behavior; use VCR for real HTTP shapes
90+
3. **Documentation**: Update `docs/source/providers.rst` and `README.rst` when adding a provider
91+
4. **Secrets**: Never commit API keys; use config file or environment variables in tests
92+
93+
## Testing Your Implementation
94+
95+
```bash
96+
nix develop -c pytest # Run all tests
97+
nix develop -c pytest tests/test_provider.py # Provider tests only
98+
```
99+
100+
Reference existing implementations:
101+
- `mymemory_translated.py` for a simple GET-based API
102+
- `microsoft.py` / `deepl.py` for authenticated POST APIs
103+
- `yandex.py` for providers with extra CLI options (`folder_id`, IAM)
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
---
2+
name: post-change-refactor
3+
description: >-
4+
Refactor and clean up the uncommitted change before committing. Eliminate
5+
duplication, rename unclear domain concepts, collapse shotgun surgery when
6+
another similar change is likely, remove dead / test-only / redundant code,
7+
split files larger than 250 lines into cohesive modules, and confirm
8+
related tests still pass. Use after finishing a phase or sub-phase and
9+
before commit, or whenever the developer asks to clean up the current
10+
change. Triggers on: refactor change, clean up change, post-change
11+
refactor, before commit cleanup, tidy current change.
12+
---
13+
14+
# Post-Change Refactor — Clean the Current Change Before Commit
15+
16+
## When to use
17+
18+
- After the implementation of a phase / sub-phase finishes and **before**
19+
the commit.
20+
- On demand, when the developer asks to clean up or refactor the current
21+
uncommitted change.
22+
23+
Start with `.cursor/rules/` for project conventions and test practices.
24+
25+
## Scope: "the current change"
26+
27+
The current change = files touched since the last commit (staged + unstaged
28+
+ untracked). Discover the scope:
29+
30+
```bash
31+
git status
32+
git diff
33+
git diff --cached
34+
```
35+
36+
**Git does not use the Nix prefix.** All other repo tooling does.
37+
38+
All refactoring work is scoped to those files and the files that
39+
directly depend on them or are depended on by them. Do **not** sweep
40+
unrelated parts of the repo.
41+
42+
## Decision boundary
43+
44+
Only keep code that is justified by **the current change** or by the
45+
**immediate next phase** in the plan (if one exists).
46+
Anything justified only by a phase further out, or by "we might need it
47+
later", is speculative — remove it.
48+
49+
If there is no plan, justification must come entirely from the current
50+
change.
51+
52+
## Procedure
53+
54+
Run each check below in order. After all checks pass, **hand control back
55+
to the caller** — do **not** commit from inside this skill.
56+
57+
### 1. Duplication
58+
59+
- Look for **new** duplication introduced by the change (copy-pasted
60+
blocks, parallel structures with cosmetic differences).
61+
- Look for duplication the change made **visible** — the new code repeats
62+
logic that already existed elsewhere.
63+
- The same concept appearing in two representations counts as duplication,
64+
not just literal copies.
65+
- **Action**: collapse onto a single representation. Prefer reusing an
66+
existing helper in the right layer (provider, `Translator`, CLI) over
67+
inventing a new one.
68+
69+
### 2. Domain naming
70+
71+
- Read every new or renamed identifier — files, modules, classes,
72+
functions, variables, tests, fixtures.
73+
- Ask: does the name match what a domain reader expects? Does it match
74+
translate-python's language (providers, translation, CLI, languages,
75+
API keys, etc.)?
76+
- **Action**: rename when intent is unclear, misleading, mixes layers, or
77+
leaks phase numbers / sequence info. Names describe **capability**, not
78+
development history.
79+
80+
### 3. Shotgun surgery
81+
82+
- A change is shotgun surgery when **one logical concept** forces edits
83+
in many places.
84+
- Estimate the likelihood of another change of the same shape in the
85+
foreseeable future.
86+
- **Action**:
87+
- **High likelihood** → consolidate the scattered edits behind a single
88+
seam (one function, one config, one module) so the next change touches
89+
one place. Do it now.
90+
- **Low likelihood** → leave it. Do not preemptively abstract.
91+
92+
### 4. Dead / redundant / cancelling code
93+
94+
Remove aggressively whatever the change introduced or exposed that is not
95+
justified by the current change or the immediate next phase:
96+
97+
- Code with no caller.
98+
- Branches that cannot be reached.
99+
- Pairs of edits that cancel each other (added then immediately worked
100+
around, flag toggles that never flip, etc.).
101+
- Production code only exercised by unit tests — no real caller from the
102+
CLI (`translate-cli`), `Translator` API, or provider pipeline.
103+
- Unit tests that overlap with another test on the same observable
104+
surface (same input/output, same entry point).
105+
- Tests that pin internal structure rather than observable behavior — if
106+
a test mainly mirrors the code's factoring, drop it in favor of the
107+
test that drives a high-level entry point (`translate-cli`, `Translator.translate`,
108+
CLI output).
109+
110+
When in doubt, **delete**. The next phase, if relevant, will reintroduce
111+
only what it actually needs.
112+
113+
### 5. File size
114+
115+
For every file touched by the change, check line count:
116+
117+
```bash
118+
wc -l <path>
119+
```
120+
121+
- Files **over 250 lines** must be split. This rule is applied to test code as well.
122+
- Split along **cohesive seams** — one concept per module, not arbitrary
123+
line cuts.
124+
- Update imports. Keep the public API stable for callers outside the
125+
change.
126+
127+
### 6. Confirm related tests still pass
128+
129+
Run **related** tests for the changed files — not the whole suite. Use
130+
`nix develop -c …` for all commands below except `git`.
131+
132+
| Area touched | Focused command |
133+
|--------------|-----------------|
134+
| Core translation (`translate/translate.py`) | `nix develop -c pytest tests/test_translate.py` |
135+
| Provider (`translate/providers/`) | `nix develop -c pytest tests/test_provider.py` |
136+
| CLI / options (`translate/main.py`, `translate/__main__.py`) | `nix develop -c pytest tests/test_main.py` |
137+
| Broad or cross-cutting change | `nix develop -c pytest` |
138+
139+
Prefer CLI integration tests and VCR-backed translation tests over tests
140+
that only exercise internal helpers.
141+
142+
All related tests must pass before returning. If a test breaks because of
143+
the refactor (not the original change), fix it now.
144+
145+
## Return
146+
147+
Report a short summary to the caller:
148+
149+
1. Which checks led to changes — duplication / naming / shotgun /
150+
dead code / file size.
151+
2. Files renamed, extracted, split, or deleted.
152+
3. Which related tests were run and confirmed passing.
153+
154+
Then hand control back. **Do not commit from inside this skill** — the
155+
caller commits.
156+
157+
## Out of scope
158+
159+
- Do not redesign code outside the changed files.
160+
- Do not start a new phase or add new behavior. Only restructure and
161+
remove.
162+
- Do not run the entire test suite or trigger CI from inside this skill
163+
unless the change is broad enough that focused tests cannot cover it.

‎AGENTS.md‎

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# AGENTS.md
2+
3+
Guidance for Codex and other AI coding agents working in this repository.
4+
5+
Translate is a Python command-line translation tool with support for multiple providers (MyMemory, Microsoft, DeepL, LibreTranslate, Yandex).
6+
7+
Repo conventions live in `.cursor/rules/`:
8+
- **basic-development.mdc** — Nix environment, test commands, test practices
9+
- **issue.mdc** — workflow for fixing GitHub issues
10+
- **translate-rule.mdc** — how to add or modify translation providers
11+
12+
Run repo tooling with `nix develop -c …` unless you are already inside `nix develop`. **Git commands do not need the Nix prefix** — run `git` directly.
13+
14+
## Development Environment
15+
16+
This project uses Nix for environment management. Run `nix develop` once per terminal session, then install dependencies:
17+
18+
```bash
19+
pip install --user -r requirements-dev.txt
20+
```
21+
22+
## Common Commands
23+
24+
| Task | Command |
25+
|------|---------|
26+
| Run all tests | `nix develop -c pytest` |
27+
| Run tests via Makefile | `nix develop -c make test` |
28+
| Lint / format checks | `nix develop -c make lint` |
29+
| Build package | `nix develop -c make build` |
30+
31+
Always run the full test suite, not a single file, before finishing a task.
32+
33+
## Architecture
34+
35+
### Tech Stack
36+
37+
- **CLI:** Python, Click
38+
- **HTTP:** requests (via provider classes)
39+
- **Testing:** pytest, VCR.py (cassettes in `tests/fixtures/cassettes/`)
40+
- **Dev Environment:** Nix (`flake.nix`)
41+
42+
### Directory Structure
43+
44+
```
45+
translate-python/
46+
├── translate/ # Main package
47+
│ ├── __main__.py # CLI entry point (translate-cli)
48+
│ ├── main.py # Click commands and config
49+
│ ├── translate.py # Translator class and provider registry
50+
│ ├── providers/ # Translation provider implementations
51+
│ │ ├── base.py # BaseProvider ABC
52+
│ │ ├── mymemory_translated.py
53+
│ │ ├── microsoft.py
54+
│ │ ├── deepl.py
55+
│ │ ├── libre.py
56+
│ │ └── yandex.py
57+
│ ├── constants.py
58+
│ └── exceptions.py
59+
├── tests/ # pytest tests
60+
│ ├── test_main.py # CLI tests
61+
│ ├── test_translate.py # Translator integration (VCR)
62+
│ └── test_provider.py # Provider unit tests
63+
├── docs/ # Sphinx documentation
64+
├── flake.nix # Nix dev environment
65+
└── pytest.ini # pytest config (--cov=translate)
66+
```
67+
68+
## Code Conventions
69+
70+
- Test observable behavior: CLI output, translated text, error messages
71+
- Use VCR cassettes for HTTP provider tests instead of live API calls
72+
- Raise `TranslationError` from providers on API failures
73+
- Register new providers in `PROVIDERS_CLASS` and `translate/providers/__init__.py`
74+
75+
## Skills
76+
77+
- **post-change-refactor** (`.cursor/skills/post-change-refactor/SKILL.md`) — clean up uncommitted changes before commit

0 commit comments

Comments
 (0)