|
| 1 | +--- |
| 2 | +applyTo: "**/*.py" |
| 3 | +--- |
| 4 | + |
| 5 | +# Project General Coding Standards |
| 6 | + |
| 7 | +## Python Version Support |
| 8 | + |
| 9 | +- Target Python 3.12 and 3.13 |
| 10 | +- Use modern Python features supported by the minimum version (3.12) |
| 11 | +- Avoid deprecated features and use future-proof syntax |
| 12 | + |
| 13 | +## Naming Conventions |
| 14 | + |
| 15 | +- Use snake_case for variable and function names |
| 16 | +- Use CamelCase for class names |
| 17 | +- Follow PEP 8 style guidelines strictly |
| 18 | +- Prefix private class members with underscore (\_) |
| 19 | +- Use ALL_CAPS for constants |
| 20 | +- Use descriptive names that clearly indicate purpose and content |
| 21 | +- Avoid single-letter variable names except for loop counters or mathematical contexts |
| 22 | + |
| 23 | +## Type Annotations |
| 24 | + |
| 25 | +- Use type annotations for ALL function and method parameters, return types, and variables (PEP 484) |
| 26 | +- Use modern built-in generics: `list`, `dict`, `set`, `tuple` instead of `List`, `Dict`, `Set`, `Tuple` from `typing` |
| 27 | +- Use `None` type for optional parameters: `str | None` instead of `Optional[str]` |
| 28 | +- Use union types with `|` operator: `int | str` instead of `Union[int, str]` |
| 29 | +- For complex types, import from `collections.abc`: `Callable`, `Iterable`, etc. |
| 30 | +- Always specify generic types: use `list[str]` not just `list` |
| 31 | +- Use `pathlib.Path` for file paths, not `str` |
| 32 | + |
| 33 | +## Error Handling |
| 34 | + |
| 35 | +- Use try/except blocks for operations that may fail |
| 36 | +- Always log errors with contextual information using the project's logger |
| 37 | +- Catch specific exceptions, avoid bare `except:` clauses |
| 38 | +- Use `finally` blocks for cleanup operations |
| 39 | +- For HTTP operations with requests library: |
| 40 | + - Use timeout parameter (default: `REQUESTS_TIMEOUT_SEC`) |
| 41 | + - Implement retry logic with `requests.adapters.Retry` for network operations |
| 42 | + - Always close response objects in `finally` blocks or use context managers |
| 43 | +- For file operations: |
| 44 | + - Use context managers (`with` statement) for file handling |
| 45 | + - Use `pathlib.Path` methods for path operations |
| 46 | + - Handle `OSError` and its subclasses appropriately |
| 47 | + |
| 48 | +## Code Style and Formatting |
| 49 | + |
| 50 | +- Line length: maximum 120 characters (as configured in Black and Ruff) |
| 51 | +- Use Black formatting style with preview features enabled |
| 52 | +- Follow isort configuration for import ordering: |
| 53 | + 1. FUTURE |
| 54 | + 2. TYPING |
| 55 | + 3. STDLIB |
| 56 | + 4. THIRDPARTY |
| 57 | + 5. FIRSTPARTY |
| 58 | + 6. LOCALFOLDER |
| 59 | +- Include trailing commas in multi-line constructs |
| 60 | +- Use more blank lines to achieve better code organization and readability |
| 61 | +- Use 4 spaces for indentation (no tabs) |
| 62 | + |
| 63 | +## Modern Python Features |
| 64 | + |
| 65 | +- Follow PEP 492 – Coroutines with async and await syntax (when applicable) |
| 66 | +- Follow PEP 498 – Literal String Interpolation (f-strings) |
| 67 | +- Follow PEP 572 – Assignment Expressions (walrus operator `:=` when it improves readability) |
| 68 | +- Use structural pattern matching (match/case) for Python 3.10+ when appropriate |
| 69 | +- Prefer pathlib.Path over os.path for file operations |
| 70 | +- Use Enum and StrEnum for constants with related values |
| 71 | +- Use dataclasses or dataclasses-json for structured data |
| 72 | + |
| 73 | +## Concurrency and Threading |
| 74 | + |
| 75 | +- Use `concurrent.futures.ThreadPoolExecutor` for I/O-bound parallel operations |
| 76 | +- Always use context managers with executors |
| 77 | +- Set appropriate `max_workers` based on operation type (use configuration values) |
| 78 | +- Handle futures with `futures.as_completed()` for better responsiveness |
| 79 | +- Implement abort/cancellation mechanisms using `threading.Event` |
| 80 | +- Cancel pending futures when aborting operations |
| 81 | +- Use thread-safe data structures when sharing data between threads |
| 82 | +- Avoid blocking operations in GUI threads |
| 83 | + |
| 84 | +## Resource Management |
| 85 | + |
| 86 | +- Always use context managers (`with` statements) for: |
| 87 | + - File operations |
| 88 | + - Network connections |
| 89 | + - Thread pools and executors |
| 90 | + - Temporary directories and files |
| 91 | +- Use `tempfile.TemporaryDirectory` with `ignore_cleanup_errors=True` for temp operations |
| 92 | +- Close network responses explicitly in `finally` blocks or use context managers |
| 93 | +- Clean up temporary files after processing |
| 94 | +- Use `pathlib.Path.unlink(missing_ok=True)` for safe file deletion |
| 95 | + |
| 96 | +## File and Path Handling |
| 97 | + |
| 98 | +- Use `pathlib.Path` exclusively for path operations |
| 99 | +- Sanitize file paths using `pathvalidate.sanitize_filename` and project's `path_file_sanitize` |
| 100 | +- Use `.expanduser()` for paths that may contain `~` |
| 101 | +- Use `.absolute()` to get absolute paths |
| 102 | +- Use `.resolve()` to resolve symlinks |
| 103 | +- Check file existence with `Path.exists()`, `Path.is_file()`, `Path.is_dir()` |
| 104 | +- Use `os.makedirs(path, exist_ok=True)` or `Path.mkdir(parents=True, exist_ok=True)` |
| 105 | +- Handle cross-platform path differences automatically with pathlib |
| 106 | + |
| 107 | +## Code Documentation |
| 108 | + |
| 109 | +- Write docstrings for ALL modules, classes, functions, and methods using Google docstring style |
| 110 | +- Include type information in docstrings even when type hints are present |
| 111 | +- Document all parameters with their types and descriptions |
| 112 | +- Document return values with type and description |
| 113 | +- Document raised exceptions |
| 114 | +- Use line comments to explain complex logic, algorithms, or non-obvious decisions |
| 115 | +- When refactoring code: |
| 116 | + - Update or add docstrings to reflect new behavior |
| 117 | + - Update existing line comments rather than removing them |
| 118 | + - Add TODO comments for known limitations or future improvements |
| 119 | + |
| 120 | +## Logging |
| 121 | + |
| 122 | +- Use the project's logger (via `fn_logger` or similar) |
| 123 | +- Log levels: |
| 124 | + - `debug`: Detailed diagnostic information |
| 125 | + - `info`: General informational messages (e.g., download completion) |
| 126 | + - `error`: Error conditions with context |
| 127 | + - `exception`: Errors with full traceback |
| 128 | +- Include relevant context in log messages (file names, IDs, URLs, etc.) |
| 129 | +- Use f-strings for log message formatting |
| 130 | + |
| 131 | +## GUI Development (PySide6/Qt) |
| 132 | + |
| 133 | +- Follow Qt naming conventions for slots and signals |
| 134 | +- Use type hints for signal parameters |
| 135 | +- Emit signals for cross-thread communication (never call GUI methods directly from worker threads) |
| 136 | +- Use Qt's threading mechanisms appropriately |
| 137 | +- Handle GUI progress updates via signals |
| 138 | +- Implement proper cleanup in close events |
| 139 | +- Use `QThread` or `ThreadPoolExecutor` for background operations, never block the GUI thread |
| 140 | + |
| 141 | +## API Integration (TIDAL) |
| 142 | + |
| 143 | +- Always check if media is available before processing (`media.available`) |
| 144 | +- Handle `tidalapi.exceptions.TooManyRequests` gracefully |
| 145 | +- Implement retry logic for transient failures |
| 146 | +- Use sessions appropriately |
| 147 | +- Handle stream manifests and encryption properly |
| 148 | +- Respect API rate limits and implement delays when configured |
| 149 | + |
| 150 | +## Testing |
| 151 | + |
| 152 | +- Place tests in the `tests/` directory |
| 153 | +- Use pytest as the testing framework |
| 154 | +- Use descriptive test function names: `test_<functionality_being_tested>` |
| 155 | +- Test edge cases: empty lists, None values, invalid inputs |
| 156 | +- Mock external dependencies (API calls, file system when appropriate) |
| 157 | +- Use fixtures for common test setup |
| 158 | +- Aim for meaningful test coverage, not just high percentages |
| 159 | + |
| 160 | +## Security |
| 161 | + |
| 162 | +- Never hardcode credentials (use configuration or environment variables) |
| 163 | +- Use base64 encoding only for obfuscation, not security |
| 164 | +- Handle sensitive data (tokens, keys) carefully |
| 165 | +- Use secure temporary file creation |
| 166 | +- Validate and sanitize all user inputs, especially file paths |
| 167 | +- Handle decryption keys securely (don't log them) |
| 168 | + |
| 169 | +## Performance |
| 170 | + |
| 171 | +- Use generators for large datasets when possible |
| 172 | +- Implement streaming for large file downloads |
| 173 | +- Use appropriate chunk sizes for file I/O (use `CHUNK_SIZE` constant) |
| 174 | +- Cache expensive computations when safe to do so |
| 175 | +- Use batch operations where applicable |
| 176 | +- Profile code before optimizing |
| 177 | +- Consider memory usage for large collections |
| 178 | + |
| 179 | +## Configuration and Settings |
| 180 | + |
| 181 | +- Use the Settings class for all configuration |
| 182 | +- Access settings via `self.settings.data.*` |
| 183 | +- Validate configuration values |
| 184 | +- Provide sensible defaults |
| 185 | +- Use type-safe configuration access |
| 186 | +- Document configuration options |
| 187 | + |
| 188 | +## Code Quality Tools |
| 189 | + |
| 190 | +- Run Ruff for linting before committing |
| 191 | +- Run Black for formatting before committing |
| 192 | +- Run mypy for type checking |
| 193 | +- Use pre-commit hooks to automate checks |
| 194 | +- Address all linting warnings and errors |
| 195 | +- Keep code complexity low (avoid deep nesting, long functions) |
| 196 | + |
| 197 | +## Best Practices Summary |
| 198 | + |
| 199 | +1. **Type Safety**: Always use type hints, enable strict mypy checks |
| 200 | +2. **Error Handling**: Catch specific exceptions, log with context, clean up resources |
| 201 | +3. **Readability**: Write self-documenting code with clear names and structure |
| 202 | +4. **Documentation**: Comprehensive docstrings and comments for complex logic |
| 203 | +5. **Testing**: Test edge cases and error conditions |
| 204 | +6. **Performance**: Use efficient algorithms and data structures |
| 205 | +7. **Maintainability**: Keep functions focused, avoid code duplication |
| 206 | +8. **Security**: Validate inputs, handle credentials safely |
| 207 | +9. **Compatibility**: Support Python 3.12-3.13, handle cross-platform differences |
| 208 | +10. **Standards**: Follow PEP 8, PEP 484, and project-specific configurations |
0 commit comments