This file is a merged representation of the entire codebase, combined into a single document by Repomix.

<file_summary>
This section contains a summary of this file.

<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.
</purpose>

<file_format>
The content is organized as follows:
1. This summary section
2. Repository information
3. Directory structure
4. Repository files (if enabled)
5. Multiple file entries, each consisting of:
  - File path as an attribute
  - Full contents of the file
</file_format>

<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.
</usage_guidelines>

<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 patterns in .gitignore are excluded
- Files matching default ignore patterns are excluded
- Files are sorted by Git change count (files with more changes are at the bottom)
</notes>

</file_summary>

<directory_structure>
.cursor/
  rules/
    0project.mdc
    cleanup.mdc
    filetree.mdc
    quality.mdc
.github/
  workflows/
    push.yml
    release.yml
src/
  twat_labs/
    __init__.py
tests/
  test_twat_labs.py
.gitignore
.pre-commit-config.yaml
cleanup.py
CLEANUP.txt
LICENSE
LOG.md
pyproject.toml
README.md
REPO_CONTENT.txt
VERSION.txt
</directory_structure>

<files>
This section contains the contents of the repository's files.

<file path=".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>

<file path=".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>

<file path=".cursor/rules/filetree.mdc">
---
description: File tree of the project
globs:
---
[ 768]  .
├── [  64]  .benchmarks
├── [  96]  .cursor
│   └── [ 224]  rules
│       ├── [ 821]  0project.mdc
│       ├── [ 516]  cleanup.mdc
│       ├── [ 950]  filetree.mdc
│       └── [2.0K]  quality.mdc
├── [  96]  .github
│   └── [ 128]  workflows
│       ├── [2.7K]  push.yml
│       └── [1.4K]  release.yml
├── [3.5K]  .gitignore
├── [ 470]  .pre-commit-config.yaml
├── [ 987]  CLEANUP.txt
├── [1.0K]  LICENSE
├── [3.5K]  LOG.md
├── [ 753]  README.md
├── [ 34K]  REPO_CONTENT.txt
├── [   7]  VERSION.txt
├── [ 13K]  cleanup.py
├── [ 160]  dist
├── [7.5K]  pyproject.toml
├── [ 128]  src
│   └── [ 224]  twat_labs
│       └── [ 140]  __init__.py
└── [ 128]  tests
    └── [ 151]  test_twat_labs.py

10 directories, 18 files
</file>

<file path=".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>

<file path=".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", "3.11", "3.12"]
        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_labs --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>

<file path=".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-labs
    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>

<file path="src/twat_labs/__init__.py">
"""twat labs plugin"""

from importlib import metadata

from twat_labs.__version__ import version as __version__

__all__ = ["__version__"]
</file>

<file path="tests/test_twat_labs.py">
"""Test suite for twat_labs."""


def test_version():
    """Verify package exposes version."""
    import twat_labs

    assert twat_labs.__version__
</file>

<file path=".gitignore">
*_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>

<file path=".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>

<file path="cleanup.py">
#!/usr/bin/env -S uv run -s
# /// script
# dependencies = [
#   "ruff>=0.9.6",
#   "pytest>=8.3.4",
#   "mypy>=1.15.0",
# ]
# ///
# this_file: cleanup.py

"""
Cleanup tool for managing repository tasks and maintaining code quality.

This script provides a comprehensive set of commands for repository maintenance:

When to use each command:

- `cleanup.py status`: Use this FIRST when starting work to check the current state
  of the repository. It shows file structure, git status, and runs all code quality
  checks. Run this before making any changes to ensure you're starting from a clean state.

- `cleanup.py venv`: Run this when setting up the project for the first time or if
  your virtual environment is corrupted/missing. Creates a new virtual environment
  using uv.

- `cleanup.py install`: Use after `venv` or when dependencies have changed. Installs
  the package and all development dependencies in editable mode.

- `cleanup.py update`: Run this when you've made changes and want to commit them.
  It will:
  1. Show current status (like `status` command)
  2. Stage and commit any changes with a generic message
  Use this for routine maintenance commits.

- `cleanup.py push`: Run this after `update` when you want to push your committed
  changes to the remote repository.

Workflow Example:
1. Start work: `cleanup.py status`
2. Make changes to code
3. Commit changes: `cleanup.py update`
4. Push to remote: `cleanup.py push`

The script maintains a CLEANUP.txt file that records all operations with timestamps.
It also includes content from README.md at the start and TODO.md at the end of logs
for context.

Required Files:
- LOG.md: Project changelog
- README.md: Project documentation
- TODO.md: Pending tasks and future plans
"""

import subprocess
import os
import sys
from datetime import datetime, timezone
from pathlib import Path
from typing import NoReturn
from shutil import which

# Configuration
IGNORE_PATTERNS = [
    ".git",
    ".venv",
    "__pycache__",
    "*.pyc",
    "dist",
    "build",
    "*.egg-info",
]
REQUIRED_FILES = ["LOG.md", ".cursor/rules/0project.mdc", "TODO.md"]
LOG_FILE = Path("CLEANUP.txt")

