This file is a merged representation of a subset of the codebase, containing files not matching ignore patterns, combined into a single document by Repomix. The content has been processed where empty lines have been removed.

================================================================
File Summary
================================================================

Purpose:
--------
This file contains a packed representation of the entire repository's contents.
It is designed to be easily consumable by AI systems for analysis, code review,
or other automated processes.

File Format:
------------
The content is organized as follows:
1. This summary section
2. Repository information
3. Directory structure
4. Multiple file entries, each consisting of:
  a. A separator line (================)
  b. The file path (File: path/to/file)
  c. Another separator line
  d. The full contents of the file
  e. A blank line

Usage Guidelines:
-----------------
- This file should be treated as read-only. Any changes should be made to the
  original repository files, not this packed version.
- When processing this file, use the file path to distinguish
  between different files in the repository.
- Be aware that this file may contain sensitive information. Handle it with
  the same level of security as you would the original repository.

Notes:
------
- Some files may have been excluded based on .gitignore rules and Repomix's configuration
- Binary files are not included in this packed representation. Please refer to the Repository Structure section for a complete list of file paths, including binary files
- Files matching these patterns are excluded: .specstory/**/*.md, .venv/**, _private/**, CLEANUP.txt, **/*.json, *.lock
- Files matching patterns in .gitignore are excluded
- Files matching default ignore patterns are excluded
- Empty lines have been removed from all files

Additional Info:
----------------

================================================================
Directory Structure
================================================================
.cursor/
  rules/
    0project.mdc
    cleanup.mdc
    filetree.mdc
    quality.mdc
.github/
  workflows/
    push.yml
    release.yml
src/
  twat/
    __init__.py
tests/
  test_twat.py
  VERSION.txt
.gitignore
.pre-commit-config.yaml
cleanup.py
LICENSE
LOG.md
pyproject.toml
README.md
TODO-ALL.md
VERSION.txt

================================================================
Files
================================================================

================
File: .cursor/rules/0project.mdc
================
---
description: About this project
globs:
---
# About this project

`twat-fs` is a file system utility library focused on robust and extensible file upload capabilities with multiple provider support. It provides:

- Multi-provider upload system with smart fallback (catbox.moe default, plus Dropbox, S3, etc.)
- Automatic retry for temporary failures, fallback for permanent ones
- URL validation and clean developer experience with type hints
- Simple CLI: `python -m twat_fs upload_file path/to/file.txt`
- Easy installation: `uv pip install twat-fs` (basic) or `uv pip install 'twat-fs[all,dev]'` (all features)

## Development Notes
- Uses `uv` for Python package management
- Quality tools: ruff, mypy, pytest
- Clear provider protocol for adding new storage backends
- Strong typing and runtime checks throughout

================
File: .cursor/rules/cleanup.mdc
================
---
description: Run `cleanup.py` script before and after changes
globs: 
---
Before you do any changes or if I say "cleanup", run the `cleanup.py update` script in the main folder. Analyze the results, describe recent changes in @LOG.md and edit @TODO.md to update priorities and plan next changes. PERFORM THE CHANGES, then run the `cleanup.py status` script and react to the results.

When you edit @TODO.md, lead in lines with empty GFM checkboxes if things aren't done (`- [ ] `) vs. filled (`- [x] `) if done.

================
File: .cursor/rules/filetree.mdc
================
---
description: File tree of the project
globs: 
---
[ 896]  .
├── [  64]  .benchmarks
├── [  96]  .cursor
│   └── [ 224]  rules
│       ├── [ 821]  0project.mdc
│       ├── [ 516]  cleanup.mdc
│       ├── [1.3K]  filetree.mdc
│       └── [2.0K]  quality.mdc
├── [  96]  .github
│   └── [ 128]  workflows
│       ├── [2.7K]  push.yml
│       └── [1.4K]  release.yml
├── [3.6K]  .gitignore
├── [ 470]  .pre-commit-config.yaml
├── [ 987]  CLEANUP.txt
├── [1.0K]  LICENSE
├── [2.7K]  LOG.md
├── [4.2K]  README.md
├── [ 60K]  REPO_CONTENT.txt
├── [3.9K]  TODO-ALL.md
├── [   7]  VERSION.txt
├── [ 13K]  cleanup.py
├── [ 160]  dist
├── [ 160]  plugins
│   └── [  64]  .benchmarks
├── [6.3K]  pyproject.toml
├── [1.9M]  repomix-output.txt
├── [ 128]  src
│   └── [ 224]  twat
│       └── [2.1K]  __init__.py
└── [ 192]  tests
    ├── [   8]  VERSION.txt
    └── [ 136]  test_twat.py

12 directories, 21 files

