Download scripts/push_to_hf.py from PowerMachine/CNN-BiGRU: direct link, hf CLI and curl.
- Browser
- Download file 7.38 kB
-
https://huggingface.co/PowerMachine/CNN-BiGRU/resolve/9f36e33eb4d0738c577cd3ca5efdfa0bce66c2ea/scripts/push_to_hf.py
- Command line
-
hf download hf://PowerMachine/CNN-BiGRU@9f36e33eb4d0738c577cd3ca5efdfa0bce66c2ea/scripts/push_to_hf.py
-
curl -L -o push_to_hf.py https://huggingface.co/PowerMachine/CNN-BiGRU/resolve/9f36e33eb4d0738c577cd3ca5efdfa0bce66c2ea/scripts/push_to_hf.py
7.38 kB
| """push_to_hf.py — Envia scripts em lote ao HF repositório 'CNN-BiGRU' (v2.0). | |
| Executa: | |
| 1. Cria repositório 'PowerMachine/CNN-BiGRU' (se não existir) | |
| 2. Envia todos os scripts .py, README.md, requirements.txt, docs/ | |
| usando `upload_folder` (upload em lote eficiente) | |
| 3. SOBRESCREVE módulos desatualizados (default do upload_folder) | |
| 4. Remove HF_TOKEN do ambiente após o uso (requisito do usuário) | |
| V2.0 melhorias: | |
| - Usa `upload_folder` (single call) em vez de `upload_file` em loop | |
| - Filtra arquivos por extensão e por padrões (ignora caches, logs, etc.) | |
| - Mantém árvore de pastas e subpastas conforme existente localmente | |
| - Log mais detalhado de sucesso/falha | |
| - Retry automático em caso de falha transitória | |
| Usage: | |
| HF_TOKEN=hf_xxx python push_to_hf.py | |
| """ | |
| from __future__ import annotations | |
| import os | |
| import sys | |
| import logging | |
| import time | |
| from pathlib import Path | |
| from typing import List, Set | |
| logging.basicConfig(level=logging.INFO, format="%(asctime)s | %(levelname)s | %(message)s") | |
| logger = logging.getLogger("push_hf") | |
| REPO_ID = "PowerMachine/CNN-BiGRU" | |
| # Path: scripts/push_to_hf.py -> parent=scripts -> parent=cnn_bigru | |
| PROJECT_DIR = Path(__file__).resolve().parent.parent | |
| # PROJECT_DIR.parent = raiz do projeto | |
| REPO_ROOT = PROJECT_DIR.parent | |
| # Extensões e nomes de arquivo permitidos para upload | |
| ALLOWED_EXTENSIONS: Set[str] = { | |
| ".py", ".md", ".txt", ".json", ".yaml", ".yml", ".toml", ".cfg", ".ini", ".sh", | |
| } | |
| # Padrões a ignorar (em qualquer parte do caminho) | |
| IGNORE_PATTERNS: Set[str] = { | |
| "__pycache__", ".pyc", ".pyo", ".pyd", | |
| ".git", ".gitignore", ".gitattributes", | |
| "node_modules", ".pytest_cache", ".mypy_cache", ".ruff_cache", | |
| ".DS_Store", "Thumbs.db", | |
| "*.log", "*.tmp", "*.swp", "*.bak", | |
| ".env", ".venv", "venv", "env", | |
| } | |
| # Arquivos específicos que NUNCA devem ser upados (podem conter tokens/sensíveis) | |
| SENSITIVE_FILENAMES: Set[str] = { | |
| ".env", ".env.local", ".env.production", ".env.development", | |
| "secrets.json", "credentials.json", "config.local.json", | |
| "hf_token.txt", "token.txt", | |
| } | |
| def should_ignore(path: Path) -> bool: | |
| """Verifica se um arquivo deve ser ignorado no upload.""" | |
| parts = path.parts | |
| name = path.name.lower() | |
| # Verificar padrões por partes do caminho | |
| for part in parts: | |
| part_lower = part.lower() | |
| if part_lower in IGNORE_PATTERNS: | |
| return True | |
| # Verificar extensões de cache | |
| if part_lower.endswith((".pyc", ".pyo", ".pyd")): | |
| return True | |
| # Verificar nome do arquivo | |
| if name in SENSITIVE_FILENAMES: | |
| return True | |
| # Verificar extensões permitidas | |
| if path.suffix.lower() not in ALLOWED_EXTENSIONS: | |
| # Permitir arquivos sem extensão apenas se forem específicos (README, LICENSE, etc.) | |
| if name not in {"readme", "license", "license-mit", "authors", "contributors"}: | |
| return True | |
| # Verificar padrões com wildcards | |
| for pattern in IGNORE_PATTERNS: | |
| if pattern.startswith("*"): | |
| suffix = pattern[1:] | |
| if name.endswith(suffix): | |
| return True | |
| return False | |
| def collect_files(project_dir: Path) -> List[Path]: | |
| """Coleta todos os arquivos elegíveis para upload.""" | |
| files = [] | |
| for path in project_dir.rglob("*"): | |
| if path.is_file() and not should_ignore(path): | |
| files.append(path) | |
| return files | |
| def upload_with_retry(api, folder: Path, repo_id: str, token: str, max_retries: int = 3): | |
| """Faz upload_folder com retry em caso de falha transitória.""" | |
| last_error = None | |
| for attempt in range(1, max_retries + 1): | |
| try: | |
| logger.info(f"Tentativa {attempt}/{max_retries}: upload_folder...") | |
| commit_info = api.upload_folder( | |
| folder_path=str(folder), | |
| repo_id=repo_id, | |
| repo_type="model", | |
| token=token, | |
| commit_message=f"v2.0: EWC + Context Window + RoPE + TransformerBlock + bug fixes (attempt {attempt})", | |
| # Sobrescreve arquivos desatualizados (default) | |
| ) | |
| logger.info(f"Upload bem-sucedido: {commit_info}") | |
| return True, None | |
| except Exception as e: | |
| last_error = e | |
| logger.warning(f"Tentativa {attempt} falhou: {e}") | |
| if attempt < max_retries: | |
| wait_time = 2 ** attempt | |
| logger.info(f"Aguardando {wait_time}s antes de tentar novamente...") | |
| time.sleep(wait_time) | |
| return False, last_error | |
| def main(): | |
| # Pega HF_TOKEN da variável de ambiente | |
| hf_token = os.environ.get("HF_TOKEN") or os.environ.get("HUGGING_FACE_HUB_TOKEN") | |
| if not hf_token: | |
| logger.error("HF_TOKEN não definido no ambiente. Abortando.") | |
| return 1 | |
| try: | |
| from huggingface_hub import HfApi, create_repo | |
| except ImportError: | |
| logger.error("huggingface_hub não instalado. Execute: pip install huggingface_hub") | |
| return 1 | |
| api = HfApi(token=hf_token) | |
| # 1. Cria repositório (se não existir) | |
| try: | |
| repo_url = create_repo( | |
| repo_id=REPO_ID, | |
| token=hf_token, | |
| repo_type="model", | |
| exist_ok=True, | |
| private=False, | |
| ) | |
| logger.info(f"Repositório criado/acessado: {repo_url}") | |
| except Exception as e: | |
| logger.error(f"Falha ao criar repositório: {e}") | |
| # Limpa o token mesmo em caso de falha | |
| _cleanup_token() | |
| return 1 | |
| # 2. Coleta todos os arquivos para upload | |
| files_to_upload = collect_files(PROJECT_DIR) | |
| logger.info(f"Total de arquivos para upload: {len(files_to_upload)} (de {PROJECT_DIR})") | |
| if not files_to_upload: | |
| logger.warning("Nenhum arquivo elegível para upload.") | |
| _cleanup_token() | |
| return 1 | |
| # Log dos arquivos que serão upados | |
| for f in files_to_upload[:10]: | |
| rel = f.relative_to(REPO_ROOT) | |
| logger.info(f" - {rel}") | |
| if len(files_to_upload) > 10: | |
| logger.info(f" ... e mais {len(files_to_upload) - 10} arquivos") | |
| # 3. Upload em lote via upload_folder (muito mais eficiente que upload_file em loop) | |
| success, error = upload_with_retry( | |
| api, folder=PROJECT_DIR, repo_id=REPO_ID, token=hf_token, max_retries=3 | |
| ) | |
| if success: | |
| logger.info("=" * 60) | |
| logger.info(f"Upload concluído com sucesso!") | |
| logger.info(f"Repo: https://huggingface.co/{REPO_ID}") | |
| logger.info(f"Total de arquivos enviados: {len(files_to_upload)}") | |
| logger.info("=" * 60) | |
| else: | |
| logger.error("=" * 60) | |
| logger.error(f"Falha no upload após retries: {error}") | |
| logger.error("=" * 60) | |
| # 4. Remove HF_TOKEN do ambiente (requisito do usuário) | |
| _cleanup_token() | |
| return 0 if success else 1 | |
| def _cleanup_token(): | |
| """Remove todas as variáveis de token HF do ambiente.""" | |
| removed = [] | |
| for var in ("HF_TOKEN", "HUGGING_FACE_HUB_TOKEN", "HF_HUB_TOKEN"): | |
| if var in os.environ: | |
| del os.environ[var] | |
| removed.append(var) | |
| if removed: | |
| logger.info(f"Tokens removidos do ambiente: {', '.join(removed)}") | |
| else: | |
| logger.info("Nenhum token HF encontrado no ambiente para remover.") | |
| if __name__ == "__main__": | |
| sys.exit(main()) | |