# Ensure we're working from the script's directory
os.chdir(Path(__file__).parent)


def new() -> None:
    """Remove existing log file."""
    if LOG_FILE.exists():
        LOG_FILE.unlink()


def prefix() -> None:
    """Write README.md content to log file."""
    readme = Path(".cursor/rules/0project.mdc")
    if readme.exists():
        log_message("\n=== PROJECT STATEMENT ===")
        content = readme.read_text()
        log_message(content)


def suffix() -> None:
    """Write TODO.md content to log file."""
    todo = Path("TODO.md")
    if todo.exists():
        log_message("\n=== TODO.md ===")
        content = todo.read_text()
        log_message(content)


def log_message(message: str) -> None:
    """Log a message to file and console with timestamp."""
    timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S")
    log_line = f"{timestamp} - {message}\n"
    with LOG_FILE.open("a") as f:
        f.write(log_line)


def run_command(cmd: list[str], check: bool = True) -> subprocess.CompletedProcess:
    """Run a shell command and return the result."""
    try:
        result = subprocess.run(
            cmd,
            check=check,
            capture_output=True,
            text=True,
            shell=False,  # Explicitly set shell=False for security
        )
        if result.stdout:
            log_message(result.stdout)
        return result
    except subprocess.CalledProcessError as e:
        log_message(f"Command failed: {' '.join(cmd)}")
        log_message(f"Error: {e.stderr}")
        if check:
            raise
        return subprocess.CompletedProcess(cmd, 1, "", str(e))


def check_command_exists(cmd: str) -> bool:
    """Check if a command exists in the system."""
    try:
        return which(cmd) is not None
    except Exception:
        return False


class Cleanup:
    """Main cleanup tool class."""

    def __init__(self) -> None:
        self.workspace = Path.cwd()

    def _print_header(self, message: str) -> None:
        """Print a section header."""
        log_message(f"\n=== {message} ===")

    def _check_required_files(self) -> bool:
        """Check if all required files exist."""
        missing = False
        for file in REQUIRED_FILES:
            if not (self.workspace / file).exists():
                log_message(f"Error: {file} is missing")
                missing = True
        return not missing

    def _generate_tree(self) -> None:
        """Generate and display tree structure of the project."""
        if not check_command_exists("tree"):
            log_message("Warning: 'tree' command not found. Skipping tree generation.")
            return None

        try:
            # Create/overwrite the file with YAML frontmatter
            rules_dir = Path(".cursor/rules")
            rules_dir.mkdir(parents=True, exist_ok=True)
            # Get tree output
            tree_result = run_command(["tree", "-a", "-I", ".git", "--gitignore", "-n", "-h", "-I", "*_cache"])
            tree_text = tree_result.stdout
            # Write frontmatter and tree output to file
            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 the contents
            log_message("\nProject structure:")
            log_message(tree_text)

        except Exception as e:
            log_message(f"Failed to generate tree: {e}")
        return None

    def _git_status(self) -> bool:
        """Check git status and return True if there are changes."""
        result = run_command(["git", "status", "--porcelain"], check=False)
        return bool(result.stdout.strip())

    def _venv(self) -> None:
        """Create and activate virtual environment using uv."""
        log_message("Setting up virtual environment")
        try:
            run_command(["uv", "venv"])
            # Activate the virtual environment
            venv_path = self.workspace / ".venv" / "bin" / "activate"
            if venv_path.exists():
                os.environ["VIRTUAL_ENV"] = str(self.workspace / ".venv")
                os.environ["PATH"] = f"{self.workspace / '.venv' / 'bin'}{os.pathsep}{os.environ['PATH']}"
                log_message("Virtual environment created and activated")
            else:
                log_message("Virtual environment created but activation failed")
        except Exception as e:
            log_message(f"Failed to create virtual environment: {e}")

    def _install(self) -> None:
        """Install package in development mode with all extras."""
        log_message("Installing package with all extras")
        try:
            self._venv()
            run_command(["uv", "pip", "install", "-e", ".[test,dev]"])
            log_message("Package installed successfully")
        except Exception as e:
            log_message(f"Failed to install package: {e}")

    def _run_checks(self) -> None:
        """Run code quality checks using ruff and pytest."""
        log_message("Running code quality checks")

        try:
            # Run ruff checks
            log_message(">>> Running code fixes...")
            run_command(
                [
                    "python",
                    "-m",
                    "ruff",
                    "check",
                    "--fix",
                    "--unsafe-fixes",
                    "src",
                    "tests",
                ],
                check=False,
            )
            run_command(
                [
                    "python",
                    "-m",
                    "ruff",
                    "format",
                    "--respect-gitignore",
                    "src",
                    "tests",
                ],
                check=False,
            )

            # Run type checks
            log_message(">>>Running type checks...")
            run_command(["python", "-m", "mypy", "src", "tests"], check=False)

            # Run tests
            log_message(">>> Running tests...")
            run_command(["python", "-m", "pytest", "tests"], check=False)

            log_message("All checks completed")
        except Exception as e:
            log_message(f"Failed during checks: {e}")

    def status(self) -> None:
        """Show current repository status: tree structure, git status, and run checks."""
        prefix()  # Add README.md content at start
        self._print_header("Current Status")

        # Check required files
        self._check_required_files()

        # Show tree structure
        self._generate_tree()

        # Show git status
        result = run_command(["git", "status"], check=False)
        log_message(result.stdout)

        # Run additional checks
        self._print_header("Environment Status")
        self._venv()
        self._install()
        self._run_checks()

        suffix()  # Add TODO.md content at end

    def venv(self) -> None:
        """Create and activate virtual environment."""
        self._print_header("Virtual Environment Setup")
        self._venv()

    def install(self) -> None:
        """Install package with all extras."""
        self._print_header("Package Installation")
        self._install()

    def update(self) -> None:
        """Show status and commit any changes if needed."""
        # First show current status
        self.status()

        # Then handle git changes if any
        if self._git_status():
            log_message("Changes detected in repository")
            try:
                # Add all changes
                run_command(["git", "add", "."])
                # Commit changes
                commit_msg = "Update repository files"
                run_command(["git", "commit", "-m", commit_msg])
                log_message("Changes committed successfully")
            except Exception as e:
                log_message(f"Failed to commit changes: {e}")
        else:
            log_message("No changes to commit")

    def push(self) -> None:
        """Push changes to remote repository."""
        self._print_header("Pushing Changes")
        try:
            run_command(["git", "push"])
            log_message("Changes pushed successfully")
        except Exception as e:
            log_message(f"Failed to push changes: {e}")


