airename 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.
@@ -0,0 +1,41 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # OS-specific files
7
+ .DS_Store
8
+ .DS_Store?
9
+ ._*
10
+ .Spotlight-V100
11
+ .Trashes
12
+ ehthumbs.db
13
+ Thumbs.db
14
+
15
+ # Environments and Virtual Environments
16
+ .env
17
+ .venv
18
+ env/
19
+ venv/
20
+ ENV/
21
+
22
+ # Testing and Coverage
23
+ .pytest_cache/
24
+ .coverage
25
+ htmlcov/
26
+ test/
27
+
28
+ # Editor / IDE configuration
29
+ .vscode/
30
+ .idea/
31
+ *.suo
32
+ *.ntvs*
33
+ *.njsproj
34
+ *.sln
35
+ *.swp
36
+
37
+ # Packaging
38
+ dist/
39
+ build/
40
+ *.egg-info/
41
+
@@ -0,0 +1,31 @@
1
+ # AGENTS.md
2
+
3
+ ## Repo Shape
4
+ - `src/airename/__init__.py` contains all runtime logic and `main()` is the only entrypoint.
5
+ - `./airename` is a thin shim that does `from airename import main; main()`.
6
+ - `pyproject.toml` at root defines the package build (hatchling), metadata, and the `airename` console_scripts entry point.
7
+ - `test_airename.py` is the only automated test file; there is no lint/typecheck config, and no CI/workflow config in the repo.
8
+
9
+ ## Verified Commands
10
+ - Show CLI/help: `python3 -m airename --help`
11
+ - Run all tests: `python3 -m unittest test_airename.py`
12
+ - Run one test: `python3 -m unittest test_airename.TestAirename.test_watch_mode`
13
+ - Editable install: `pip install -e .` (run from repo root)
14
+
15
+ ## Python / Test Gotchas
16
+ - The repo works on Python 3.6+ for the current test suite and subprocess helpers because it uses `stdout/stderr=subprocess.PIPE` plus `universal_newlines=True` instead of the Python 3.7+ `capture_output=` and `text=` shortcuts.
17
+ - Tests execute `python -m airename` as a subprocess via `sys.executable` and set `HOME` to a temp directory. If you change config loading or CLI argument parsing, verify through the subprocess-based tests, not just by importing functions.
18
+ - The package must be installed (`pip install -e .`) before tests can run, or you must activate the venv it was installed into.
19
+ - Current tests use fake `.pdf` and `.png` files written as plain text. They cover extension-driven routing and fallback behavior, not real PDF/image parsing.
20
+
21
+ ## Behavior That Is Easy To Miss
22
+ - Config is loaded only from `~/.config/airename/airename.json` via `load_config()`. The loader strips `//`, `/* ... */`, and `#` comments before `json.loads`.
23
+ - Config aliases are real behavior: `interval` or `intervall`, `watch_dir` or `watch_dirs`, `gemini_api_key` or `api_keys.gemini`, `openai_api_key` or `api_keys.openai`.
24
+ - Backend selection is not only `--backend`: in `main()`, models containing `gemini` force the Gemini backend, and models containing `gpt-` or `openai` force the OpenAI-compatible backend.
25
+ - Watch mode only runs when `--watch` is set and no positional files are given. It recursively skips hidden directories and dotfiles, and only processes files after the size is unchanged for 2 poll cycles.
26
+ - Batch size is hard-coded to 30 files per API call in `main()`.
27
+ - `rename_batch()` preserves the original extension, keeps renamed files in the source directory, replaces `:` with `-`, and skips collisions unless `--force` is set.
28
+
29
+ ## External Dependency Notes
30
+ - Runtime is mostly stdlib. `pypdf` and `Pillow` are required dependencies (installed automatically). PDF text extraction prefers `pypdf`, then falls back to `pdftotext`; image datetime extraction prefers Pillow, then `exiftool`, then file mtime.
31
+ - Ollama is the only backend with a preflight connectivity check (`/api/tags`) before processing.
@@ -0,0 +1,174 @@
1
+ Metadata-Version: 2.4
2
+ Name: airename
3
+ Version: 0.1.0
4
+ Summary: AI-powered cross-platform batch file renaming
5
+ Project-URL: Homepage, https://github.com/j0ta29/airename
6
+ Project-URL: Repository, https://github.com/j0ta29/airename
7
+ Project-URL: Bug Tracker, https://github.com/j0ta29/airename/issues
8
+ Author-email: Jürgen Albert <jota@gmx.de>
9
+ License: MIT
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Environment :: Console
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Requires-Python: >=3.8
16
+ Requires-Dist: pillow
17
+ Requires-Dist: pypdf
18
+ Description-Content-Type: text/markdown
19
+
20
+ # airename
21
+
22
+ `airename` is a cross-platform, AI-powered command-line interface (CLI) tool written in Python that automatically renames files or directories using a local **Ollama** LLM or **Google Gemini API** based on their actual text, image, or PDF content and metadata.
23
+
24
+ Every filename is automatically structured with an extracted ISO date/datetime prefix.
25
+
26
+ ---
27
+
28
+ ## Features
29
+
30
+ - **Multi-Backend AI Support**:
31
+ - **Ollama**: Local, private, and free (using offline models like `llama3` or `gemma4`).
32
+ - **Google Gemini**: Remote, high-speed, and extremely smart (using models like `gemini-1.5-flash` or `gemini-1.5-pro`).
33
+ - **OpenAI-Compatible**: Remote or local high-speed processing (using standard OpenAI models like `gpt-4o-mini` or third-party compatible endpoints such as Groq, DeepSeek, LM Studio, etc.).
34
+ - **Configuration File Support (`~/.config/airename/airename.json`)**:
35
+ - Centralize your preferences. Configure default watch directories, standard models, chosen backend, custom intervals, API keys, and local URLs.
36
+ - **Content-Aware Renaming**:
37
+ - **Text Files**: Reads the first 4000 characters to extract a fitting, descriptive name and scan for document dates (like invoices, contracts, or letter headers).
38
+ - **PDF Files**: Uses `pypdf` to read the first 4000 characters of text from the PDF, treating it as text content for smart renaming.
39
+ - **Image Files**: Uses original names but prefixes them with their authentic photo-taken date extracted from EXIF metadata (via `Pillow`).
40
+ - **Recursive Watch Mode (`-w` / `--watch`)**:
41
+ - Continuously and recursively monitors a target directory tree for files lacking the ISO date/datetime prefix.
42
+ - **Write-Stability Safety**: Automatically tracks file size and only renames a file once it remains stable (unchanged) for at least 2 consecutive poll cycles. This prevents renaming active downloads or files currently being written.
43
+ - **High Performance**: Automatically batches files (up to 30 files per API call) to optimize LLM throughput.
44
+ - **Cross-Platform**: Run it seamlessly on macOS, Linux, and Windows.
45
+ - **Safety Features**:
46
+ - **Dry-Run mode (`-d` / `--dry-run`)**: Safely inspect proposed changes without renaming any files.
47
+ - **Interactive mode (`-i` / `--interactive`)**: Confirm each individual file rename with a quick terminal prompt.
48
+ - **Collision Prevention**: Warns and skips renaming if the target file name already exists on disk.
49
+
50
+ ---
51
+
52
+ ## Installation
53
+
54
+ ```bash
55
+ pip install airename
56
+ ```
57
+
58
+ For development:
59
+ ```bash
60
+ git clone https://github.com/j0ta29/airename.git
61
+ cd airename
62
+ pip install -e .
63
+ ```
64
+
65
+ ### Prerequisites
66
+
67
+ To use `airename`, you need:
68
+
69
+ 1. **Python 3.x**: Ensure Python is installed.
70
+ 2. **Pillow** (Recommended, for Image EXIF):
71
+ ```bash
72
+ pip install Pillow
73
+ ```
74
+ 3. **pypdf** (Recommended, for PDF content-awareness):
75
+ ```bash
76
+ pip install pypdf
77
+ ```
78
+
79
+ ### Backend Prerequisites:
80
+
81
+ - **For Ollama (Local)**:
82
+ - Download and install from [ollama.com](https://ollama.com/). Ensure the service is running (`ollama serve`).
83
+ - **For Google Gemini (Remote)**:
84
+ - Obtain a Gemini API Key from Google AI Studio.
85
+ - Export it as `GEMINI_API_KEY`, or configure it inside your `~/.config/airename/airename.json` file.
86
+ - **For OpenAI-Compatible Backends (Remote or Local)**:
87
+ - Obtain your API key from OpenAI (or your provider of choice).
88
+ - Export it as `OPENAI_API_KEY`, or configure it inside your `~/.config/airename/airename.json` file.
89
+
90
+ ---
91
+
92
+ ## Configuration File
93
+
94
+ `airename` automatically loads default options from a JSON configuration file located at `~/.config/airename/airename.json`.
95
+
96
+ Here is a complete schema example of `~/.config/airename/airename.json`:
97
+
98
+ ```json
99
+ {
100
+ "backend": "gemini",
101
+ "model": "gemini-1.5-flash",
102
+ "interval": 5,
103
+ "ollama_url": "http://localhost:11434",
104
+ "openai_url": "https://api.openai.com/v1",
105
+ "watch_dir": "/Users/username/Downloads",
106
+ "api_keys": {
107
+ "gemini": "AIzaSyYourKeyHere...",
108
+ "openai": "sk-proj-YourKeyHere..."
109
+ }
110
+ }
111
+ ```
112
+
113
+ ### Config File Fields
114
+
115
+ - `backend`: `"ollama"`, `"gemini"`, or `"openai"` (default: `ollama`).
116
+ - `model`: Default LLM model identifier (e.g. `llama3`, `gemma4`, `gemini-1.5-flash`, `gpt-4o-mini`).
117
+ - `interval` / `intervall`: Interval in seconds between directory scans in watch mode (default: `5`).
118
+ - `ollama_url`: Host address of your local Ollama server (default: `http://localhost:11434`).
119
+ - `openai_url`: API base URL for OpenAI-compatible providers (default: `https://api.openai.com/v1`).
120
+ - `watch_dir` / `watch_dirs`: Default directory path to recursively monitor if launched without a path argument.
121
+ - `gemini_api_key` or `api_keys.gemini`: Google Gemini API credentials.
122
+ - `openai_api_key` or `api_keys.openai`: OpenAI-compatible API credentials.
123
+
124
+ *Note: Any options passed as CLI flags (such as `-m` or `--interval`) will automatically override entries inside the config file.*
125
+ ## Usage
126
+
127
+ ```bash
128
+ airename [OPTIONS] [FILES...]
129
+ ```
130
+
131
+ ### Options
132
+
133
+ | Option | Long Option | Description |
134
+ | :--- | :--- | :--- |
135
+ | `-b <backend>`| `--backend <backend>` | Specify AI backend: `ollama`, `gemini`, or `openai` (default: `ollama`) |
136
+ | `-m <name>` | `--model <name>` | Specify the model to use (defaults: `llama3` for Ollama, `gemini-1.5-flash` for Gemini, `gpt-4o-mini` for OpenAI) |
137
+ | `-w <dir>` | `--watch <dir>` | Continuously and recursively watch a directory for unprocessed files |
138
+ | `--interval <sec>` | | The interval in seconds between directory watch scans (default: `5`) |
139
+ | `-d` | `--dry-run` | Show proposed changes without actually renaming files |
140
+ | `-i` | `--interactive` | Ask for confirmation before renaming each file |
141
+ | `-f` | `--force` | Overwrite existing files without warning |
142
+ | `-v` | `--verbose` | Print detailed debug / API payloads |
143
+ | | `--url <url>` | Override the default Ollama API URL (default: `http://localhost:11434`) |
144
+ | | `--openai-url <url>`| Override the default OpenAI API base URL (default: `https://api.openai.com/v1`) |
145
+ | `-h` | `--help` | Show the help message and exit |
146
+
147
+ ---
148
+
149
+ ## Examples
150
+
151
+ ### 1. Simple Run using Config Defaults
152
+ If you have configured `watch_dir`, `backend`, and `gemini` API keys inside your `~/.config/airename/airename.json` file, you can start recursively watching your folder simply by running:
153
+ ```bash
154
+ airename
155
+ ```
156
+
157
+ ### 2. Using Google Gemini Backend with CLI overrides
158
+ ```bash
159
+ airename -b gemini -d test/*
160
+ ```
161
+
162
+ ### 3. Continuous Recursive Watch Mode (Local Ollama)
163
+ ```bash
164
+ airename --watch ~/Downloads --interval 3 -m gemma4
165
+ ```
166
+
167
+ ---
168
+
169
+ ## Testing
170
+
171
+ To run tests:
172
+ ```bash
173
+ python3 test_airename.py
174
+ ```
@@ -0,0 +1,155 @@
1
+ # airename
2
+
3
+ `airename` is a cross-platform, AI-powered command-line interface (CLI) tool written in Python that automatically renames files or directories using a local **Ollama** LLM or **Google Gemini API** based on their actual text, image, or PDF content and metadata.
4
+
5
+ Every filename is automatically structured with an extracted ISO date/datetime prefix.
6
+
7
+ ---
8
+
9
+ ## Features
10
+
11
+ - **Multi-Backend AI Support**:
12
+ - **Ollama**: Local, private, and free (using offline models like `llama3` or `gemma4`).
13
+ - **Google Gemini**: Remote, high-speed, and extremely smart (using models like `gemini-1.5-flash` or `gemini-1.5-pro`).
14
+ - **OpenAI-Compatible**: Remote or local high-speed processing (using standard OpenAI models like `gpt-4o-mini` or third-party compatible endpoints such as Groq, DeepSeek, LM Studio, etc.).
15
+ - **Configuration File Support (`~/.config/airename/airename.json`)**:
16
+ - Centralize your preferences. Configure default watch directories, standard models, chosen backend, custom intervals, API keys, and local URLs.
17
+ - **Content-Aware Renaming**:
18
+ - **Text Files**: Reads the first 4000 characters to extract a fitting, descriptive name and scan for document dates (like invoices, contracts, or letter headers).
19
+ - **PDF Files**: Uses `pypdf` to read the first 4000 characters of text from the PDF, treating it as text content for smart renaming.
20
+ - **Image Files**: Uses original names but prefixes them with their authentic photo-taken date extracted from EXIF metadata (via `Pillow`).
21
+ - **Recursive Watch Mode (`-w` / `--watch`)**:
22
+ - Continuously and recursively monitors a target directory tree for files lacking the ISO date/datetime prefix.
23
+ - **Write-Stability Safety**: Automatically tracks file size and only renames a file once it remains stable (unchanged) for at least 2 consecutive poll cycles. This prevents renaming active downloads or files currently being written.
24
+ - **High Performance**: Automatically batches files (up to 30 files per API call) to optimize LLM throughput.
25
+ - **Cross-Platform**: Run it seamlessly on macOS, Linux, and Windows.
26
+ - **Safety Features**:
27
+ - **Dry-Run mode (`-d` / `--dry-run`)**: Safely inspect proposed changes without renaming any files.
28
+ - **Interactive mode (`-i` / `--interactive`)**: Confirm each individual file rename with a quick terminal prompt.
29
+ - **Collision Prevention**: Warns and skips renaming if the target file name already exists on disk.
30
+
31
+ ---
32
+
33
+ ## Installation
34
+
35
+ ```bash
36
+ pip install airename
37
+ ```
38
+
39
+ For development:
40
+ ```bash
41
+ git clone https://github.com/j0ta29/airename.git
42
+ cd airename
43
+ pip install -e .
44
+ ```
45
+
46
+ ### Prerequisites
47
+
48
+ To use `airename`, you need:
49
+
50
+ 1. **Python 3.x**: Ensure Python is installed.
51
+ 2. **Pillow** (Recommended, for Image EXIF):
52
+ ```bash
53
+ pip install Pillow
54
+ ```
55
+ 3. **pypdf** (Recommended, for PDF content-awareness):
56
+ ```bash
57
+ pip install pypdf
58
+ ```
59
+
60
+ ### Backend Prerequisites:
61
+
62
+ - **For Ollama (Local)**:
63
+ - Download and install from [ollama.com](https://ollama.com/). Ensure the service is running (`ollama serve`).
64
+ - **For Google Gemini (Remote)**:
65
+ - Obtain a Gemini API Key from Google AI Studio.
66
+ - Export it as `GEMINI_API_KEY`, or configure it inside your `~/.config/airename/airename.json` file.
67
+ - **For OpenAI-Compatible Backends (Remote or Local)**:
68
+ - Obtain your API key from OpenAI (or your provider of choice).
69
+ - Export it as `OPENAI_API_KEY`, or configure it inside your `~/.config/airename/airename.json` file.
70
+
71
+ ---
72
+
73
+ ## Configuration File
74
+
75
+ `airename` automatically loads default options from a JSON configuration file located at `~/.config/airename/airename.json`.
76
+
77
+ Here is a complete schema example of `~/.config/airename/airename.json`:
78
+
79
+ ```json
80
+ {
81
+ "backend": "gemini",
82
+ "model": "gemini-1.5-flash",
83
+ "interval": 5,
84
+ "ollama_url": "http://localhost:11434",
85
+ "openai_url": "https://api.openai.com/v1",
86
+ "watch_dir": "/Users/username/Downloads",
87
+ "api_keys": {
88
+ "gemini": "AIzaSyYourKeyHere...",
89
+ "openai": "sk-proj-YourKeyHere..."
90
+ }
91
+ }
92
+ ```
93
+
94
+ ### Config File Fields
95
+
96
+ - `backend`: `"ollama"`, `"gemini"`, or `"openai"` (default: `ollama`).
97
+ - `model`: Default LLM model identifier (e.g. `llama3`, `gemma4`, `gemini-1.5-flash`, `gpt-4o-mini`).
98
+ - `interval` / `intervall`: Interval in seconds between directory scans in watch mode (default: `5`).
99
+ - `ollama_url`: Host address of your local Ollama server (default: `http://localhost:11434`).
100
+ - `openai_url`: API base URL for OpenAI-compatible providers (default: `https://api.openai.com/v1`).
101
+ - `watch_dir` / `watch_dirs`: Default directory path to recursively monitor if launched without a path argument.
102
+ - `gemini_api_key` or `api_keys.gemini`: Google Gemini API credentials.
103
+ - `openai_api_key` or `api_keys.openai`: OpenAI-compatible API credentials.
104
+
105
+ *Note: Any options passed as CLI flags (such as `-m` or `--interval`) will automatically override entries inside the config file.*
106
+ ## Usage
107
+
108
+ ```bash
109
+ airename [OPTIONS] [FILES...]
110
+ ```
111
+
112
+ ### Options
113
+
114
+ | Option | Long Option | Description |
115
+ | :--- | :--- | :--- |
116
+ | `-b <backend>`| `--backend <backend>` | Specify AI backend: `ollama`, `gemini`, or `openai` (default: `ollama`) |
117
+ | `-m <name>` | `--model <name>` | Specify the model to use (defaults: `llama3` for Ollama, `gemini-1.5-flash` for Gemini, `gpt-4o-mini` for OpenAI) |
118
+ | `-w <dir>` | `--watch <dir>` | Continuously and recursively watch a directory for unprocessed files |
119
+ | `--interval <sec>` | | The interval in seconds between directory watch scans (default: `5`) |
120
+ | `-d` | `--dry-run` | Show proposed changes without actually renaming files |
121
+ | `-i` | `--interactive` | Ask for confirmation before renaming each file |
122
+ | `-f` | `--force` | Overwrite existing files without warning |
123
+ | `-v` | `--verbose` | Print detailed debug / API payloads |
124
+ | | `--url <url>` | Override the default Ollama API URL (default: `http://localhost:11434`) |
125
+ | | `--openai-url <url>`| Override the default OpenAI API base URL (default: `https://api.openai.com/v1`) |
126
+ | `-h` | `--help` | Show the help message and exit |
127
+
128
+ ---
129
+
130
+ ## Examples
131
+
132
+ ### 1. Simple Run using Config Defaults
133
+ If you have configured `watch_dir`, `backend`, and `gemini` API keys inside your `~/.config/airename/airename.json` file, you can start recursively watching your folder simply by running:
134
+ ```bash
135
+ airename
136
+ ```
137
+
138
+ ### 2. Using Google Gemini Backend with CLI overrides
139
+ ```bash
140
+ airename -b gemini -d test/*
141
+ ```
142
+
143
+ ### 3. Continuous Recursive Watch Mode (Local Ollama)
144
+ ```bash
145
+ airename --watch ~/Downloads --interval 3 -m gemma4
146
+ ```
147
+
148
+ ---
149
+
150
+ ## Testing
151
+
152
+ To run tests:
153
+ ```bash
154
+ python3 test_airename.py
155
+ ```
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env python3
2
+ from airename import main
3
+ main()
@@ -0,0 +1,4 @@
1
+ {
2
+ "$schema": "https://opencode.ai/config.json",
3
+ "lsp": true
4
+ }
@@ -0,0 +1,38 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "airename"
7
+ version = "0.1.0"
8
+ description = "AI-powered cross-platform batch file renaming"
9
+ readme = "README.md"
10
+ requires-python = ">=3.8"
11
+ license = {text = "MIT"}
12
+ authors = [
13
+ {name = "Jürgen Albert", email = "jota@gmx.de"}
14
+ ]
15
+
16
+ classifiers = [
17
+ "Development Status :: 4 - Beta",
18
+ "Environment :: Console",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Operating System :: OS Independent",
21
+ "Programming Language :: Python :: 3",
22
+ ]
23
+
24
+ dependencies = [
25
+ "pypdf",
26
+ "Pillow",
27
+ ]
28
+
29
+ [project.urls]
30
+ Homepage = "https://github.com/j0ta29/airename"
31
+ Repository = "https://github.com/j0ta29/airename"
32
+ "Bug Tracker" = "https://github.com/j0ta29/airename/issues"
33
+
34
+ [project.scripts]
35
+ airename = "airename:main"
36
+
37
+ [tool.hatch.build.targets.wheel]
38
+ packages = ["src/airename"]
@@ -0,0 +1,10 @@
1
+ {
2
+ "include": [
3
+ "airename",
4
+ "test_airename.py"
5
+ ],
6
+ "exclude": [
7
+ ".venv"
8
+ ],
9
+ "typeCheckingMode": "basic"
10
+ }