Initial upload: gitignore-generator-cli v1.0.0 with CI/CD workflow

This commit is contained in:
2026-01-30 15:34:03 +00:00
parent 8f39f5244f
commit 8951f27181

125
gitignore_generator/api.py Normal file
View File

@@ -0,0 +1,125 @@
"""API client for gitignore.io."""
from pathlib import Path
from typing import Optional
import requests
BASE_URL = "https://www.toptal.com/developers/gitignore/api"
CACHE_DIR = Path.home() / ".cache" / "gitignore-generator"
TEMPLATES_DIR = Path(__file__).parent.parent / "templates"
class GitignoreIOError(Exception):
"""Exception raised for gitignore.io API errors."""
pass
def get_patterns(tech: str, force_refresh: bool = False) -> str:
"""Fetch gitignore patterns for a single technology.
Args:
tech: Technology name (e.g., 'node', 'python', 'django')
force_refresh: Force refresh from API instead of using cache
Returns:
Gitignore patterns as a string
Raises:
GitignoreIOError: If the API request fails
"""
tech_lower = tech.lower()
cache_file = CACHE_DIR / f"{tech_lower}.txt"
if not force_refresh and cache_file.exists():
cache_data = cache_file.read_text()
return cache_data
try:
response = requests.get(f"{BASE_URL}/{tech_lower}", timeout=30)
response.raise_for_status()
patterns = response.text
CACHE_DIR.mkdir(parents=True, exist_ok=True)
cache_file.write_text(patterns)
return patterns
except requests.RequestException as e:
fallback = get_local_template(tech_lower)
if fallback:
return fallback
raise GitignoreIOError(f"Failed to fetch patterns for '{tech}': {e}")
def get_patterns_batch(techs: list[str], force_refresh: bool = False) -> dict[str, str]:
"""Fetch gitignore patterns for multiple technologies.
Args:
techs: List of technology names
force_refresh: Force refresh from API instead of using cache
Returns:
Dictionary mapping technology names to their patterns
"""
patterns = {}
for tech in techs:
try:
patterns[tech] = get_patterns(tech, force_refresh)
except GitignoreIOError:
patterns[tech] = ""
return patterns
def get_list(force_refresh: bool = False) -> list[str]:
"""Get list of all available technology stacks from gitignore.io.
Args:
force_refresh: Force refresh from API instead of using cache
Returns:
List of available technology names
"""
cache_file = CACHE_DIR / "list.txt"
if not force_refresh and cache_file.exists():
cache_data = cache_file.read_text()
return cache_data.strip().split('\n')
try:
response = requests.get(f"{BASE_URL}/list", timeout=30)
response.raise_for_status()
lines = response.text.strip().split('\n')
techs = [line.split(',')[0] for line in lines if line]
CACHE_DIR.mkdir(parents=True, exist_ok=True)
cache_file.write_text(response.text)
return techs
except requests.RequestException as e:
local_list = get_local_list()
if local_list:
return local_list
raise GitignoreIOError(f"Failed to fetch list: {e}")
def get_local_template(tech: str) -> Optional[str]:
"""Get local template for a technology as fallback.
Args:
tech: Technology name
Returns:
Template content or None if not found
"""
template_file = TEMPLATES_DIR / f"{tech.lower()}.gitignore"
if template_file.exists():
return template_file.read_text()
return None
def get_local_list() -> Optional[list[str]]:
"""Get list of locally available templates.
Returns:
List of available technology names or None
"""
list_file = TEMPLATES_DIR / "list.txt"
if list_file.exists():
return list_file.read_text().strip().split('\n')
return None