def repomix(
    *,
    compress: bool = True,
    remove_empty_lines: bool = True,
    ignore_patterns: str = ".specstory/**/*.md,.venv/**,_private/**,CLEANUP.txt,**/*.json,*.lock",
    output_file: str = "REPO_CONTENT.txt",
) -> None:
    """Combine repository files into a single text file.

    Args:
        compress: Whether to compress whitespace in output
        remove_empty_lines: Whether to remove empty lines
        ignore_patterns: Comma-separated glob patterns of files to ignore
        output_file: Output file path
    """
    try:
        # Build command
        cmd = ["repomix"]
        if compress:
            cmd.append("--compress")
        if remove_empty_lines:
            cmd.append("--remove-empty-lines")
        if ignore_patterns:
            cmd.append("-i")
            cmd.append(ignore_patterns)
        cmd.extend(["-o", output_file])

        # Run repomix
        run_command(cmd)
        log_message(f"Repository content mixed into {output_file}")

    except Exception as e:
        log_message(f"Failed to mix repository: {e}")


def print_usage() -> None:
    """Print usage information."""
    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:
    """Main entry point."""
    new()  # Clear log file

    if len(sys.argv) < 2:
        print_usage()
        sys.exit(1)

    command = sys.argv[1]
    cleanup = Cleanup()

    try:
        if command == "status":
            cleanup.status()
        elif command == "venv":
            cleanup.venv()
        elif command == "install":
            cleanup.install()
        elif command == "update":
            cleanup.update()
        elif command == "push":
            cleanup.push()
        else:
            print_usage()
    except Exception as e:
        log_message(f"Error: {e}")
    repomix()
    sys.stdout.write(Path("CLEANUP.txt").read_text())
    sys.exit(0)  # Ensure we exit with a status code


if __name__ == "__main__":
    main()
</file>

<file path="CLEANUP.txt">
2025-03-05 12:14:36 -
=== PROJECT STATEMENT ===
2025-03-05 12:14:36 - ---
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

2025-03-05 12:14:36 -
=== Current Status ===
2025-03-05 12:14:36 - Error: TODO.md is missing
2025-03-05 12:14:36 - [ 768]  .
âââ [  64]  .benchmarks
âââ [  96]  .cursor
âÂ Â  âââ [ 224]  rules
âÂ Â      âââ [ 821]  0project.mdc
âÂ Â      âââ [ 516]  cleanup.mdc
âÂ Â      âââ [ 950]  filetree.mdc
âÂ Â      âââ [2.0K]  quality.mdc
âââ [  96]  .github
âÂ Â  âââ [ 128]  workflows
âÂ Â      âââ [2.7K]  push.yml
âÂ Â      âââ [1.4K]  release.yml
âââ [3.5K]  .gitignore
âââ [ 470]  .pre-commit-config.yaml
âââ [ 987]  CLEANUP.txt
âââ [1.0K]  LICENSE
âââ [3.5K]  LOG.md
âââ [ 753]  README.md
âââ [ 34K]  REPO_CONTENT.txt
âââ [   7]  VERSION.txt
âââ [ 13K]  cleanup.py
âââ [ 160]  dist
âââ [7.5K]  pyproject.toml
âââ [ 128]  src
âÂ Â  âââ [ 224]  twat_labs
âÂ Â      âââ [ 140]  __init__.py
âââ [ 128]  tests
    âââ [ 151]  test_twat_labs.py

10 directories, 18 files