================
File: .cursor/rules/quality.mdc
================
---
description: Quality
globs: 
---
- **Verify Information**: Always verify information before presenting it. Do not make assumptions or speculate without clear evidence.
- **No Apologies**: Never use apologies.
- **No Whitespace Suggestions**: Don't suggest whitespace changes.
- **No Inventions**: Don't invent major changes other than what's explicitly requested.
- **No Unnecessary Confirmations**: Don't ask for confirmation of information already provided in the context.
- **Preserve Existing Code**: Don't remove unrelated code or functionalities. Pay attention to preserving existing structures.
- **No Implementation Checks**: Don't ask the user to verify implementations that are visible in the provided context.
- **No Unnecessary Updates**: Don't suggest updates or changes to files when there are no actual modifications needed.
- **No Current Implementation**: Don't show or discuss the current implementation unless specifically requested.
- **Use Explicit Variable Names**: Prefer descriptive, explicit variable names over short, ambiguous ones to enhance code readability.
- **Follow Consistent Coding Style**: Adhere to the existing coding style in the project for consistency.
- **Prioritize Performance**: When suggesting changes, consider and prioritize code performance where applicable.
- **Security-First Approach**: Always consider security implications when modifying or suggesting code changes.
- **Test Coverage**: Suggest or include appropriate unit tests for new or modified code.
- **Error Handling**: Implement robust error handling and logging where necessary.
- **Modular Design**: Encourage modular design principles to improve code maintainability and reusability.
- **Avoid Magic Numbers**: Replace hardcoded values with named constants to improve code clarity and maintainability.
- **Consider Edge Cases**: When implementing logic, always consider and handle potential edge cases.
- **Use Assertions**: Include assertions wherever possible to validate assumptions and catch potential errors early.

================
File: .github/workflows/push.yml
================
name: Build & Test
on:
  push:
    branches: [main]
    tags-ignore: ["v*"]
  pull_request:
    branches: [main]
  workflow_dispatch:
permissions:
  contents: write
  id-token: write
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true
jobs:
  quality:
    name: Code Quality
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - name: Run Ruff lint
        uses: astral-sh/ruff-action@v3
        with:
          version: "latest"
          args: "check --output-format=github"
      - name: Run Ruff Format
        uses: astral-sh/ruff-action@v3
        with:
          version: "latest"
          args: "format --check --respect-gitignore"
  test:
    name: Run Tests
    needs: quality
    strategy:
      matrix:
        python-version: ["3.10"]
        os: [ubuntu-latest]
      fail-fast: true
    runs-on: ${{ matrix.os }}
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}
      - name: Install UV
        uses: astral-sh/setup-uv@v5
        with:
          version: "latest"
          python-version: ${{ matrix.python-version }}
          enable-cache: true
          cache-suffix: ${{ matrix.os }}-${{ matrix.python-version }}
      - name: Install test dependencies
        run: |
          uv pip install --system --upgrade pip
          uv pip install --system ".[test]"
      - name: Run tests with Pytest
        run: uv run pytest -n auto --maxfail=1 --disable-warnings --cov-report=xml --cov-config=pyproject.toml --cov=src/twat --cov=tests tests/
      - name: Upload coverage report
        uses: actions/upload-artifact@v4
        with:
          name: coverage-${{ matrix.python-version }}-${{ matrix.os }}
          path: coverage.xml
  build:
    name: Build Distribution
    needs: test
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.12"
      - name: Install UV
        uses: astral-sh/setup-uv@v5
        with:
          version: "latest"
          python-version: "3.12"
          enable-cache: true
      - name: Install build tools
        run: uv pip install build hatchling hatch-vcs
      - name: Build distributions
        run: uv run python -m build --outdir dist
      - name: Upload distribution artifacts
        uses: actions/upload-artifact@v4
        with:
          name: dist-files
          path: dist/
          retention-days: 5

================
File: .github/workflows/release.yml
================
name: Release
on:
  push:
    tags: ["v*"]
permissions:
  contents: write
  id-token: write
