diff --git a/.gitignore b/.gitignore index 17964cc..220ebc1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,50 +1,116 @@ ``` -# Environment variables -.env -.env.local -.env.* - -# Python specific +# Python __pycache__/ *.pyc *.pyo *.pyd .Python -*.so -*.egg-info/ -.eggs/ - -# Dependencies -.venv/ -venv/ env/ -ENV/ +venv/ +.venv/ +.venv*/ +.ENV +.env.bak +.env.dev +.env.development +.env.prod +.env.production +.env.staging +.env.test +.env.testing -# Build artifacts -build/ +# Testing +.coverage +coverage/ +htmlcov/ +.nyc_output/ +.pytest_cache/ +.tox/ +.cover/ + +# Distribution / packaging dist/ +build/ *.egg +*.egg-info/ +.eggs/ +pip-log.txt +pip-delete-this-directory.txt -# Logs -*.log - -# OS generated files -.DS_Store -Thumbs.db - -# Editor files +# IDE .vscode/ .idea/ *.swp *.swo + +# OS +.DS_Store +Thumbs.db + +# Logs +*.log + +# Environment +.env +.env.local +*.env.* + +# Temp files *.tmp +*.temp -# Coverage reports -.coverage -htmlcov/ -coverage/ +# Coverage +coverage.xml +*.gcda +*.gcno -# Testing -.pytest_cache/ +# Compiled +*.so +*.dylib +*.dll +*.exe +*.out + +# Compressed +*.zip +*.gz +*.tar +*.tgz +*.bz2 +*.xz +*.7z +*.rar +*.zst +*.lz4 +*.lzh +*.cab +*.arj +*.rpm +*.deb +*.Z +*.lz +*.lzo +*.tar.gz +*.tar.bz2 +*.tar.xz +*.tar.zst + +# Gradle +.gradle/ +build/ + +# MyPy .mypy_cache/ + +# Node +node_modules/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Jupyter +.ipynb_checkpoints/ + +# Docker +.dockerenv ``` \ No newline at end of file diff --git a/ai/retry.py b/ai/retry.py index 42e81d5..1675c97 100644 --- a/ai/retry.py +++ b/ai/retry.py @@ -132,7 +132,8 @@ def execute(self, fn: Callable[..., Any], *args: Any, **kwargs: Any) -> Any: ) time.sleep(delay) - # Unreachable in practice, but keeps mypy happy. + # last_exception is guaranteed to be set here because we only reach + # this point if an exception was caught in the loop above. raise last_exception # type: ignore[misc] def calculate_delay(self, attempt: int) -> float: diff --git a/services/zc/app/api/v1/routes.py b/services/zc/app/api/v1/routes.py index 3567a67..efe02e8 100644 --- a/services/zc/app/api/v1/routes.py +++ b/services/zc/app/api/v1/routes.py @@ -243,7 +243,7 @@ async def upload_chunk( form = await request.form() chunk_index_val = form.get("chunk_index") else: - chunk_index_val = data.get("chunk_index") + chunk_index_val = data.get("chunk_index") if data else None if chunk_index_val is None: raise HTTPException(400, "Missing chunk_index") @@ -257,7 +257,7 @@ async def upload_chunk( form = await request.form() chunk_hash_val = form.get("chunk_hash") else: - chunk_hash_val = data.get("chunk_hash") + chunk_hash_val = data.get("chunk_hash") if data else None if not chunk_hash_val: raise HTTPException(400, "Missing chunk_hash for integrity verification") diff --git a/services/zc/app/grpc/wire_servicer.py b/services/zc/app/grpc/wire_servicer.py index dc5883a..2891511 100644 --- a/services/zc/app/grpc/wire_servicer.py +++ b/services/zc/app/grpc/wire_servicer.py @@ -173,31 +173,30 @@ async def StreamUploadProgress( # Check if upload is complete chunks_received = session.get('chunks_received', 0) - if True: - total_size = session['total_size'] - chunk_size = session.get('chunk_size', 1024 * 1024) - total_chunks = session.get('total_chunks', 1) - - bytes_transferred = chunks_received * chunk_size - percent_complete = (chunks_received / total_chunks) * 100 - - # Estimate transfer rate and ETA - elapsed = time.time() - session['started_at'] - transfer_rate = (bytes_transferred / elapsed / 1_000_000) if elapsed > 0 else 0 - remaining_bytes = total_size - bytes_transferred - eta_seconds = (remaining_bytes / transfer_rate / 1_000_000) if transfer_rate > 0 else 0 - - yield wire_pb2.UploadProgressStream( # type: ignore[attr-defined] - session_id=session_id, - percent_complete=percent_complete, - bytes_transferred=bytes_transferred, - bytes_total=total_size, - transfer_rate_mbps=transfer_rate, - eta_seconds=int(eta_seconds) - ) - - if chunks_received >= total_chunks: - break + total_size = session['total_size'] + chunk_size = session.get('chunk_size', 1024 * 1024) + total_chunks = session.get('total_chunks', 1) + + bytes_transferred = chunks_received * chunk_size + percent_complete = (chunks_received / total_chunks) * 100 + + # Estimate transfer rate and ETA + elapsed = time.time() - session['started_at'] + transfer_rate = (bytes_transferred / elapsed / 1_000_000) if elapsed > 0 else 0 + remaining_bytes = total_size - bytes_transferred + eta_seconds = (remaining_bytes / transfer_rate / 1_000_000) if transfer_rate > 0 else 0 + + yield wire_pb2.UploadProgressStream( # type: ignore[attr-defined] + session_id=session_id, + percent_complete=percent_complete, + bytes_transferred=bytes_transferred, + bytes_total=total_size, + transfer_rate_mbps=transfer_rate, + eta_seconds=int(eta_seconds) + ) + + if chunks_received >= total_chunks: + break await asyncio.sleep(0.5) diff --git a/services/zc/app/services/upload_manager.py b/services/zc/app/services/upload_manager.py index a4bda3b..d809e65 100644 --- a/services/zc/app/services/upload_manager.py +++ b/services/zc/app/services/upload_manager.py @@ -129,7 +129,6 @@ async def _recover_sessions(self) -> None: """Recover incomplete upload sessions from Redis.""" CacheKey.build('upload', 'session', '*') # In production, scan Redis for incomplete sessions - pass async def init_upload( self, diff --git a/services/zc/scripts/e2e_load_test.py b/services/zc/scripts/e2e_load_test.py index c71be15..27bfecc 100755 --- a/services/zc/scripts/e2e_load_test.py +++ b/services/zc/scripts/e2e_load_test.py @@ -37,6 +37,7 @@ def fetch_url(url: str, method: str = "GET", headers: Optional[dict] = None, dat req.add_header(k, v) status = 500 + response = None try: with urllib.request.urlopen(req, timeout=5) as response: status = response.getcode() diff --git a/services/zc/src/wire/main.py b/services/zc/src/wire/main.py index e08655d..9729cc9 100755 --- a/services/zc/src/wire/main.py +++ b/services/zc/src/wire/main.py @@ -62,7 +62,8 @@ def _model(args): def _read_file(path): try: - return open(path).read() + with open(path) as f: + return f.read() except Exception as e: print(f"[ERROR] Cannot read {path}: {e}", file=sys.stderr) sys.exit(1) @@ -1737,7 +1738,10 @@ def main(): show_stats=args.cache_stats); return if args.cache: from wire.zc_cache import cmd_cache_generate - docs = [open(f).read() for f in (args.cache_docs or [])] + docs = [] + for f in (args.cache_docs or []): + with open(f) as fh: + docs.append(fh.read()) cmd_cache_generate(args.prompt or "", key, model, system=args.cache_system or None, docs=docs, ttl=args.cache_ttl, show_stats=args.cache_stats, @@ -2098,7 +2102,8 @@ def main(): file_content=_read_file(args.file) if args.file else None) print(result) if args.output: - open(args.output, "w").write(result) + with open(args.output, "w") as fh: + fh.write(result) return parser.print_help() diff --git a/services/zc/src/wire/zc_git.py b/services/zc/src/wire/zc_git.py index 75cf938..69571f2 100755 --- a/services/zc/src/wire/zc_git.py +++ b/services/zc/src/wire/zc_git.py @@ -77,7 +77,8 @@ def explain_blame(file: str, line_start: int, line_end: int, cwd: str, api_key: str, model: str) -> str: blame = _git(f"git log --oneline {file}", cwd) try: - code = "\n".join(open(f"{cwd}/{file}").readlines()[line_start-1:line_end]) + with open(f"{cwd}/{file}") as f: + code = "\n".join(f.readlines()[line_start-1:line_end]) except Exception: code = "(could not read file)" return _call(api_key, model, diff --git a/services/zc/tests/test_zc_compliance_api.py b/services/zc/tests/test_zc_compliance_api.py index 9552334..b9a738c 100644 --- a/services/zc/tests/test_zc_compliance_api.py +++ b/services/zc/tests/test_zc_compliance_api.py @@ -132,9 +132,7 @@ def fake_urlopen(req, timeout=None): import urllib.error body = json.dumps({"error": {"type": "permission_error", "message": "Missing required scopes."}}).encode() - raise urllib.error.HTTPError(req.full_url, 403, "forbidden", {}, None).__class__( - req.full_url, 403, "forbidden", {}, None - ) if False else _http_error(req.full_url, 403, body) + return _http_error(req.full_url, 403, body) def _http_error(url, code, body): import io