2025-03-05 12:14:36 -
Project structure:
2025-03-05 12:14:36 - [ 768]  .
âââ [  64]  .benchmarks
âââ [  96]  .cursor
âÂ Â  âââ [ 224]  rules
âÂ Â      âââ [ 821]  0project.mdc
âÂ Â      âââ [ 516]  cleanup.mdc
âÂ Â      âââ [ 950]  filetree.mdc
âÂ Â      âââ [2.0K]  quality.mdc
âââ [  96]  .github
âÂ Â  âââ [ 128]  workflows
âÂ Â      âââ [2.7K]  push.yml
âÂ Â      âââ [1.4K]  release.yml
âââ [3.5K]  .gitignore
âââ [ 470]  .pre-commit-config.yaml
âââ [ 987]  CLEANUP.txt
âââ [1.0K]  LICENSE
âââ [3.5K]  LOG.md
âââ [ 753]  README.md
âââ [ 34K]  REPO_CONTENT.txt
âââ [   7]  VERSION.txt
âââ [ 13K]  cleanup.py
âââ [ 160]  dist
âââ [7.5K]  pyproject.toml
âââ [ 128]  src
âÂ Â  âââ [ 224]  twat_labs
âÂ Â      âââ [ 140]  __init__.py
âââ [ 128]  tests
    âââ [ 151]  test_twat_labs.py

10 directories, 18 files

2025-03-05 12:14:36 - On branch main
Your branch is up to date with 'origin/main'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   .cursor/rules/filetree.mdc
	modified:   CLEANUP.txt

no changes added to commit (use "git add" and/or "git commit -a")

2025-03-05 12:14:36 - On branch main
Your branch is up to date with 'origin/main'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   .cursor/rules/filetree.mdc
	modified:   CLEANUP.txt

no changes added to commit (use "git add" and/or "git commit -a")

2025-03-05 12:14:36 -
=== Environment Status ===
2025-03-05 12:14:36 - Setting up virtual environment
2025-03-05 12:14:37 - Virtual environment created and activated
2025-03-05 12:14:37 - Installing package with all extras
2025-03-05 12:14:37 - Setting up virtual environment
2025-03-05 12:14:38 - Virtual environment created and activated
2025-03-05 12:14:38 - Package installed successfully
2025-03-05 12:14:38 - Running code quality checks
2025-03-05 12:14:38 - >>> Running code fixes...
2025-03-05 12:14:38 - src/twat_labs/__init__.py:3:23: F401 `importlib.metadata` imported but unused
  |
1 | """twat labs plugin"""
2 |
3 | from importlib import metadata
  |                       ^^^^^^^^ F401
4 |
5 | from twat_labs.__version__ import version as __version__
  |
  = help: Remove unused import: `importlib.metadata`

Found 1 error.

2025-03-05 12:14:38 - 2 files left unchanged

2025-03-05 12:14:38 - >>>Running type checks...
2025-03-05 12:14:41 - tests/test_twat_labs.py:4: error: Function is missing a return type annotation  [no-untyped-def]
tests/test_twat_labs.py:4: note: Use "-> None" if function does not return a value
Found 1 error in 1 file (checked 3 source files)

2025-03-05 12:14:41 - >>> Running tests...
2025-03-05 12:14:43 - ============================= test session starts ==============================
platform darwin -- Python 3.12.8, pytest-8.3.5, pluggy-1.5.0 -- /Users/adam/Developer/vcs/github.twardoch/pub/twat-packages/_good/twat/plugins/repos/twat_labs/.venv/bin/python
cachedir: .pytest_cache
benchmark: 5.1.0 (defaults: timer=time.perf_counter disable_gc=False min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10 warmup=False warmup_iterations=100000)
rootdir: /Users/adam/Developer/vcs/github.twardoch/pub/twat-packages/_good/twat/plugins/repos/twat_labs
configfile: pyproject.toml
plugins: cov-6.0.0, benchmark-5.1.0, xdist-3.6.1
collecting ... collected 1 item

tests/test_twat_labs.py::test_version PASSED                             [100%]

============================== 1 passed in 0.04s ===============================

2025-03-05 12:14:43 - All checks completed
2025-03-05 12:14:45 -
đŚ Repomix v0.2.29