jobs:
  release:
    name: Release to PyPI
    runs-on: ubuntu-latest
    environment:
      name: pypi
      url: https://pypi.org/p/twat
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.12"
      - name: Install UV
        uses: astral-sh/setup-uv@v5
        with:
          version: "latest"
          python-version: "3.12"
          enable-cache: true
      - name: Install build tools
        run: uv pip install build hatchling hatch-vcs
      - name: Build distributions
        run: uv run python -m build --outdir dist
      - name: Verify distribution files
        run: |
          ls -la dist/
          test -n "$(find dist -name '*.whl')" || (echo "Wheel file missing" && exit 1)
          test -n "$(find dist -name '*.tar.gz')" || (echo "Source distribution missing" && exit 1)
      - name: Publish to PyPI
        uses: pypa/gh-action-pypi-publish@release/v1
        with:
          password: ${{ secrets.PYPI_TOKEN }}
      - name: Create GitHub Release
        uses: softprops/action-gh-release@v1
        with:
          files: dist/*
          generate_release_notes: true
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

================
File: src/twat/__init__.py
================
__version__ = metadata.version(__name__)
def _load_plugin(name: str) -> ModuleType | None:
        eps = metadata.entry_points(group="twat.plugins")
                plugin = ep.load()
def __getattr__(name: str) -> Any:
    plugin = _load_plugin(name)
    raise AttributeError(msg)
def run_plugin(plugin_name: str) -> NoReturn:
                if hasattr(plugin, "main"):
                    plugin.main()
                    sys.exit(0)
                    sys.exit(1)
def main() -> NoReturn:
    if len(sys.argv) < 2:
    run_plugin(plugin_name)

================
File: tests/test_twat.py
================
def test_version():

================
File: tests/VERSION.txt
================
v1.7.12

================
File: .gitignore
================
plugins/repos/
*_autogen/
.DS_Store
__version__.py
__pycache__/
_Chutzpah*
_deps
_NCrunch_*
_pkginfo.txt
_Pvt_Extensions
_ReSharper*/
_TeamCity*
_UpgradeReport_Files/
!?*.[Cc]ache/
!.axoCover/settings.json
!.vscode/extensions.json
!.vscode/launch.json
!.vscode/settings.json
!.vscode/tasks.json
!**/[Pp]ackages/build/
!Directory.Build.rsp
.*crunch*.local.xml
.axoCover/*
.builds
.cr/personal
.fake/
.history/
.ionide/
.localhistory/
.mfractor/
.ntvs_analysis.dat
.paket/paket.exe
.sass-cache/
.vs/
.vscode
.vscode/*
.vshistory/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
[Bb]in/
[Bb]uild[Ll]og.*
[Dd]ebug/
[Dd]ebugPS/
[Dd]ebugPublic/
[Ee]xpress/
[Ll]og/
[Ll]ogs/
[Oo]bj/
[Rr]elease/
[Rr]eleasePS/
[Rr]eleases/
[Tt]est[Rr]esult*/
[Ww][Ii][Nn]32/
*_h.h
*_i.c
*_p.c
*_wpftmp.csproj
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
*- [Bb]ackup.rdl
*.[Cc]ache
*.[Pp]ublish.xml
*.[Rr]e[Ss]harper
*.a
*.app
*.appx
*.appxbundle
*.appxupload
*.aps
*.azurePubxml
*.bim_*.settings
*.bim.layout
*.binlog
*.btm.cs
*.btp.cs
*.build.csdef
*.cab
*.cachefile
*.code-workspace
*.coverage
*.coveragexml
*.d
*.dbmdl
*.dbproj.schemaview
*.dll
*.dotCover
*.DotSettings.user
*.dsp
*.dsw
*.dylib
*.e2e
*.exe
*.gch
*.GhostDoc.xml
*.gpState
*.ilk
*.iobj
*.ipdb
*.jfm
*.jmconfig
*.la
*.lai
*.ldf
*.lib
*.lo
*.log
*.mdf
*.meta
*.mm.*
*.mod
*.msi
*.msix
*.msm
*.msp
*.ncb
*.ndf
*.nuget.props
*.nuget.targets
*.nupkg
*.nvuser
*.o
*.obj
*.odx.cs
*.opendb
*.opensdf
*.opt
*.out
*.pch
*.pdb
*.pfx
*.pgc
*.pgd
*.pidb
*.plg
*.psess
*.publishproj
*.publishsettings
*.pubxml
*.pyc
*.rdl.data
*.rptproj.bak
*.rptproj.rsuser
*.rsp
*.rsuser
*.sap
*.sbr
*.scc
*.sdf
*.sln.docstates
*.sln.iml
*.slo
*.smod
*.snupkg
*.so
*.suo
*.svclog
*.tlb
*.tlh
*.tli
*.tlog
*.tmp
*.tmp_proj
*.tss
*.user
*.userosscache
*.userprefs
*.vbp
*.vbw
*.VC.db
*.VC.VC.opendb
*.VisualState.xml
*.vsp
*.vspscc
*.vspx
*.vssscc
*.xsd.cs
**/[Pp]ackages/*
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.HTMLClient/GeneratedArtifacts
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
*~
~$*
$tf/
AppPackages/
artifacts/
ASALocalRun/
AutoTest.Net/
Backup*/
BenchmarkDotNet.Artifacts/
bld/
BundleArtifacts/
ClientBin/
cmake_install.cmake
CMakeCache.txt
CMakeFiles
CMakeLists.txt.user
CMakeScripts
CMakeUserPresets.json
compile_commands.json
coverage*.info
coverage*.json
coverage*.xml
csx/
CTestTestfile.cmake
dlldata.c
DocProject/buildhelp/
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/*.HxC
DocProject/Help/*.HxT
DocProject/Help/html
DocProject/Help/Html2
ecf/
FakesAssemblies/
FodyWeavers.xsd
Generated_Code/
Generated\ Files/
healthchecksdb
install_manifest.txt
ipch/
Makefile
MigrationBackup/
mono_crash.*
nCrunchTemp_*
node_modules/
nunit-*.xml
OpenCover/
orleans.codegen.cs
Package.StoreAssociation.xml
paket-files/
project.fragment.lock.json
project.lock.json
publish/
PublishScripts/
rcf/
ScaffoldingReadMe.txt
ServiceFabricBackup/
StyleCopReport.xml
Testing
TestResult.xml
UpgradeLog*.htm
UpgradeLog*.XML
x64/
x86/
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# Distribution / packaging
!dist/.gitkeep

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
.ruff_cache/

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# IDE
.idea/
.vscode/
*.swp
*.swo
*~

# OS
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db

# Project specific
__version__.py
_private

================
File: .pre-commit-config.yaml
================
repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.3.4
    hooks:
      - id: ruff
        args: [--fix]
      - id: ruff-format
        args: [--respect-gitignore]
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.5.0
    hooks:
      - id: check-yaml
      - id: check-toml
      - id: check-added-large-files
      - id: debug-statements
      - id: check-case-conflict
      - id: mixed-line-ending
        args: [--fix=lf]

================
File: cleanup.py
================
LOG_FILE = Path("CLEANUP.txt")
os.chdir(Path(__file__).parent)
def new() -> None:
    if LOG_FILE.exists():
        LOG_FILE.unlink()
def prefix() -> None:
    readme = Path(".cursor/rules/0project.mdc")
    if readme.exists():
        log_message("\n=== PROJECT STATEMENT ===")
        content = readme.read_text()
        log_message(content)
def suffix() -> None:
    todo = Path("TODO.md")
    if todo.exists():
        log_message("\n=== TODO.md ===")
        content = todo.read_text()
def log_message(message: str) -> None:
    timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S")
    with LOG_FILE.open("a") as f:
        f.write(log_line)
def run_command(cmd: list[str], check: bool = True) -> subprocess.CompletedProcess:
        result = subprocess.run(
            log_message(result.stdout)
        log_message(f"Command failed: {' '.join(cmd)}")
        log_message(f"Error: {e.stderr}")
        return subprocess.CompletedProcess(cmd, 1, "", str(e))
def check_command_exists(cmd: str) -> bool:
        return which(cmd) is not None
class Cleanup:
    def __init__(self) -> None:
        self.workspace = Path.cwd()
    def _print_header(self, message: str) -> None:
        log_message(f"\n=== {message} ===")
    def _check_required_files(self) -> bool:
            if not (self.workspace / file).exists():
                log_message(f"Error: {file} is missing")
    def _generate_tree(self) -> None:
        if not check_command_exists("tree"):
            log_message("Warning: 'tree' command not found. Skipping tree generation.")
            rules_dir = Path(".cursor/rules")
            rules_dir.mkdir(parents=True, exist_ok=True)
            tree_result = run_command(["tree", "-a", "-I", ".git", "--gitignore", "-n", "-h", "-I", "*_cache"])
            with open(rules_dir / "filetree.mdc", "w") as f:
                f.write("---\ndescription: File tree of the project\nglobs: \n---\n")
                f.write(tree_text)
            log_message("\nProject structure:")
            log_message(tree_text)
            log_message(f"Failed to generate tree: {e}")
    def _git_status(self) -> bool:
        result = run_command(["git", "status", "--porcelain"], check=False)
        return bool(result.stdout.strip())
    def _venv(self) -> None:
        log_message("Setting up virtual environment")
            run_command(["uv", "venv"])
            if venv_path.exists():
                os.environ["VIRTUAL_ENV"] = str(self.workspace / ".venv")
                log_message("Virtual environment created and activated")
                log_message("Virtual environment created but activation failed")
            log_message(f"Failed to create virtual environment: {e}")
    def _install(self) -> None:
        log_message("Installing package with all extras")
            self._venv()
            run_command(["uv", "pip", "install", "-e", ".[test,dev]"])
            log_message("Package installed successfully")
            log_message(f"Failed to install package: {e}")
    def _run_checks(self) -> None:
        log_message("Running code quality checks")
            log_message(">>> Running code fixes...")
            run_command(
            log_message(">>>Running type checks...")
            run_command(["python", "-m", "mypy", "src", "tests"], check=False)
            log_message(">>> Running tests...")
            run_command(["python", "-m", "pytest", "tests"], check=False)
            log_message("All checks completed")
            log_message(f"Failed during checks: {e}")
    def status(self) -> None:
        prefix()  # Add README.md content at start
        self._print_header("Current Status")
        self._check_required_files()
        self._generate_tree()
        result = run_command(["git", "status"], check=False)
        self._print_header("Environment Status")
        self._install()
        self._run_checks()
        suffix()  # Add TODO.md content at end
    def venv(self) -> None:
        self._print_header("Virtual Environment Setup")
    def install(self) -> None:
        self._print_header("Package Installation")
    def update(self) -> None:
        self.status()
        if self._git_status():
            log_message("Changes detected in repository")
                run_command(["git", "add", "."])
                run_command(["git", "commit", "-m", commit_msg])
                log_message("Changes committed successfully")
                log_message(f"Failed to commit changes: {e}")
            log_message("No changes to commit")
    def push(self) -> None:
        self._print_header("Pushing Changes")
            run_command(["git", "push"])
            log_message("Changes pushed successfully")
            log_message(f"Failed to push changes: {e}")
def repomix(
            cmd.append("--compress")
            cmd.append("--remove-empty-lines")
            cmd.append("-i")
            cmd.append(ignore_patterns)
        cmd.extend(["-o", output_file])
        run_command(cmd)
        log_message(f"Repository content mixed into {output_file}")
        log_message(f"Failed to mix repository: {e}")
def print_usage() -> None:
    log_message("Usage:")
    log_message("  cleanup.py status   # Show current status and run all checks")
    log_message("  cleanup.py venv     # Create virtual environment")
    log_message("  cleanup.py install  # Install package with all extras")
    log_message("  cleanup.py update   # Update and commit changes")
    log_message("  cleanup.py push     # Push changes to remote")
def main() -> NoReturn:
    new()  # Clear log file
    if len(sys.argv) < 2:
        print_usage()
        sys.exit(1)
    cleanup = Cleanup()
            cleanup.status()
            cleanup.venv()
            cleanup.install()
            cleanup.update()
            cleanup.push()
        log_message(f"Error: {e}")
    repomix()
    sys.stdout.write(Path("CLEANUP.txt").read_text())
    sys.exit(0)  # Ensure we exit with a status code
    main()

================
File: LICENSE
================
MIT License

Copyright (c) 2025 Adam Twardoch

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

================
File: LOG.md
================
---
this_file: LOG.md
---

# Changelog

All notable changes to the `twat` project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.7.6] - 2025-02-15

### Changed

- Updated package dependencies in `pyproject.toml`
- Enhanced documentation in README.md
- Refined package configuration

## [1.7.5] - 2025-02-15

### Added

- Extensive documentation improvements in README.md
- Enhanced package initialization functionality

### Changed

- Major refactoring of `src/twat/__init__.py`
- Updated path handling in `src/twat/paths.py`
- Refined package dependencies

## [1.7.0] - 2025-02-13

### Added

- New gitignore patterns for better repository management

### Changed

- Improved project structure
- Enhanced development workflow

## [1.6.2] - 2025-02-06

### Added

- Extended package configuration in `pyproject.toml`
- Added new package metadata
- Improved dependency specifications

## [1.6.1] - 2025-02-06

### Changed

- Refactored initialization code in `src/__init__.py` and `src/twat/__init__.py`
- Improved path handling in `src/twat/paths.py`
- Enhanced test coverage

### Fixed

- Path resolution issues
- Package initialization bugs

## [1.6.0] - 2025-02-06

### Added

- Initial GitHub repository setup
- Comprehensive plugin system implementation
- Modern Python packaging with PEP 621 compliance

### Changed

- Updated project documentation
- Refined package structure

## [1.1.0] - 2025-02-03

### Added

- Implemented core package functionality in `src/__init__.py`
- Added initial test suite in `tests/test_package.py`
- Enhanced project configuration in `pyproject.toml`

### Changed

- Improved gitignore configuration
- Updated README with more detailed information

## [1.0.1] - 2025-02-03

### Fixed

- Package configuration issues in `pyproject.toml`
- Repository ignore patterns

## [1.0.0] - 2025-02-03

### Added

- Initial release
- Basic package structure
- Core module implementation
- Package initialization
- Version management system

[1.7.6]: https://github.com/twardoch/twat/compare/v1.7.5...v1.7.6
[1.7.5]: https://github.com/twardoch/twat/compare/v1.7.0...v1.7.5
[1.7.0]: https://github.com/twardoch/twat/compare/v1.6.2...v1.7.0
[1.6.2]: https://github.com/twardoch/twat/compare/v1.6.1...v1.6.2
[1.6.1]: https://github.com/twardoch/twat/compare/v1.6.0...v1.6.1
[1.6.0]: https://github.com/twardoch/twat/compare/v1.1.0...v1.6.0
[1.1.0]: https://github.com/twardoch/twat/compare/v1.0.1...v1.1.0
[1.0.1]: https://github.com/twardoch/twat/compare/v1.0.0...v1.0.1
[1.0.0]: https://github.com/twardoch/twat/releases/tag/v1.0.0

================
File: pyproject.toml
================
[build-system]
requires = ["hatchling>=1.21.0", "hatch-vcs>=0.3.0"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = ["src/twat"]
include = ["src/twat/**/*.py"]