No custom config found at repomix.config.json or global config at /Users/adam/.config/repomix/repomix.config.json.
You can add a config file for additional settings. Please check https://github.com/yamadashy/repomix for more information.
â  Searching for files...
[2K[1A[2K[Gâ š Collecting files...
[2K[1A[2K[Gâ ¸ Collecting files...
[2K[1A[2K[Gâ ź Collecting files...
[2K[1A[2K[Gâ ´ Running security check...
[2K[1A[2K[Gâ Ś Running security check...
[2K[1A[2K[Gâ § Processing files...
[2K[1A[2K[Gâ  Processing files...
[2K[1A[2K[Gâ  Processing file... (6/16) .github/workflows/release.yml
[2K[1A[2K[Gâ  Calculating metrics...
[2K[1A[2K[Gâ  Calculating metrics...
[2K[1A[2K[Gâ š Calculating metrics...
[2K[1A[2K[Gâ ¸ Calculating metrics...
[2K[1A[2K[Gâ ź Calculating metrics...
[2K[1A[2K[Gâ ´ Calculating metrics...
[2K[1A[2K[Gâ Packing completed successfully!

đ Top 5 Files by Character Count and Token Count:
ââââââââââââââââââââââââââââââââââââââââââââââââââ
1.  pyproject.toml (7,639 chars, 2,166 tokens)
2.  cleanup.py (5,977 chars, 1,344 tokens)
3.  .gitignore (3,633 chars, 1,391 tokens)
4.  LOG.md (3,561 chars, 866 tokens)
5.  .github/workflows/push.yml (2,745 chars, 709 tokens)

đ Security Check:
ââââââââââââââââââ
â No suspicious files detected.

đ Pack Summary:
ââââââââââââââââ
  Total Files: 16 files
  Total Chars: 35,094 chars
 Total Tokens: 9,196 tokens
       Output: REPO_CONTENT.txt
     Security: â No suspicious files detected

đ All Done!
Your repository has been successfully packed.

đĄ Repomix is now available in your browser! Try it at https://repomix.com

2025-03-05 12:14:45 - Repository content mixed into REPO_CONTENT.txt
</file>

<file path="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>

<file path="LOG.md">
---
this_file: LOG.md
---

# Changelog

All notable changes to the `twat-labs` 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.5] - 2025-02-15

### Changed

- Enhanced error handling in package installation with UV (users now get clearer error messages when installations fail)
- Improved module installation with better error messages and exception handling (makes troubleshooting easier)
- Refactored installation process with separate `_install_with_uv` and `_import_modules` functions (more reliable package installation)
- Updated logging to use `logging.info` instead of print statements (better integration with Python logging systems)

## [1.7.0] - 2025-02-13

### Added

- Major refactoring of `py_needs.py` with improved architecture (faster and more reliable package management)
- Enhanced UV package manager integration (better package installation experience)
- Added FontLab-specific site-packages detection (improved compatibility with FontLab environment)
- Implemented XDG path management for better cross-platform support (more reliable on Linux and macOS)
- Added comprehensive system-specific path discovery (better executable finding across different OS platforms)
- Introduced caching for performance optimization with `@lru_cache` (faster repeated operations)

### Changed

- Reorganized code structure with clear section separation (easier to maintain and understand)
- Improved error handling and logging throughout the module (better debugging experience)
- Enhanced security with executable verification (safer package management)
- Updated path management with extended search capabilities (more reliable command finding)
- Refactored URL download functionality with Qt and fallback implementations (more reliable downloads)

### Fixed

- Improved handling of UV installation target paths (more reliable package installation)
- Better error handling for package installation failures (clearer error messages)

## [1.6.2] - 2025-02-06

### Fixed

- Quick patch release addressing minor issues from 1.6.1 (improved stability)
- Bug fixes and stability improvements (better overall reliability)
- Enhanced error handling in package management (fewer silent failures)

## [1.6.1] - 2025-02-06

### Fixed

- Hotfix release addressing issues from 1.6.0 (improved reliability)
- Performance optimizations (faster operations)
- Improved package installation reliability (fewer failed installations)

## [1.6.0] - 2025-02-06

### Added

- First feature-complete release
- Modern Python packaging with PEP 621 compliance (better package management)
- Type hints and runtime type checking (improved code reliability)
- Comprehensive test suite (better stability)
- CI/CD configuration (faster updates)
- Basic UV package manager integration (modern package management)

## [1.0.0] - 2025-02-06

### Added

- Initial release
- Basic project structure
- Core functionality implementation
- Basic documentation
- Fundamental package management features

[1.7.5]: https://github.com/twardoch/twat-labs/compare/v1.7.0...v1.7.5
[1.7.0]: https://github.com/twardoch/twat-labs/compare/v1.6.2...v1.7.0
[1.6.2]: https://github.com/twardoch/twat-labs/compare/v1.6.1...v1.6.2
[1.6.1]: https://github.com/twardoch/twat-labs/compare/v1.6.0...v1.6.1
[1.6.0]: https://github.com/twardoch/twat-labs/compare/v1.0.0...v1.6.0
[1.0.0]: https://github.com/twardoch/twat-labs/releases/tag/v1.0.0
</file>

<file path="pyproject.toml">
# this_file: pyproject.toml
# this_project: twat_labs
# Build System Configuration
# -------------------------
# Specifies the build system and its requirements for packaging the project
# Specifies the build backend and its requirements for building the package
[build-system]
requires = [
    "hatchling>=1.27.0", # Core build backend for Hatch
    "hatch-vcs>=0.4.0", # Version Control System plugin for Hatch

]
build-backend = "hatchling.build" # Use Hatchling as the build backend

# Wheel build configuration
# Specifies which packages to include in the wheel distribution
[tool.hatch.build.targets.wheel]
packages = ["src/twat_labs"]

# Project Metadata Configuration
# ------------------------------
# Comprehensive project description, requirements, and compatibility information
[project]
name = "twat-labs"
dynamic = ["version"] # Version is determined dynamically from VCS
description = ""
readme = "README.md"
requires-python = ">=3.10" # Minimum Python version required
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",
]
# Runtime Dependencies
# -------------------
# External packages required for the project to function
dependencies = [
    "twat>=1.8.1", # Main twat package

]

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

# Project URLs
# ------------
# Links to project resources for documentation, issues, and source code
[project.urls]
Documentation = "https://github.com/twardoch/twat-labs#readme"
Issues = "https://github.com/twardoch/twat-labs/issues"
Source = "https://github.com/twardoch/twat-labs"

# Twat Plugin Registration
# -----------------------
# Registers this package as a plugin for the twat ecosystem
[project.entry-points."twat.plugins"]
labs = "twat_labs"

# Version configuration using VCS (Git)
[tool.hatch.version]
source = "vcs"

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

# VCS hook configuration for version file generation
[tool.hatch.build.hooks.vcs]
version-file = "src/twat_labs/__version__.py"

# Default development environment configuration
[tool.hatch.envs.default]
dependencies = [
    "pytest", # Testing framework
    "pytest-cov", # Coverage reporting
    "mypy>=1.15.0", # Static type checker
    "ruff>=0.9.6", # Fast Python linter
    "pytest>=8.3.4", # Testing framework
    "pytest-cov>=6.0.0", # Coverage reporting
    "ruff>=0.9.6", # Fast Python linter
    "mypy>=1.15.0", # Static type checker

]

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

# Python version matrix for testing
[[tool.hatch.envs.all.matrix]]
python = ["3.10", "3.11", "3.12"]

# Linting environment configuration
[tool.hatch.envs.lint]
detached = true # Run in isolated environment
dependencies = [
    "mypy>=1.15.0", # Static type checker
    "ruff>=0.9.6", # Fast Python linter

]

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

# Ruff (linter) configuration
[tool.ruff]
target-version = "py310"
line-length = 88

# Ruff lint rules configuration
[tool.ruff.lint]
extend-select = [
    "A", # flake8-builtins
    "ARG", # flake8-unused-arguments
    "B", # flake8-bugbear
    "C", # flake8-comprehensions
    "DTZ", # flake8-datetimez
    "E", # pycodestyle errors
    "EM", # flake8-errmsg
    "F", # pyflakes
    "FBT", # flake8-boolean-trap
    "I", # isort
    "ICN", # flake8-import-conventions
    "ISC", # flake8-implicit-str-concat
    "N", # pep8-naming
    "PLC", # pylint convention
    "PLE", # pylint error
    "PLR", # pylint refactor
    "PLW", # pylint warning
    "Q", # flake8-quotes
    "RUF", # Ruff-specific rules
    "S", # flake8-bandit
    "T", # flake8-debugger
    "TID", # flake8-tidy-imports
    "UP", # pyupgrade
    "W", # pycodestyle warnings
    "YTT", # flake8-2020

]
ignore = [
    "ARG001", # Unused function argument
    "E501", # Line too long
    "I001", # Import block formatting

]

# isort configuration within Ruff
[tool.ruff.lint.isort]
known-first-party = ["twat_labs"] # Treat as first-party imports for sorting

# flake8-tidy-imports configuration within Ruff
[tool.ruff.lint.flake8-tidy-imports]
ban-relative-imports = "all" # Ban all relative imports for consistency

# File-specific Ruff configurations
[tool.ruff.lint.per-file-ignores]
"tests/*" = [
    "S101", # Allow assert in tests
    "PLR2004", # Allow magic values in tests for readability
    "TID252", # Allow relative imports in tests for convenience

]

# MyPy (type checker) configuration
[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

# Coverage.py configuration for test coverage
[tool.coverage.run]
source_pkgs = ["twat_labs", "tests"]
branch = true
parallel = true
omit = ["src/twat_labs/__about__.py"]

# Coverage path mappings
[tool.coverage.paths]
twat_labs = ["src/twat_labs", "*/twat-labs/src/twat_labs"]
tests = ["tests", "*/twat-labs/tests"]

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

# Optional dependencies
[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.1.0", # Git pre-commit hooks
    "ruff>=0.9.6", # Fast Python linter
    "mypy>=1.15.0", # Static type checker

]
all = [
    "twat>=1.8.1", # Main twat package

]

# Test environment configuration
[tool.hatch.envs.test]
dependencies = [".[test]"]

# Test environment scripts
[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_labs --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"

# Pytest configuration
[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"

# Pytest-benchmark configuration
[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>

<file path="README.md">
# twat-labs

(work in progress)

## Features

- Plugin for twat
- 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-labs
```

## Usage

```python
import twat_labs
```

## Development

This project uses [Hatch](https://hatch.pypa.io/) for development workflow management.

### Setup Development Environment

```bash
# Install hatch if you haven't already
pip install hatch

# Create and activate development environment
hatch shell

# Run tests
hatch run test

# Run tests with coverage
hatch run test-cov

# Run linting
hatch run lint

# Format code
hatch run format
```

## License

MIT License
.
</file>

<file path="REPO_CONTENT.txt">
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_labs/
    __init__.py
tests/
  test_twat_labs.py
.gitignore
.pre-commit-config.yaml
cleanup.py
LICENSE
LOG.md
pyproject.toml
README.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:
---
[ 768]  .
├── [  64]  .benchmarks
├── [  96]  .cursor
│   └── [ 224]  rules
│       ├── [ 821]  0project.mdc
│       ├── [ 516]  cleanup.mdc
│       ├── [ 950]  filetree.mdc
│       └── [2.0K]  quality.mdc
├── [  96]  .github
│   └── [ 128]  workflows
│       ├── [2.7K]  push.yml
│       └── [1.4K]  release.yml
├── [3.5K]  .gitignore
├── [ 470]  .pre-commit-config.yaml
├── [ 987]  CLEANUP.txt
├── [1.0K]  LICENSE
├── [3.5K]  LOG.md
├── [ 753]  README.md
├── [ 34K]  REPO_CONTENT.txt
├── [   7]  VERSION.txt
├── [ 13K]  cleanup.py
├── [ 160]  dist
├── [7.5K]  pyproject.toml
├── [ 128]  src
│   └── [ 224]  twat_labs
│       └── [ 140]  __init__.py
└── [ 128]  tests
    └── [ 151]  test_twat_labs.py

10 directories, 18 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", "3.11", "3.12"]
        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_labs --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-labs
    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_labs/__init__.py
================


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

================
File: .gitignore
================
*_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-labs` 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.5] - 2025-02-15

### Changed

- Enhanced error handling in package installation with UV (users now get clearer error messages when installations fail)
- Improved module installation with better error messages and exception handling (makes troubleshooting easier)
- Refactored installation process with separate `_install_with_uv` and `_import_modules` functions (more reliable package installation)
- Updated logging to use `logging.info` instead of print statements (better integration with Python logging systems)

## [1.7.0] - 2025-02-13

### Added

- Major refactoring of `py_needs.py` with improved architecture (faster and more reliable package management)
- Enhanced UV package manager integration (better package installation experience)
- Added FontLab-specific site-packages detection (improved compatibility with FontLab environment)
- Implemented XDG path management for better cross-platform support (more reliable on Linux and macOS)
- Added comprehensive system-specific path discovery (better executable finding across different OS platforms)
- Introduced caching for performance optimization with `@lru_cache` (faster repeated operations)

### Changed

- Reorganized code structure with clear section separation (easier to maintain and understand)
- Improved error handling and logging throughout the module (better debugging experience)
- Enhanced security with executable verification (safer package management)
- Updated path management with extended search capabilities (more reliable command finding)
- Refactored URL download functionality with Qt and fallback implementations (more reliable downloads)

### Fixed

- Improved handling of UV installation target paths (more reliable package installation)
- Better error handling for package installation failures (clearer error messages)

## [1.6.2] - 2025-02-06

### Fixed

- Quick patch release addressing minor issues from 1.6.1 (improved stability)
- Bug fixes and stability improvements (better overall reliability)
- Enhanced error handling in package management (fewer silent failures)

## [1.6.1] - 2025-02-06

### Fixed

- Hotfix release addressing issues from 1.6.0 (improved reliability)
- Performance optimizations (faster operations)
- Improved package installation reliability (fewer failed installations)

## [1.6.0] - 2025-02-06

### Added

- First feature-complete release
- Modern Python packaging with PEP 621 compliance (better package management)
- Type hints and runtime type checking (improved code reliability)
- Comprehensive test suite (better stability)
- CI/CD configuration (faster updates)
- Basic UV package manager integration (modern package management)

## [1.0.0] - 2025-02-06

### Added

- Initial release
- Basic project structure
- Core functionality implementation
- Basic documentation
- Fundamental package management features

[1.7.5]: https://github.com/twardoch/twat-labs/compare/v1.7.0...v1.7.5
[1.7.0]: https://github.com/twardoch/twat-labs/compare/v1.6.2...v1.7.0
[1.6.2]: https://github.com/twardoch/twat-labs/compare/v1.6.1...v1.6.2
[1.6.1]: https://github.com/twardoch/twat-labs/compare/v1.6.0...v1.6.1
[1.6.0]: https://github.com/twardoch/twat-labs/compare/v1.0.0...v1.6.0
[1.0.0]: https://github.com/twardoch/twat-labs/releases/tag/v1.0.0

================
File: pyproject.toml
================
# this_file: twat_labs/pyproject.toml

# this_file: twat_labs/pyproject.toml

# Build System Configuration
# -------------------------
# Specifies the build system and its requirements for packaging the project
# Specifies the build backend and its requirements for building the package
[build-system]
requires = [
    "hatchling>=1.27.0",     # Core build backend for Hatch
    "hatch-vcs>=0.4.0",      # Version Control System plugin for Hatch
]
build-backend = "hatchling.build"  # Use Hatchling as the build backend

# Wheel build configuration
# Specifies which packages to include in the wheel distribution
[tool.hatch.build.targets.wheel]
packages = ["src/twat_labs"]

# Project Metadata Configuration
# ------------------------------
# Comprehensive project description, requirements, and compatibility information
[project]
name = "twat-labs"
dynamic = ["version"]  # Version is determined dynamically from VCS
description = ""
readme = "README.md"
requires-python = ">=3.10"  # Minimum Python version required
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",
]

# Runtime Dependencies
# -------------------
# External packages required for the project to function
dependencies = [
    "twat>=1.8.1",           # Main twat package
]

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

# Project URLs
# ------------
# Links to project resources for documentation, issues, and source code
[project.urls]
Documentation = "https://github.com/twardoch/twat-labs#readme"
Issues = "https://github.com/twardoch/twat-labs/issues"
Source = "https://github.com/twardoch/twat-labs"

# Twat Plugin Registration
# -----------------------
# Registers this package as a plugin for the twat ecosystem
[project.entry-points."twat.plugins"]
labs = "twat_labs"

# Version configuration using VCS (Git)
[tool.hatch.version]
source = "vcs"

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

# VCS hook configuration for version file generation
[tool.hatch.build.hooks.vcs]
version-file = "src/twat_labs/__version__.py"

# Default development environment configuration
[tool.hatch.envs.default]
dependencies = [
    "pytest",                # Testing framework
    "pytest-cov",           # Coverage reporting
    "mypy>=1.15.0",         # Static type checker
    "ruff>=0.9.6",          # Fast Python linter
    "pytest>=8.3.4",        # Testing framework
    "pytest-cov>=6.0.0",    # Coverage reporting
    "ruff>=0.9.6",          # Fast Python linter
    "mypy>=1.15.0",         # Static type checker
]

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

# Python version matrix for testing
[[tool.hatch.envs.all.matrix]]
python = ["3.10", "3.11", "3.12"]

# Linting environment configuration
[tool.hatch.envs.lint]
detached = true  # Run in isolated environment
dependencies = [
    "mypy>=1.15.0",         # Static type checker
    "ruff>=0.9.6",          # Fast Python linter
]

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

# Ruff (linter) configuration
[tool.ruff]
target-version = "py310"
line-length = 88

# Ruff lint rules configuration
[tool.ruff.lint]
extend-select = [
    "A",     # flake8-builtins
    "ARG",   # flake8-unused-arguments
    "B",     # flake8-bugbear
    "C",     # flake8-comprehensions
    "DTZ",   # flake8-datetimez
    "E",     # pycodestyle errors
    "EM",    # flake8-errmsg
    "F",     # pyflakes
    "FBT",   # flake8-boolean-trap
    "I",     # isort
    "ICN",   # flake8-import-conventions
    "ISC",   # flake8-implicit-str-concat
    "N",     # pep8-naming
    "PLC",   # pylint convention
    "PLE",   # pylint error
    "PLR",   # pylint refactor
    "PLW",   # pylint warning
    "Q",     # flake8-quotes
    "RUF",   # Ruff-specific rules
    "S",     # flake8-bandit
    "T",     # flake8-debugger
    "TID",   # flake8-tidy-imports
    "UP",    # pyupgrade
    "W",     # pycodestyle warnings
    "YTT",   # flake8-2020
]
ignore = [
    "ARG001", # Unused function argument
    "E501",   # Line too long
    "I001",   # Import block formatting
]

# File-specific Ruff configurations
[tool.ruff.per-file-ignores]
"tests/*" = ["S101"]  # Allow assert in tests

# MyPy (type checker) configuration
[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

# Coverage.py configuration for test coverage
[tool.coverage.run]
source_pkgs = ["twat_labs", "tests"]
branch = true
parallel = true
omit = [
    "src/twat_labs/__about__.py",
]

# Coverage path mappings
[tool.coverage.paths]
twat_labs = ["src/twat_labs", "*/twat-labs/src/twat_labs"]
tests = ["tests", "*/twat-labs/tests"]

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

# Optional dependencies
[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.1.0",     # Git pre-commit hooks
    "ruff>=0.9.6",           # Fast Python linter
    "mypy>=1.15.0",          # Static type checker
]

all = [
    "twat>=1.8.1",           # Main twat package
]

# Test environment configuration
[tool.hatch.envs.test]
dependencies = [".[test]"]

# Test environment scripts
[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_labs --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"

# Pytest configuration
[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"

# Pytest-benchmark configuration
[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-labs

(work in progress)

## Features

- Plugin for twat
- 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-labs
```

## Usage

```python
import twat_labs
```

## Development

This project uses [Hatch](https://hatch.pypa.io/) for development workflow management.

### Setup Development Environment

```bash
# Install hatch if you haven't already
pip install hatch

# Create and activate development environment
hatch shell

# Run tests
hatch run test

# Run tests with coverage
hatch run test-cov

# Run linting
hatch run lint

# Format code
hatch run format
```

## License

MIT License
.

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



================================================================
End of Codebase
================================================================
</file>

<file path="VERSION.txt">
v2.7.5
</file>

</files>