[project]
name = "twat"
dynamic = ["version"]
description = ""
readme = "README.md"
requires-python = ">=3.10"
license = "MIT"
keywords = []
classifiers = [
    "Development Status :: 4 - Beta",
    "Programming Language :: Python",
    "Programming Language :: Python :: 3.10",
    "Programming Language :: Python :: 3.11",
    "Programming Language :: Python :: 3.12",
    "Programming Language :: Python :: Implementation :: CPython",
    "Programming Language :: Python :: Implementation :: PyPy",
]

dependencies = [
    "importlib-metadata>=8.6.1",
    "importlib-resources>=6.5.2",
    "typing-extensions>=4.0.0; python_version < '3.10'",
    "pydantic>=2.10.6",
    "tomli>=2.2.1",
    "loguru>=0.7.3",
    "fire>=0.7.0",
    "python-dotenv>=1.0.1",
    "rich>=13.9.4",

]

[project.scripts]
twat = "twat:main"

[[project.authors]]
name = "Adam Twardoch"
email = "adam+github@twardoch.com"


[project.urls]
Documentation = "https://github.com/twardoch/twat#readme"
Issues = "https://github.com/twardoch/twat/issues"
Source = "https://github.com/twardoch/twat"


[tool.hatch.version]
source = "vcs"

[tool.hatch.version.raw-options]
version_scheme = "post-release"

[tool.hatch.build.hooks.vcs]
version-file = "src/twat/__version__.py"


[tool.hatch.envs.default]
dependencies = [
    "pytest",
    "pytest-cov",
    "mypy>=1.15.0",
    "ruff>=0.9.7",
    "pytest>=8.3.4",
    "pytest-cov>=6.0.0",
]


[tool.hatch.envs.default.scripts]
test = "pytest {args:tests}"
test-cov = "pytest --cov-report=term-missing --cov-config=pyproject.toml --cov=src/twat --cov=tests {args:tests}"
type-check = "mypy src/twat tests"
lint = ["ruff check src/twat tests", "ruff format src/twat tests"]


[[tool.hatch.envs.all.matrix]]
python = ["3.10", "3.11", "3.12"]


[tool.hatch.envs.lint]
detached = true
dependencies = ["mypy>=1.0.0", "ruff>=0.1.0"]


[tool.hatch.envs.lint.scripts]
typing = "mypy --install-types --non-interactive {args:src/twat tests}"
style = ["ruff check {args:.}", "ruff format {args:.}"]
fmt = ["ruff format {args:.}", "ruff check --fix {args:.}"]
all = ["style", "typing"]


[tool.ruff]
target-version = 'py310'
line-length = 120

[tool.ruff.lint]
select = [
    'A',
    'ARG',
    'B',
    'C',
    'DTZ',
    'E',
    'EM',
    'F',
    'FBT',
    'I',
    'ICN',
    'ISC',
    'N',
    'PLC',
    'PLE',
    'PLR',
    'PLW',
    'Q',
    'RUF',
    'S',
    'T',
    'TID',
    'UP',
    'W',
    'YTT',
]
ignore = [
    'ARG001',
    'ARG002',
    'ARG004',
    'ARG005',
    'B904',
    'C901',
    'DTZ005',
    'E501',
    'F401',
    'F811',
    'FBT001',
    'FBT002',
    'FBT003',
    'I001',
    'ISC001',
    'N803',
    'PLR0911',
    'PLR0912',
    'PLR0913',
    'PLR0915',
    'PLR2004',
    'S311',
    'S603',
    'S607',
    'T201',
]

[tool.ruff.lint.per-file-ignores]
"tests/*" = ['S101']


[tool.mypy]
python_version = "3.10"
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = true
disallow_incomplete_defs = true
check_untyped_defs = true
disallow_untyped_decorators = true
no_implicit_optional = true
warn_redundant_casts = true
warn_unused_ignores = true
warn_no_return = true
warn_unreachable = true


[tool.coverage.run]
source_pkgs = ["twat", "tests"]
branch = true
parallel = true
omit = ["src/twat/__about__.py"]


[tool.coverage.paths]
twat = ["src/twat", "*/twat/src/twat"]
tests = ["tests", "*/twat/tests"]


[tool.coverage.report]
exclude_lines = ["no cov", "if __name__ == .__main__.:", "if TYPE_CHECKING:"]

[project.optional-dependencies]
test = [
    "pytest>=8.3.4",
    "pytest-cov>=6.0.0",
    "pytest-xdist>=3.6.1",                # For parallel test execution
    "pytest-benchmark[histogram]>=5.1.0", # For performance testing
]

dev = ["pre-commit>=4.0.0", "ruff>=0.1.0", "mypy>=1.0.0"]

audio = ["twat-audio[all]>=0.0.1"]
cache = ["twat-cache[all]>=2.6.7"]
coding = ["twat-coding[all]>=0.0.1"]
ez = ["twat-ez[all]>=2.6.2"]
fs = ["twat-fs[all]>=2.6.2"]
genai = ["twat-genai[all]>=2.6.2"]
hatch = ["twat-hatch[all]>=2.6.2"]
image = ["twat-image[all]>=2.6.2"]
labs = ["twat-labs[all]>=1.7.5"]
llm = ["twat-llm[all]>=2.6.2"]
mp = ["twat-mp[all]>=2.6.2"]
os = ["twat-os[all]>=2.6.2"]
search = ["twat-search[all]>=2.6.2"]
speech = ["twat-speech[all]>=2.6.2"]
task = ["twat-task[all]>=2.6.2"]
text = ["twat-text[all]>=2.6.2"]
video = ["twat-video[all]>=2.6.2"]

all = [
    "twat-audio[all]>=2.1.3",
    "twat-cache[all]>=2.6.7",
    #"twat-coding[all]>=0.0.1",
    "twat-ez[all]>=2.6.2",
    "twat-fs[all]>=2.6.2",
    "twat-genai[all]>=2.6.2",
    "twat-hatch[all]>=2.6.2",
    "twat-image[all]>=2.6.2",
    "twat-labs[all]>=2.6.2",
    "twat-llm[all]>=2.6.2",
    "twat-mp[all]>=2.6.2",
    "twat-search[all]>=2.6.2",
    "twat-speech[all]>=2.6.2",
    "twat-task[all]>=2.6.2",
    "twat-text[all]>=2.6.2",
    "twat-video[all]>=2.6.2",
    "importlib-metadata>=8.6.1",
    "importlib-resources>=6.5.2",
    "typing-extensions>=4.0.0; python_version < '3.10'",
    "pydantic>=2.10.6",
    "tomli>=2.2.1",
    "loguru>=0.7.3",
    "fire>=0.7.0",
    "python-dotenv>=1.0.1",
    "rich>=13.9.4",
]

[tool.hatch.envs.test]
dependencies = [".[test]"]

[tool.hatch.envs.test.scripts]
test = "python -m pytest -n auto {args:tests}"
test-cov = "python -m pytest -n auto --cov-report=term-missing --cov-config=pyproject.toml --cov=src/twat --cov=tests {args:tests}"
bench = "python -m pytest -v -p no:briefcase tests/test_benchmark.py --benchmark-only"
bench-save = "python -m pytest -v -p no:briefcase tests/test_benchmark.py --benchmark-only --benchmark-json=benchmark/results.json"

[tool.pytest.ini_options]
markers = ["benchmark: marks tests as benchmarks (select with '-m benchmark')"]
addopts = "-v -p no:briefcase"
testpaths = ["tests"]
python_files = ["test_*.py"]
filterwarnings = ["ignore::DeprecationWarning", "ignore::UserWarning"]
asyncio_mode = "auto"

[tool.pytest-benchmark]
min_rounds = 100
min_time = 0.1
histogram = true
storage = "file"
save-data = true
compare = [
    "min",    # Minimum time
    "max",    # Maximum time
    "mean",   # Mean time
    "stddev", # Standard deviation
    "median", # Median time
    "iqr",    # Inter-quartile range
    "ops",    # Operations per second
    "rounds", # Number of rounds
]

================
File: README.md
================
# twat

A plugin-based Python package system that provides a unified interface for various utilities.

## Features

- Plugin system for Python packages with standardized interfaces
- Dynamic plugin loading and discovery
- Modern Python packaging with PEP 621 compliance
- Type hints and runtime type checking
- Comprehensive test suite and documentation
- CI/CD ready configuration

## Installation

```bash
pip install twat
```

## Usage

### As a Library

```python
import twat

# Load a plugin
fs = twat.fs  # Loads the twat-fs plugin

# List available plugins
from importlib.metadata import entry_points
plugins = entry_points(group="twat.plugins")
```

### Command Line

```bash
# Run a plugin through the twat command
twat fs --help

# Or run the plugin directly if it provides a CLI
twat-fs --help
```

## Plugin Development Guide

To create a new plugin for the `twat` system, follow these guidelines. We'll use the `twat-fs` package as an example.

### 1. Package Structure

```
twat-yourplugin/
├── src/
│   └── twat_yourplugin/
│       ├── __init__.py      # Main package interface
│       ├── __main__.py      # CLI entry point
│       └── core.py          # Core functionality
├── tests/
├── pyproject.toml           # Package configuration
├── README.md
└── LICENSE
```

### 2. Package Configuration

Your `pyproject.toml` should include:

```toml
[project]
name = "twat-yourplugin"  # Use hyphen in package name
dependencies = [
    "twat",               # Always include the main package
    # Your other dependencies
]

[project.scripts]
twat-yourplugin = "twat_yourplugin.__main__:main"  # Optional CLI

[project.entry-points."twat.plugins"]
yourplugin = "twat_yourplugin"  # Register as a twat plugin
```

### 3. Package Interface

Your `__init__.py` should expose a clean public API:

```python
# this_file: src/twat_yourplugin/__init__.py
"""Package description."""

from importlib import metadata

__version__ = metadata.version(__name__)

# Export your public API
from .core import main_function, OtherClass

__all__ = ["main_function", "OtherClass"]
```

### 4. CLI Support (Optional)

If your plugin provides a command-line interface:

```python
# this_file: src/twat_yourplugin/__main__.py
"""Command-line interface."""

import sys
from typing import NoReturn

def main() -> NoReturn:
    """CLI entry point."""
    # Your CLI implementation
    sys.exit(0)

if __name__ == "__main__":
    main()
```

### 5. Example Implementation

Here's a minimal example based on `twat-fs`:

```python
# src/twat_yourplugin/__init__.py
"""Your plugin description."""

from importlib import metadata
from .core import upload_file, ProviderType

__version__ = metadata.version(__name__)
__all__ = ["upload_file", "ProviderType"]

# src/twat_yourplugin/__main__.py
"""CLI interface."""

import sys
from typing import NoReturn
import fire
from loguru import logger

from .core import upload_file

def main() -> NoReturn:
    """CLI entry point."""
    try:
        fire.Fire({
            "upload": upload_file,
            # other commands...
        })
        sys.exit(0)
    except Exception as e:
        logger.error(f"Error: {e}")
        sys.exit(1)

if __name__ == "__main__":
    main()
```

### 6. Best Practices

1. **Naming**:
   - Package name: `twat-yourplugin` (with hyphen)
   - Import name: `twat_yourplugin` (with underscore)
   - Plugin entry point: `yourplugin` (no prefix)

2. **Dependencies**:
   - Always include `twat` as a dependency
   - Use optional dependencies for provider-specific features
   - Include development tools in `dev` extra

3. **Documentation**:
   - Include docstrings for all public APIs
   - Provide a comprehensive README
   - Include usage examples

4. **Testing**:
   - Write unit tests for core functionality
   - Include integration tests if applicable
   - Test both Python API and CLI interface

5. **Type Hints**:
   - Use type hints throughout your code
   - Support Python 3.10+
   - Follow PEP 484 and PEP 585

### 7. Development Workflow

```bash
# Create development environment
pip install hatch
hatch shell

# Install in development mode
pip install -e '.[dev,test]'

# Run tests
hatch run test
hatch run test-cov

# Run linting
hatch run lint

# Format code
hatch run format
```

## License

MIT License  
.

================
File: TODO-ALL.md
================
# TODO for all `twat` repos

# `twat_fs`, `twat_cache` and `twat_hatch` have had the most work done. Do not make major changes to them. Instead, distill a "best" configuration for them, and apply it to the other packages.

## 1. Critical Issues

### 1.1. Package Import and Version Issues

* `twat_speech`: Fix missing `__version__` attribute
* `twat_text`: Fix missing `__version__` attribute
* `twat_llm`: Fix missing `__version__` attribute

### 1.2. Missing Dependencies

* `twat_genai`: Install missing `fal` package
* `twat_cache`: Install missing `pydantic` package
* `twat_image`: Install missing `numpy`,  `webcolors`,  `PIL` packages
* `twat_llm`: Install missing `cv2`,  `llm`,  `pathos`,  `PIL`,  `tenacity` packages

### 1.3. Type Annotation Issues

* All packages: Add return type annotations to test functions
* `twat_cache`: Fix multiple type annotation issues in engines
* `twat_ez`: Fix type annotations in `py_needs.py`
* `twat_genai`: Fix type annotations in async functions
* `twat_hatch`: Fix type annotations in CLI functions

## 2. High Priority Improvements

### 2.1. Code Quality

* `twat_cache`: 
  + Fix 39 linting errors
  + Address 344 type checking errors
  + Fix failing tests
* `twat_genai`:
  + Fix 43 linting errors
  + Address 29 type checking errors
  + Fix dependency issues
* `twat_hatch`:
  + Fix 27 linting errors
  + Address 5 type checking errors

### 2.2. Test Coverage

* `twat_mp`: Excellent test coverage, use as reference
* Most packages: Only have basic version test
* Add comprehensive test suites for:
  + `twat_cache`
  + `twat_genai`
  + `twat_fs`
  + `twat_image`
  + `twat_llm`

### 2.3. Documentation

* All packages: Add proper docstrings
* All packages: Create README.md with:
  + Installation instructions
  + Basic usage examples
  + API documentation
  + Development setup guide

## 3. Medium Priority Tasks

### 3.1. Code Structure

* `twat_task`: Fix property decorators

### 3.2. Security

* `twat_task`: Fix random number generation usage


## 4. Low Priority Enhancements

### 4.1. Developer Experience

* All packages: Add pre-commit hooks
* All packages: Standardize development tools

### 4.2. CI/CD

* All packages: Add GitHub Actions for:
  + Testing
  + Linting
  + Type checking
  + Documentation building
  + Package publishing

### 4.3. Monitoring & Logging

* All packages: Add structured logging
* All packages: Add error reporting

## 5. Package-Specific Notes

### 5.1. twat_cache

* Highest priority for fixes
* Major type system overhaul needed
* Test suite needs complete rewrite

### 5.2. twat_genai

* Second highest priority
* Focus on async code improvements
* Fix dependency management

### 5.3. twat_mp

* Use as reference implementation
* Well-tested with benchmarks
* Document performance patterns

### 5.4. twat_fs

* Core functionality package
* Needs better error handling
* Add upload progress tracking

### 5.5. twat_hatch

* Focus on CLI improvements
* Better subprocess handling
* Add project templates

### 5.6. twat_image

* Fix dependency chain
* Add image processing tests
* Improve error messages

### 5.7. twat_llm

* Complete dependency audit
* Add model validation
* Improve async handling

## 6. Action Plan

1. Week 1:
   - Fix all critical version issues
   - Resolve dependency problems
   - Add missing type annotations

2. Week 2:
   - Address major linting issues
   - Fix type checking errors
   - Get all tests passing

3. Week 3:
   - Improve test coverage
   - Add documentation
   - Fix security issues

4. Week 4:
   - Implement CI/CD
   - Add development tools
   - Performance optimizations

## 7. Metrics for Success

1. All packages should have:
   - Zero linting errors
   - Zero type checking errors
   - 80%+ test coverage
   - Complete documentation
   - Working CI/CD pipeline

2. Performance targets:
   - Cache hit time < 1ms
   - Image processing < 100ms
   - API response time < 200ms

3. Code quality metrics:
   - Cyclomatic complexity < 10
   - Method length < 50 lines
   - Class length < 300 lines

================
File: VERSION.txt
================
v2.6.2



================================================================
End of Codebase
================================================================
