diff --git a/doc/parse_hdlist.py b/doc/parse_hdlist.py index c06a1b0..fff0f1e 100644 --- a/doc/parse_hdlist.py +++ b/doc/parse_hdlist.py @@ -36,7 +36,6 @@ def read_header(f): """Lit un header RPM depuis un flux""" - pos = f.tell() magic = f.read(3) if not magic or len(magic) < 3: @@ -46,8 +45,8 @@ def read_header(f): # Pas un header RPM, probablement le trailer return None - version = f.read(1) - reserved = f.read(4) + _version = f.read(1) + _reserved = f.read(4) nindex = struct.unpack('>I', f.read(4))[0] hsize = struct.unpack('>I', f.read(4))[0] diff --git a/urpm/auth/audit.py b/urpm/auth/audit.py index 32f3a12..f4e7c17 100644 --- a/urpm/auth/audit.py +++ b/urpm/auth/audit.py @@ -8,10 +8,9 @@ import json import logging -import os import time from pathlib import Path -from typing import Optional, List +from typing import List from .context import AuthContext diff --git a/urpm/auth/context.py b/urpm/auth/context.py index 2d1277a..d0b73fa 100644 --- a/urpm/auth/context.py +++ b/urpm/auth/context.py @@ -9,7 +9,6 @@ import pwd from dataclasses import dataclass from enum import Flag, auto -from typing import Optional class Permission(Flag): diff --git a/urpm/auth/polkit.py b/urpm/auth/polkit.py index 6816b6d..aa4d415 100644 --- a/urpm/auth/polkit.py +++ b/urpm/auth/polkit.py @@ -14,7 +14,7 @@ """ import logging -from typing import Optional, Tuple +from typing import Tuple from .context import AuthContext, Permission diff --git a/urpm/cli/commands/appstream.py b/urpm/cli/commands/appstream.py index 1c409a0..859f4b1 100644 --- a/urpm/cli/commands/appstream.py +++ b/urpm/cli/commands/appstream.py @@ -1,6 +1,5 @@ """AppStream metadata command.""" -import gzip from datetime import datetime from pathlib import Path from typing import TYPE_CHECKING @@ -187,7 +186,7 @@ def cmd_appstream(args, db: 'PackageDatabase') -> int: print(colors.ok(f"OS metainfo file created: {metainfo_file}")) return 0 except PermissionError: - print(colors.error(f"Permission denied. Run with sudo.")) + print(colors.error("Permission denied. Run with sudo.")) return 1 except Exception as e: print(colors.error(f"Failed to create metainfo: {e}")) diff --git a/urpm/cli/commands/build.py b/urpm/cli/commands/build.py index e55ca91..9d27204 100644 --- a/urpm/cli/commands/build.py +++ b/urpm/cli/commands/build.py @@ -109,9 +109,9 @@ def cmd_mkimage(args, db: 'PackageDatabase') -> int: # Check if image already exists if container.image_exists(tag): print(colors.error(f"\nError: Image '{tag}' already exists.")) - print(f"\nTo replace it, first remove the existing image:") + print("\nTo replace it, first remove the existing image:") print(f" {runtime.name} rmi {tag}") - print(f"\nThen run mkimage again.") + print("\nThen run mkimage again.") return 1 # Base packages for build image @@ -160,7 +160,7 @@ def cmd_mkimage(args, db: 'PackageDatabase') -> int: if free_gb < MIN_SPACE_GB: print(colors.error(f"Insufficient disk space in {workdir}")) print(colors.error(f" Available: {free_gb:.1f} GB, required: {MIN_SPACE_GB} GB")) - print(colors.dim(f" Use --workdir to specify a different location")) + print(colors.dim(" Use --workdir to specify a different location")) return 1 except OSError as e: print(colors.warning(f"Could not check disk space: {e}")) @@ -243,7 +243,7 @@ def cmd_mkimage(args, db: 'PackageDatabase') -> int: print(colors.dim(f" DEBUG: rpmdb.sqlite size: {rpmdb_sqlite.stat().st_size} bytes")) else: if DEBUG_MKIMAGE: - print(colors.error(f" DEBUG: RPM db dir does not exist!")) + print(colors.error(" DEBUG: RPM db dir does not exist!")) check = subprocess.run( ['rpm', '--root', tmpdir, '-q', 'filesystem'], @@ -272,10 +272,10 @@ def cmd_mkimage(args, db: 'PackageDatabase') -> int: print(colors.success(f" DEBUG: /bin is symlink -> {bin_path.resolve()}")) elif bin_path.exists(): if DEBUG_MKIMAGE: - print(colors.error(f" DEBUG: /bin exists but is NOT a symlink!")) + print(colors.error(" DEBUG: /bin exists but is NOT a symlink!")) else: if DEBUG_MKIMAGE: - print(colors.error(f" DEBUG: /bin does not exist!")) + print(colors.error(" DEBUG: /bin does not exist!")) # Now install remaining packages (filesystem already provides /bin -> usr/bin etc) remaining_packages = [p for p in packages if p != 'filesystem'] @@ -396,7 +396,7 @@ def cmd_mkimage(args, db: 'PackageDatabase') -> int: ) ret = cmd_install(urpm_local_args, chroot_db) if ret != 0: - print(colors.error(f"Failed to install urpm")) + print(colors.error("Failed to install urpm")) return ret print(colors.success(f" Installed {rpm_path.name}")) else: @@ -427,7 +427,7 @@ def cmd_mkimage(args, db: 'PackageDatabase') -> int: print(f" Chroot size: {size_mb:.1f} MB") except Exception: pass - print(f" Archiving and importing (this may take a moment)...", end='', flush=True) + print(" Archiving and importing (this may take a moment)...", end='', flush=True) # Use podman unshare for import when not root (same UID/GID mapping as install) if not container.import_from_dir(tmpdir, tag, use_unshare=use_noscripts): print() # newline after "..." @@ -440,11 +440,11 @@ def cmd_mkimage(args, db: 'PackageDatabase') -> int: size = images[0]['size'] if images else 'unknown' print(colors.success(f"\n{'='*60}")) - print(colors.success(f"Image created successfully!")) + print(colors.success("Image created successfully!")) print(colors.success(f"{'='*60}")) print(f" Tag: {tag}") print(f" Size: {size}") - print(f"\nUsage:") + print("\nUsage:") print(f" {runtime.name} run -it {tag} /bin/bash") print(f" urpm build --image {tag} ./package.src.rpm") @@ -456,7 +456,7 @@ def cmd_mkimage(args, db: 'PackageDatabase') -> int: finally: if not keep_chroot: - print(f"\nCleaning up temporary directory...") + print("\nCleaning up temporary directory...") shutil.rmtree(tmpdir, ignore_errors=True) else: print(f"\nChroot kept at: {tmpdir}") @@ -469,7 +469,6 @@ def _cleanup_chroot_for_image(root: str): """ import glob - from .. import colors cleanup_patterns = [ 'var/cache/urpmi/*', @@ -503,7 +502,7 @@ def _cleanup_chroot_for_image(root: str): var_tmp = os.path.join(root, 'var', 'tmp') if not os.path.exists(var_tmp): os.makedirs(var_tmp, mode=0o1777, exist_ok=True) - print(f" Created /var/tmp") + print(" Created /var/tmp") # Create /etc/machine-id if missing (required by systemd, dbus, etc.) machine_id_path = os.path.join(root, 'etc', 'machine-id') @@ -513,7 +512,7 @@ def _cleanup_chroot_for_image(root: str): machine_id = uuid.uuid4().hex # 32 hex chars, no dashes with open(machine_id_path, 'w') as f: f.write(machine_id + '\n') - print(f" Created /etc/machine-id") + print(" Created /etc/machine-id") except (IOError, OSError): pass @@ -560,7 +559,7 @@ def cmd_build(args, db: 'PackageDatabase') -> int: valid_sources.append(source_path) elif source_path.suffix == '.rpm': print(colors.warning(f"Binary RPM cannot be built: {source}")) - print(colors.dim(f" Use a .src.rpm or .spec file instead")) + print(colors.dim(" Use a .src.rpm or .spec file instead")) continue else: print(colors.warning(f"Unsupported source type: {source}")) @@ -618,7 +617,7 @@ def build_one(source_path: Path) -> tuple: print(f" Output: {output_dir}") if fail_count > 0: - print(f"\nFailed packages:") + print("\nFailed packages:") for source, success, msg in results: if not success: print(f" {colors.error('X')} {source.name}: {msg}") @@ -705,14 +704,14 @@ def _build_single_package( container.exec(cid, ['/bin/update-ca-trust', 'extract']) # 3. Copy source into container - print(f" Copying source...") + print(" Copying source...") if source_path.suffix == '.rpm' and '.src.' in source_path.name: # Source RPM - install it to extract spec and sources if not container.cp(str(source_path), f"{cid}:/root/rpmbuild/SRPMS/"): return (source_path, False, "Failed to copy SRPM") - print(f" Installing SRPM...") + print(" Installing SRPM...") result = container.exec(cid, [ 'rpm', '-ivh', f'/root/rpmbuild/SRPMS/{source_path.name}' ]) @@ -741,13 +740,13 @@ def _build_single_package( # Copy entire directory content at once container.cp(f"{sources_dir}/.", f"{cid}:/root/rpmbuild/SOURCES/") else: - print(colors.warning(f" Warning: No SOURCES directory found")) + print(colors.warning(" Warning: No SOURCES directory found")) else: return (source_path, False, f"Unsupported source type: {source_path.suffix}") # 4. Install rpm-build (provides rpmbuild) - print(f" Installing rpm-build...") + print(" Installing rpm-build...") ret = container.exec_stream(cid, [ 'urpm', 'install', '--auto', '--sync', 'rpm-build' ]) @@ -755,15 +754,15 @@ def _build_single_package( return (source_path, False, "Failed to install rpm-build") # 5. Install build dependencies - print(f" Installing BuildRequires...") + print(" Installing BuildRequires...") ret = container.exec_stream(cid, [ 'urpm', 'install', '--auto', '--sync', '--builddeps', spec_path ]) if ret != 0: - return (source_path, False, f"BuildRequires install failed") + return (source_path, False, "BuildRequires install failed") # 6. Build the package - print(f" Building...") + print(" Building...") result = container.exec_stream(cid, [ 'rpmbuild', '-ba', spec_path ]) @@ -771,7 +770,7 @@ def _build_single_package( return (source_path, False, "rpmbuild failed") # 7. Copy results out - print(f" Retrieving results...") + print(" Retrieving results...") # Determine output location if is_spec_build and workspace: diff --git a/urpm/cli/commands/cache.py b/urpm/cli/commands/cache.py index 25d1b33..3f2777c 100644 --- a/urpm/cli/commands/cache.py +++ b/urpm/cli/commands/cache.py @@ -263,7 +263,7 @@ def cmd_cache_rebuild_fts(args, db: 'PackageDatabase') -> int: # Check current FTS state stats = db.get_fts_stats() - print(f"\nFTS Index Status:") + print("\nFTS Index Status:") print(f" Available: {'yes' if stats['available'] else 'no'}") print(f" Current: {'yes' if stats['current'] else 'no'}") print(f" Files in package_files: {stats['pf_count']:,}") @@ -274,7 +274,7 @@ def cmd_cache_rebuild_fts(args, db: 'PackageDatabase') -> int: rebuild_time = datetime.fromtimestamp(stats['last_rebuild']) print(f" Last rebuild: {rebuild_time.strftime('%Y-%m-%d %H:%M:%S')}") - print(f"\nRebuilding FTS index...", flush=True) + print("\nRebuilding FTS index...", flush=True) # Try to use urpmd API if running (avoids database lock issues) port = DEV_PORT if is_dev_mode() else PROD_PORT diff --git a/urpm/cli/commands/cleanup.py b/urpm/cli/commands/cleanup.py index 1978a50..13a738c 100644 --- a/urpm/cli/commands/cleanup.py +++ b/urpm/cli/commands/cleanup.py @@ -31,7 +31,7 @@ def cmd_autoremove(args, db: 'PackageDatabase') -> int: # Check for previous background errors prev_error = check_background_error() if prev_error: - print(colors.warning(f"Warning: Previous background operation had an error:")) + print(colors.warning("Warning: Previous background operation had an error:")) print(colors.warning(f" {prev_error}")) print(colors.dim(" (This message will not appear again)")) clear_background_error() @@ -256,7 +256,7 @@ def queue_progress(op_id: str, name: str, current: int, total: int): print(f"\r\033[K [{len(package_names)}/{len(package_names)}] done") if not queue_result.success: - print(colors.error(f"\nRemoval failed:")) + print(colors.error("\nRemoval failed:")) if queue_result.operations: for err in queue_result.operations[0].errors[:3]: print(f" {colors.error(err)}") @@ -266,7 +266,7 @@ def queue_progress(op_id: str, name: str, current: int, total: int): return 1 if interrupted[0]: - print(colors.warning(f"\n Autoremove interrupted")) + print(colors.warning("\n Autoremove interrupted")) db.abort_transaction(transaction_id) return 130 @@ -289,7 +289,7 @@ def queue_progress(op_id: str, name: str, current: int, total: int): return 0 - except Exception as e: + except Exception: db.abort_transaction(transaction_id) raise finally: @@ -611,7 +611,7 @@ def queue_progress(op_id: str, name: str, current: int, total: int): print(f"\r\033[K [{len(packages_to_erase)}/{len(packages_to_erase)}] done") if not queue_result.success: - print(colors.error(f"\nErase failed:")) + print(colors.error("\nErase failed:")) if queue_result.operations: for err in queue_result.operations[0].errors[:5]: print(f" {colors.error(err)}") @@ -647,7 +647,7 @@ def queue_progress(op_id: str, name: str, current: int, total: int): return 0 - except Exception as e: + except Exception: db.abort_transaction(transaction_id) raise finally: diff --git a/urpm/cli/commands/config.py b/urpm/cli/commands/config.py index 499d724..dabc1cd 100644 --- a/urpm/cli/commands/config.py +++ b/urpm/cli/commands/config.py @@ -5,7 +5,7 @@ from typing import TYPE_CHECKING if TYPE_CHECKING: - from ...core.database import PackageDatabase + pass from ..helpers.kernel import ( read_config as _read_config, diff --git a/urpm/cli/commands/depends.py b/urpm/cli/commands/depends.py index 4bcfc74..30d9efb 100644 --- a/urpm/cli/commands/depends.py +++ b/urpm/cli/commands/depends.py @@ -1135,7 +1135,7 @@ def format_dep_type(dep_type: str, short: bool = False) -> str: if not direct_rdeps: print(f"{colors.bold(pkg_name)}: {colors.warning('orphan')} (nothing requires it)") - print(f"\nThis package can be removed with: urpm autoremove --orphans") + print("\nThis package can be removed with: urpm autoremove --orphans") return 0 # For each direct rdep, find ALL paths to explicit packages using ONLY requires @@ -1174,7 +1174,7 @@ def format_dep_type(dep_type: str, short: bool = False) -> str: if not explicit_branches: print(f"{colors.bold(pkg_name)}: {colors.warning('orphan')} (no explicit package requires it)") - print(f"\nThis package can be removed with: urpm autoremove --orphans") + print("\nThis package can be removed with: urpm autoremove --orphans") return 0 # Group by explicit package diff --git a/urpm/cli/commands/history.py b/urpm/cli/commands/history.py index f838602..782e276 100644 --- a/urpm/cli/commands/history.py +++ b/urpm/cli/commands/history.py @@ -498,7 +498,7 @@ def install_progress(op_id: str, name: str, current: int, total: int): print(colors.success(f" {installed_count} packages reinstalled")) elif not_found and not rpm_paths: - print(colors.warning(f" Could not reinstall: packages not found in repositories")) + print(colors.warning(" Could not reinstall: packages not found in repositories")) if interrupted: db.abort_transaction(undo_trans_id) diff --git a/urpm/cli/commands/install.py b/urpm/cli/commands/install.py index ababb41..c13d17f 100644 --- a/urpm/cli/commands/install.py +++ b/urpm/cli/commands/install.py @@ -36,7 +36,7 @@ def cmd_install(args, db: 'PackageDatabase') -> int: """Handle install command.""" import signal import solv - from ...core.resolver import Resolver, Resolution, format_size, set_solver_debug, PackageAction, TransactionType + from ...core.resolver import Resolution, format_size, set_solver_debug, PackageAction, TransactionType from ...core.operations import PackageOperations, InstallOptions from ...core.background_install import ( check_background_error, clear_background_error, @@ -55,7 +55,7 @@ def cmd_install(args, db: 'PackageDatabase') -> int: # Check for previous background install errors prev_error = check_background_error() if prev_error: - print(colors.warning(f"Warning: Previous background operation had an error:")) + print(colors.warning("Warning: Previous background operation had an error:")) print(colors.warning(f" {prev_error}")) print(colors.dim(" (This message will not appear again)")) clear_background_error() @@ -354,7 +354,6 @@ def cmd_install(args, db: 'PackageDatabase') -> int: all_to_install = [a.name for a in result.actions] if with_suggests: suggests = [] - suggest_alternatives = [] packages_to_check = all_to_install[:] checked_packages = set(p.lower() for p in all_to_install) max_iterations = 10 # Safety limit against infinite loops @@ -409,7 +408,7 @@ def cmd_install(args, db: 'PackageDatabase') -> int: print(f" {len(filtered) + 1}) All") try: - choice = input(f"\nChoice [1]: ").strip() or "1" + choice = input("\nChoice [1]: ").strip() or "1" if choice == str(len(filtered) + 1): # "All" selected - add all providers for prov_name in filtered: @@ -530,7 +529,6 @@ def cmd_install(args, db: 'PackageDatabase') -> int: break else: suggests = [] - suggest_alternatives = [] # Calculate sizes for initial display rec_size = sum(a.size for a in rec_pkgs) @@ -547,7 +545,7 @@ def cmd_install(args, db: 'PackageDatabase') -> int: rec_names = [f"{a.name}-{a.evr}" for a in rec_pkgs] display.print_package_list(rec_names, max_lines=5) try: - answer = input(f"\nInstall recommended packages? [Y/n] ") + answer = input("\nInstall recommended packages? [Y/n] ") install_recommends_final = answer.lower() not in ('n', 'no') except EOFError: print("\nAborted") @@ -560,7 +558,7 @@ def cmd_install(args, db: 'PackageDatabase') -> int: sug_names = [f"{a.name}-{a.evr}" for a in suggests] display.print_package_list(sug_names, max_lines=5) try: - answer = input(f"\nInstall suggested packages? [Y/n] ") + answer = input("\nInstall suggested packages? [Y/n] ") install_suggests = answer.lower() not in ('n', 'no') except EOFError: print("\nAborted") @@ -594,8 +592,6 @@ def cmd_install(args, db: 'PackageDatabase') -> int: # If resolution failed and we have suggests, try removing problematic suggests skipped_suggests = {} # suggest_name -> reason if not result.success and install_suggests and suggests: - suggest_names_set = set(suggest_names) - # Find suggests mentioned in problems and store the reason for prob in result.problems: prob_str = str(prob) @@ -657,6 +653,7 @@ def cmd_install(args, db: 'PackageDatabase') -> int: sug_pkgs = [a for a in install_actions if a.reason == InstallReason.SUGGESTED] # Build set of explicit package names for history recording + # TODO: explicit_names isn't used yet explicit_names = set(a.name.lower() for a in explicit_pkgs) # Calculate final sizes @@ -879,7 +876,7 @@ def queue_progress(op_id: str, name: str, current: int, total: int): print(f"\r\033[K [{len(rpm_paths)}/{len(rpm_paths)}] done") if not queue_result.success: - print(colors.error(f"\nInstallation failed:")) + print(colors.error("\nInstallation failed:")) if queue_result.operations: for err in queue_result.operations[0].errors[:3]: print(f" {colors.error(err)}") @@ -889,7 +886,7 @@ def queue_progress(op_id: str, name: str, current: int, total: int): return 1 if interrupted[0]: - print(colors.warning(f"\n Installation interrupted")) + print(colors.warning("\n Installation interrupted")) ops.abort_transaction(transaction_id) return 130 @@ -912,7 +909,7 @@ def queue_progress(op_id: str, name: str, current: int, total: int): return 0 - except Exception as e: + except Exception: ops.abort_transaction(transaction_id) raise finally: @@ -927,9 +924,8 @@ def cmd_download(args, db: 'PackageDatabase') -> int: """ import time import platform - from pathlib import Path - from ...core.resolver import Resolver, Resolution, format_size, set_solver_debug, PackageAction + from ...core.resolver import Resolution, format_size, set_solver_debug, PackageAction from ...core.download import Downloader, DownloadItem from ...core.config import get_base_dir from .. import colors @@ -1005,7 +1001,7 @@ def cmd_download(args, db: 'PackageDatabase') -> int: auto_mode = getattr(args, 'auto', False) # Show what we're downloading - print(colors.info(f"\nResolving packages for download...")) + print(colors.info("\nResolving packages for download...")) if target_release: print(f" Target release: {target_release}") print(f" Target arch: {target_arch}") @@ -1208,7 +1204,7 @@ def progress(name, pkg_num, pkg_total, bytes_done, bytes_total, if downloaded > 0: _notify_urpmd_cache_invalidate() - print(colors.success(f"\nPackages saved to cache. Use 'urpm install' to install them.")) + print(colors.success("\nPackages saved to cache. Use 'urpm install' to install them.")) return 0 diff --git a/urpm/cli/commands/media.py b/urpm/cli/commands/media.py index 5b22a66..f12feac 100644 --- a/urpm/cli/commands/media.py +++ b/urpm/cli/commands/media.py @@ -7,12 +7,7 @@ from ...core.database import PackageDatabase from ..helpers.media import ( - KNOWN_VERSIONS, KNOWN_ARCHES, - KNOWN_CLASSES, - KNOWN_TYPES, - generate_media_name as _generate_media_name, - generate_short_name as _generate_short_name, generate_server_name as _generate_server_name, parse_mageia_media_url, parse_custom_media_url, @@ -375,8 +370,7 @@ def is_proc_mounted(chroot_proc: Path) -> bool: pass # Initialize empty rpmdb in the chroot - rpmdb_dir = root_path / "var/lib/rpm" - print(f"Initializing rpmdb...") + print("Initializing rpmdb...") result = subprocess.run( ['rpm', '--root', urpm_root, '--initdb'], capture_output=True, text=True @@ -386,7 +380,7 @@ def is_proc_mounted(chroot_proc: Path) -> bool: return 1 # Import Mageia GPG key into the chroot - print(f"Importing Mageia GPG key...") + print("Importing Mageia GPG key...") # Try to copy host's Mageia key to chroot key_paths = [ '/etc/pki/rpm-gpg/RPM-GPG-KEY-Mageia', @@ -424,7 +418,7 @@ def is_proc_mounted(chroot_proc: Path) -> bool: return 1 # Fetch mirrorlist - print(f"Fetching mirrorlist...", end=' ', flush=True) + print("Fetching mirrorlist...", end=' ', flush=True) try: req = Request(mirrorlist_url, headers={'User-Agent': 'urpm/0.1'}) @@ -490,7 +484,7 @@ def test_latency(candidate): try: start = time.time() req = Request(test_url, method='HEAD') - with urlopen(req, timeout=5) as resp: + with urlopen(req, timeout=5): latency = (time.time() - start) * 1000 return (candidate, latency) except Exception: @@ -514,12 +508,12 @@ def test_latency(candidate): results.sort(key=lambda x: x[1]) best_mirrors = results[:3] - print(f"\nBest mirrors:") + print("\nBest mirrors:") for candidate, latency in best_mirrors: print(f" {candidate['host']} ({latency:.0f}ms)") # Add servers - print(f"\nAdding servers...") + print("\nAdding servers...") servers_added = [] for candidate, latency in best_mirrors: @@ -607,7 +601,7 @@ def test_latency(candidate): return 1 # Link servers to media - print(f"\nLinking servers to media...") + print("\nLinking servers to media...") for server in servers_added: for media in media_added: if not db.server_media_link_exists(server['id'], media['id']): @@ -617,7 +611,7 @@ def test_latency(candidate): # Sync media unless --no-sync if not getattr(args, 'no_sync', False): - print(f"\nSyncing media metadata...") + print("\nSyncing media metadata...") # Trigger sync for all media for media in media_added: media_name = media.get('name', '') @@ -1028,7 +1022,7 @@ def parallel_progress(media_name, stage, current, total): # Sync files.xml if requested if sync_files: - print(f"\nSyncing files.xml...") + print("\nSyncing files.xml...") # Track status for each media (same pattern as synthesis sync) # Filter by version/arch like sync_all_files_xml does @@ -1411,7 +1405,6 @@ def cmd_media_import(args, db: 'PackageDatabase') -> int: def cmd_media_set(args, db: 'PackageDatabase') -> int: """Handle media set command - modify media settings.""" from .. import colors - from datetime import datetime # Handle --all option for sync_files use_all = getattr(args, 'all', False) @@ -1534,7 +1527,6 @@ def cmd_media_seed_info(args, db: 'PackageDatabase') -> int: """Show seed set info for a media.""" from .. import colors import json - from pathlib import Path from ...core.rpmsrate import RpmsrateParser, DEFAULT_RPMSRATE_PATH media = db.get_media(args.name) @@ -1870,7 +1862,7 @@ def test_mirror(url): req = Request(test_url, method='HEAD') req.add_header('User-Agent', 'urpm-ng') start = time.time() - with urlopen(req, timeout=5) as response: + with urlopen(req, timeout=5): latency = time.time() - start return (latency, url) except Exception: @@ -1917,6 +1909,7 @@ def extract_base_url(mirror_url, release, arch): skipped = 0 # First, add servers from best mirrors + # TODO: this server isn't actually used server_to_use = None for latency, mirror_url in best_mirrors[:1]: # Just use the best one base_url = extract_base_url(mirror_url, release, arch) diff --git a/urpm/cli/commands/mirror.py b/urpm/cli/commands/mirror.py index 0876456..c37765c 100644 --- a/urpm/cli/commands/mirror.py +++ b/urpm/cli/commands/mirror.py @@ -197,7 +197,7 @@ def cmd_mirror_sync(args, db: 'PackageDatabase') -> int: from ..helpers.debug import notify_urpmd_cache_invalidate as _notify_urpmd_cache_invalidate from ...core.rpmsrate import RpmsrateParser, DEFAULT_RPMSRATE_PATH from ...core.download import Downloader, DownloadItem - from ...core.config import get_media_local_path, build_media_url + from ...core.config import get_media_local_path import json # Default sections (same as DVD content) @@ -476,7 +476,7 @@ def progress(name, pkg_num, pkg_total, bytes_done, bytes_total, _notify_urpmd_cache_invalidate() if failed: - print(colors.warning(f"\nFailed downloads:")) + print(colors.warning("\nFailed downloads:")) for r in failed[:10]: print(f" {r.item.name}: {r.error}") if len(failed) > 10: diff --git a/urpm/cli/commands/peer.py b/urpm/cli/commands/peer.py index 1d8f8de..d64cf74 100644 --- a/urpm/cli/commands/peer.py +++ b/urpm/cli/commands/peer.py @@ -178,7 +178,7 @@ def cmd_peer(args, db: 'PackageDatabase') -> int: # Confirm deletion if not args.yes: - print(f"\nFiles to delete:") + print("\nFiles to delete:") show_all = getattr(args, 'show_all', False) display.print_package_list([str(p) for p in existing], max_lines=10, show_all=show_all) diff --git a/urpm/cli/commands/query.py b/urpm/cli/commands/query.py index 29b119f..b180585 100644 --- a/urpm/cli/commands/query.py +++ b/urpm/cli/commands/query.py @@ -261,7 +261,6 @@ def cmd_show(args, db: 'PackageDatabase') -> int: def cmd_list(args, db: 'PackageDatabase') -> int: """Handle list command.""" - import platform filter_type = getattr(args, 'filter', 'installed') @@ -370,7 +369,6 @@ def cmd_provides(args, db: 'PackageDatabase') -> int: ts = rpm.TransactionSet() # Try exact name first - found = False for hdr in ts.dbMatch('name', pkg_name): # If NEVRA was given, check it matches version = hdr[rpm.RPMTAG_VERSION] @@ -391,7 +389,6 @@ def cmd_provides(args, db: 'PackageDatabase') -> int: provides.append(f"{prov} = {ver}") else: provides.append(prov) - found = True break except ImportError: diff --git a/urpm/cli/commands/remove.py b/urpm/cli/commands/remove.py index 78787b8..aedfad1 100644 --- a/urpm/cli/commands/remove.py +++ b/urpm/cli/commands/remove.py @@ -18,10 +18,9 @@ def cmd_erase(args, db: 'PackageDatabase') -> int: """Handle erase (remove) command.""" - import platform import signal - from ...core.resolver import Resolver, format_size, set_solver_debug + from ...core.resolver import format_size, set_solver_debug from ...core.install import check_root from ...core.operations import PackageOperations, InstallOptions from ...core.background_install import ( @@ -33,7 +32,7 @@ def cmd_erase(args, db: 'PackageDatabase') -> int: # Check for previous background errors prev_error = check_background_error() if prev_error: - print(colors.warning(f"Warning: Previous background operation had an error:")) + print(colors.warning("Warning: Previous background operation had an error:")) print(colors.warning(f" {prev_error}")) print(colors.dim(" (This message will not appear again)")) clear_background_error() @@ -247,7 +246,7 @@ def queue_progress(op_id: str, name: str, current: int, total: int): print(f"\r\033[K [{len(packages_to_erase)}/{len(packages_to_erase)}] done") if not queue_result.success: - print(colors.error(f"\nErase failed:")) + print(colors.error("\nErase failed:")) if queue_result.operations: for err in queue_result.operations[0].errors[:3]: print(f" {colors.error(err)}") @@ -259,7 +258,7 @@ def queue_progress(op_id: str, name: str, current: int, total: int): return 1 if interrupted[0]: - print(colors.warning(f"\n Erase interrupted")) + print(colors.warning("\n Erase interrupted")) ops.abort_transaction(transaction_id) return 130 @@ -281,7 +280,7 @@ def queue_progress(op_id: str, name: str, current: int, total: int): return 0 - except Exception as e: + except Exception: ops.abort_transaction(transaction_id) raise finally: diff --git a/urpm/cli/commands/server.py b/urpm/cli/commands/server.py index d94716a..a2d1d87 100644 --- a/urpm/cli/commands/server.py +++ b/urpm/cli/commands/server.py @@ -186,7 +186,7 @@ def patched(host, port, fam=0, type=0, proto=0, flags=0): for _, media_name in sorted(found, key=lambda x: x[1]): print(f" {colors.success('+')} {media_name}") else: - print(colors.warning(f"No existing media found on this server")) + print(colors.warning("No existing media found on this server")) return 0 @@ -319,7 +319,6 @@ def cmd_server_ipmode(args, db: 'PackageDatabase') -> int: def cmd_server_autoconfig(args, db: 'PackageDatabase') -> int: """Handle server autoconfig command - auto-discover servers from Mageia mirrorlist.""" from .. import colors - from ..helpers.media import generate_server_name as _generate_server_name from urllib.request import urlopen, Request from urllib.error import URLError, HTTPError from urllib.parse import urlparse @@ -441,7 +440,7 @@ def test_latency(candidate): try: start = time.time() req = Request(test_url, method='HEAD') - with urlopen(req, timeout=5) as resp: + with urlopen(req, timeout=5): latency = (time.time() - start) * 1000 return (candidate, latency) except Exception: diff --git a/urpm/cli/commands/upgrade.py b/urpm/cli/commands/upgrade.py index a859f21..2c391c1 100644 --- a/urpm/cli/commands/upgrade.py +++ b/urpm/cli/commands/upgrade.py @@ -14,15 +14,10 @@ copy_installed_deps_list as _copy_installed_deps_list, ) from ..helpers.resolver import create_resolver as _create_resolver -from ..helpers.alternatives import ( - PreferencesMatcher, - _resolve_with_alternatives, -) def cmd_upgrade(args, db: 'PackageDatabase') -> int: """Handle upgrade command - upgrade packages.""" - import platform import signal import time @@ -36,7 +31,7 @@ def cmd_upgrade(args, db: 'PackageDatabase') -> int: # Check for previous background install errors prev_error = check_background_error() if prev_error: - print(colors.warning(f"Warning: Previous background operation had an error:")) + print(colors.warning("Warning: Previous background operation had an error:")) print(colors.warning(f" {prev_error}")) print(colors.dim(" (This message will not appear again)")) clear_background_error() @@ -46,7 +41,7 @@ def cmd_upgrade(args, db: 'PackageDatabase') -> int: _clear_debug_file(DEBUG_LAST_INSTALLED_DEPS) _clear_debug_file(DEBUG_LAST_REMOVED_DEPS) - from ...core.resolver import Resolver, format_size, set_solver_debug + from ...core.resolver import format_size, set_solver_debug from ...core.install import check_root from pathlib import Path from ...core.rpm import is_local_rpm, read_rpm_header @@ -363,10 +358,10 @@ def queue_progress(op_id: str, name: str, current: int, total: int): ) # Clear the line after last progress - print(f"\r\033[K", end='') + print("\r\033[K", end='') if interrupted[0]: - print(colors.warning(f"\n Operation interrupted")) + print(colors.warning("\n Operation interrupted")) ops.abort_transaction(transaction_id) return 130 @@ -385,7 +380,7 @@ def queue_progress(op_id: str, name: str, current: int, total: int): print(colors.success(f" {', '.join(msg_parts)}")) else: upgrade_success = False - print(colors.error(f"\nUpgrade failed:")) + print(colors.error("\nUpgrade failed:")) for err in op_result.errors[:3]: print(f" {colors.error(err)}") @@ -418,7 +413,7 @@ def queue_progress(op_id: str, name: str, current: int, total: int): return 0 - except Exception as e: + except Exception: ops.abort_transaction(transaction_id) raise finally: diff --git a/urpm/cli/display.py b/urpm/cli/display.py index ba94a14..532bdb1 100644 --- a/urpm/cli/display.py +++ b/urpm/cli/display.py @@ -411,7 +411,6 @@ def update(self, pkg_num: int, pkg_total: int, bytes_done: int, bytes_total: int Args: Same as render() """ - import sys # Get terminal width to truncate lines (avoid wrapping issues) term_width = get_terminal_width() diff --git a/urpm/cli/helpers/alternatives.py b/urpm/cli/helpers/alternatives.py index 649c050..c284205 100644 --- a/urpm/cli/helpers/alternatives.py +++ b/urpm/cli/helpers/alternatives.py @@ -6,12 +6,10 @@ - _handle_bloc_choices: Handle bloc-based alternative choices """ -import re from typing import TYPE_CHECKING if TYPE_CHECKING: - from ...core.database import PackageDatabase - from ...core.resolver import Resolver, Resolution + pass from .resolver import _group_by_version @@ -209,9 +207,9 @@ def _find_compatible_providers(self, pool) -> None: if DEBUG_PREFERENCES: if 'php8.4-fpm-apache' in self._compatible_providers: - print(f"DEBUG: php8.4-fpm-apache IS in _compatible_providers") + print("DEBUG: php8.4-fpm-apache IS in _compatible_providers") else: - print(f"DEBUG: php8.4-fpm-apache NOT in _compatible_providers") + print("DEBUG: php8.4-fpm-apache NOT in _compatible_providers") print(f"DEBUG: provided_caps sample: {list(provided_caps)[:10]}") def match_bloc_version(self, bloc_defining_caps: dict, bloc_key: str) -> bool: @@ -526,7 +524,6 @@ def _resolve_with_alternatives(resolver, packages: list, choices: dict, """ if local_packages is None: local_packages = set() - from .. import colors import solv if preferences is None: @@ -607,7 +604,7 @@ def expand_choice(pkg_name: str, choices: dict): versionless = version_groups.pop(None, set()) if len(version_groups) > 1 and not auto_mode: # Multiple versions detected, ask user - print(f"\nMultiple versions in preferences:") + print("\nMultiple versions in preferences:") sorted_versions = sorted(version_groups.keys()) for i, ver in enumerate(sorted_versions, 1): pkgs = version_groups[ver] diff --git a/urpm/cli/helpers/kernel.py b/urpm/cli/helpers/kernel.py index 87c9062..6b183be 100644 --- a/urpm/cli/helpers/kernel.py +++ b/urpm/cli/helpers/kernel.py @@ -163,6 +163,7 @@ def get_blacklist() -> set: } # Dynamic: running kernel + # TODO: running is not actually used yet running = get_running_kernel() # Add kernel packages matching running version # The kernel name pattern is kernel---. diff --git a/urpm/cli/helpers/package.py b/urpm/cli/helpers/package.py index fdefc10..c15de6f 100644 --- a/urpm/cli/helpers/package.py +++ b/urpm/cli/helpers/package.py @@ -147,12 +147,12 @@ def resolve_virtual_package(db: 'PackageDatabase', pkg_name: str, auto: bool, in installed_str = ', '.join(sorted(installed_families)) print(f"\nWarning: '{pkg_name}' is only provided by {provider_name}") print(f" but you have {installed_str} installed.") - print(f" This will likely cause conflicts!") + print(" This will likely cause conflicts!") if auto: print("Aborting (use explicit package name to force)") return [] try: - answer = input(f"\nInstall anyway? [y/N] ").strip() + answer = input("\nInstall anyway? [y/N] ").strip() if answer.lower() not in ('y', 'yes'): return [] except (EOFError, KeyboardInterrupt): @@ -173,7 +173,7 @@ def resolve_virtual_package(db: 'PackageDatabase', pkg_name: str, auto: bool, in print(f" {len(sorted_families) + 1}) All") try: - choice = input(f"\nChoice [1]: ").strip() or "1" + choice = input("\nChoice [1]: ").strip() or "1" if choice == str(len(sorted_families) + 1): return [families[f][0]['name'] for f in sorted_families] idx = int(choice) - 1 @@ -205,7 +205,7 @@ def resolve_virtual_package(db: 'PackageDatabase', pkg_name: str, auto: bool, in print(f" {len(sorted_families) + 1}) All") try: - choice = input(f"\nChoice [1]: ").strip() or "1" + choice = input("\nChoice [1]: ").strip() or "1" if choice == str(len(sorted_families) + 1): return [matching_families[f][0]['name'] for f in sorted_families] idx = int(choice) - 1 diff --git a/urpm/cli/main.py b/urpm/cli/main.py index 879397e..463ab29 100755 --- a/urpm/cli/main.py +++ b/urpm/cli/main.py @@ -12,70 +12,11 @@ """ import argparse -import shutil -import subprocess +import importlib import sys -import time -from pathlib import Path from .. import __version__ from ..core.database import PackageDatabase -from .helpers.package import ( - extract_pkg_name as _extract_pkg_name, - extract_family as _extract_family, - get_installed_families as _get_installed_families, - resolve_virtual_package as _resolve_virtual_package, -) -from .helpers.debug import ( - DEBUG_LAST_INSTALLED_DEPS, - DEBUG_LAST_REMOVED_DEPS, - DEBUG_INSTALLED_DEPS_COPY, - DEBUG_PREV_INSTALLED_DEPS, - write_debug_file as _write_debug_file, - clear_debug_file as _clear_debug_file, - copy_installed_deps_list as _copy_installed_deps_list, - notify_urpmd_cache_invalidate as _notify_urpmd_cache_invalidate, -) -from .helpers.kernel import ( - CONFIG_FILE, - get_running_kernel as _get_running_kernel, - get_root_fstype as _get_root_fstype, - get_blacklist as _get_blacklist, - get_redlist as _get_redlist, - read_config as _read_config, - write_config as _write_config, - get_user_blacklist as _get_user_blacklist, - get_user_redlist as _get_user_redlist, - get_kernel_keep as _get_kernel_keep, - is_running_kernel as _is_running_kernel, - find_old_kernels as _find_old_kernels, - find_faildeps as _find_faildeps, -) -from .helpers.resolver import ( - extract_version as _extract_version, - group_by_version as _group_by_version, - create_resolver as _create_resolver, -) -from .helpers.alternatives import ( - PreferencesMatcher, - _resolve_with_alternatives, - _handle_bloc_choices, -) -from .helpers.media import ( - KNOWN_VERSIONS, - KNOWN_ARCHES, - KNOWN_CLASSES, - KNOWN_TYPES, - generate_media_name as _generate_media_name, - generate_short_name as _generate_short_name, - generate_server_name as _generate_server_name, - parse_mageia_media_url, - parse_custom_media_url, - fetch_media_pubkey as _fetch_media_pubkey, - get_gpg_key_info as _get_gpg_key_info, - is_key_in_rpm_keyring as _is_key_in_rpm_keyring, - import_gpg_key as _import_gpg_key, -) from .commands.cache import ( cmd_cache_info, cmd_cache_clean, @@ -100,8 +41,7 @@ cmd_media_list, cmd_init, cmd_media_add, cmd_media_remove, cmd_media_enable, cmd_media_disable, cmd_media_update, cmd_media_import, cmd_media_set, cmd_media_seed_info, - cmd_media_link, cmd_media_autoconfig, parse_urpmi_cfg, - STANDARD_MEDIA_TYPES, + cmd_media_link, cmd_media_autoconfig, ) from .commands.query import ( cmd_search, cmd_show, cmd_list, cmd_provides, cmd_whatprovides, cmd_find, @@ -116,7 +56,7 @@ cmd_upgrade, ) from .commands.cleanup import ( - cmd_autoremove, cmd_mark, cmd_hold, cmd_unhold, cmd_cleandeps, + cmd_autoremove, cmd_mark, cmd_hold, cmd_unhold, ) from .commands.depends import ( cmd_depends, cmd_rdepends, cmd_recommends, cmd_whatrecommends, @@ -146,15 +86,11 @@ def check_dependencies() -> list: missing = [] # Check libsolv (required for dependency resolution) - try: - import solv - except ImportError: + if not importlib.util.find_spec('solv'): missing.append(('python3-solv', 'dependency resolution')) # Check zstandard (required for .cz decompression) - try: - import zstandard - except ImportError: + if not importlib.util.find_spec('zstandard'): missing.append(('python3-zstandard', 'synthesis decompression')) return missing @@ -165,7 +101,7 @@ def print_missing_dependencies(missing: list): print("ERROR: Missing required Python modules:\n", file=sys.stderr) for pkg, purpose in missing: print(f" - {pkg} ({purpose})", file=sys.stderr) - print(f"\nInstall with:", file=sys.stderr) + print("\nInstall with:", file=sys.stderr) print(f" urpmi {' '.join(pkg for pkg, _ in missing)}", file=sys.stderr) @@ -364,6 +300,7 @@ def create_parser() -> argparse.ArgumentParser: # ========================================================================= # cleanup - Unmount chroot filesystems # ========================================================================= + # TODO: cleanup_parser isn't used yet cleanup_parser = subparsers.add_parser( 'cleanup', help='Unmount chroot filesystems (/dev, /proc)', @@ -1811,6 +1748,7 @@ def create_parser() -> argparse.ArgumentParser: ) # peer list / ls - list known peers and their stats + # TODO: peer_list isn't used yet peer_list = peer_subparsers.add_parser( 'list', aliases=['ls'], help='List peers and download statistics' @@ -1905,6 +1843,7 @@ def create_parser() -> argparse.ArgumentParser: ) # appstream status + # TODO: appstream_status isn't used yet appstream_status = appstream_subparsers.add_parser( 'status', help='Show AppStream status for all media' diff --git a/urpm/core/background_install.py b/urpm/core/background_install.py index 2223a7a..e8f0b95 100644 --- a/urpm/core/background_install.py +++ b/urpm/core/background_install.py @@ -23,8 +23,6 @@ import json import logging import os -import signal -import sys import time from dataclasses import dataclass from pathlib import Path diff --git a/urpm/core/cache.py b/urpm/core/cache.py index c4c370e..8e57348 100644 --- a/urpm/core/cache.py +++ b/urpm/core/cache.py @@ -9,10 +9,8 @@ """ import logging -import os -import time from pathlib import Path -from typing import Dict, List, Optional, Tuple, Any +from typing import Dict, List, Tuple, Any from .database import PackageDatabase from .config import get_base_dir diff --git a/urpm/core/compression.py b/urpm/core/compression.py index cda11d6..894d460 100644 --- a/urpm/core/compression.py +++ b/urpm/core/compression.py @@ -8,6 +8,8 @@ - bzip2 (legacy) """ +import shutil +import subprocess from pathlib import Path from typing import Union @@ -18,10 +20,6 @@ MAGIC_BZ2 = b'BZ' -import subprocess -import shutil - - def _decompress_zstd_subprocess(data: bytes) -> bytes: """Decompress zstd data using zstdcat subprocess (fallback).""" result = subprocess.run( diff --git a/urpm/core/config.py b/urpm/core/config.py index 7101534..856a47e 100644 --- a/urpm/core/config.py +++ b/urpm/core/config.py @@ -24,7 +24,6 @@ # Comments start with # """ -import os import sys from pathlib import Path from typing import Optional diff --git a/urpm/core/container.py b/urpm/core/container.py index c8f9020..dc6cbc0 100644 --- a/urpm/core/container.py +++ b/urpm/core/container.py @@ -10,7 +10,7 @@ import subprocess from dataclasses import dataclass from pathlib import Path -from typing import List, Optional, Tuple +from typing import List, Tuple logger = logging.getLogger(__name__) diff --git a/urpm/core/database.py b/urpm/core/database.py index b0503a1..ec3aa6e 100644 --- a/urpm/core/database.py +++ b/urpm/core/database.py @@ -10,7 +10,7 @@ import threading import time from pathlib import Path -from typing import Callable, Dict, List, Optional, Any, Iterator, Set, Tuple +from typing import Dict, List, Optional, Any, Iterator, Set from .db import ( MediaMixin, ServerMixin, ConstraintsMixin, @@ -805,8 +805,8 @@ def _apply_migrations(self, from_version: int): logger.error(f"Migration v{version} -> v{to_version} failed: {e}") if "locked" in str(e): raise RuntimeError( - f"Database migration failed: database is locked.\n" - f"Try: sudo systemctl stop urpmd && urpm --version && sudo systemctl start urpmd" + "Database migration failed: database is locked.\n" + "Try: sudo systemctl stop urpmd && urpm --version && sudo systemctl start urpmd" ) raise RuntimeError(f"Database migration failed: {e}") diff --git a/urpm/core/db/files.py b/urpm/core/db/files.py index 951b59d..338cbc3 100644 --- a/urpm/core/db/files.py +++ b/urpm/core/db/files.py @@ -144,7 +144,6 @@ def search_files( List of dicts with keys: file_path, pkg_nevra, media_id, media_name """ import logging - import os.path logger = logging.getLogger(__name__) diff --git a/urpm/core/db/media.py b/urpm/core/db/media.py index 0e456da..19535b0 100644 --- a/urpm/core/db/media.py +++ b/urpm/core/db/media.py @@ -4,7 +4,7 @@ from typing import Dict, List, Optional, TYPE_CHECKING if TYPE_CHECKING: - import sqlite3 + pass class MediaMixin: diff --git a/urpm/core/download.py b/urpm/core/download.py index 4e10ffc..aaa96a6 100644 --- a/urpm/core/download.py +++ b/urpm/core/download.py @@ -8,7 +8,6 @@ import hashlib import logging -import os import queue import threading import urllib.request @@ -20,8 +19,7 @@ from .database import PackageDatabase from .config import get_base_dir, is_dev_mode from .peer_client import ( - PeerClient, Peer, create_download_plan, summarize_download_plan, - DownloadAssignment + PeerClient, Peer, create_download_plan, DownloadAssignment ) logger = logging.getLogger(__name__) @@ -81,6 +79,7 @@ def verify_rpm_signature(rpm_path: Path) -> tuple: try: with open(rpm_path, 'rb') as f: # hdrFromFdno verifies signature when VSFlags allows it + # TODO: hdr isn't used yet hdr = ts.hdrFromFdno(f.fileno()) return (True, None) except rpm.error as e: @@ -837,7 +836,6 @@ def download_one(self, item: DownloadItem, DownloadResult with status """ import time - import socket # Check cache first cache_path = self.get_cache_path(item) diff --git a/urpm/core/files_xml.py b/urpm/core/files_xml.py index 01cd6ee..8dce63e 100644 --- a/urpm/core/files_xml.py +++ b/urpm/core/files_xml.py @@ -54,9 +54,11 @@ def parse_files_xml( # Determine if compressed if path.suffix == '.lzma' or str(path).endswith('.xml.lzma'): - opener = lambda p: lzma.open(p, 'rb') + def opener(p): + return lzma.open(p, 'rb') else: - opener = lambda p: open(p, 'rb') + def opener(p): + return open(p, 'rb') pkg_count = 0 file_count = 0 @@ -160,18 +162,23 @@ def search_files_xml( regex = re.compile(fnmatch.translate(pattern), re.IGNORECASE) else: regex = re.compile(fnmatch.translate(pattern)) - match_func = lambda f: regex.match(f) + def match_func(f): + return regex.match(f) elif exact_match: if case_sensitive: - match_func = lambda f: f == pattern + def match_func(f): + return f == pattern else: - match_func = lambda f: f.lower() == pattern_lower + def match_func(f): + return f.lower() == pattern_lower else: # Substring match if case_sensitive: - match_func = lambda f: pattern in f + def match_func(f): + return pattern in f else: - match_func = lambda f: pattern_lower in f.lower() + def match_func(f): + return pattern_lower in f.lower() for nevra, files in parse_files_xml(path): for filepath in files: @@ -205,9 +212,11 @@ def extract_nevras_from_files_xml(path: Path) -> Set[str]: # Determine if compressed if path.suffix == '.lzma' or str(path).endswith('.xml.lzma'): - opener = lambda p: lzma.open(p, 'rb') + def opener(p): + return lzma.open(p, 'rb') else: - opener = lambda p: open(p, 'rb') + def opener(p): + return open(p, 'rb') try: with opener(path) as f: diff --git a/urpm/core/install.py b/urpm/core/install.py index e2ad2fd..30a8979 100644 --- a/urpm/core/install.py +++ b/urpm/core/install.py @@ -4,13 +4,14 @@ Handles package installation using python3-rpm bindings. """ +import importlib import logging import os import rpm import time from dataclasses import dataclass from pathlib import Path -from typing import List, Callable, Optional +from typing import List, Callable logger = logging.getLogger(__name__) @@ -470,7 +471,6 @@ def erase(self, package_names: List[str], ts = rpm.TransactionSet(self.root or '/') errors = [] - total = len(package_names) found = 0 # Add packages to erase @@ -563,11 +563,7 @@ def erase_batched(self, package_names: List[str], def check_rpm_available() -> bool: """Check if rpm module is available.""" - try: - import rpm - return True - except ImportError: - return False + return importlib.util.find_spec('rpm') is not None def check_root() -> bool: diff --git a/urpm/core/operations.py b/urpm/core/operations.py index 718194f..306aead 100644 --- a/urpm/core/operations.py +++ b/urpm/core/operations.py @@ -14,8 +14,7 @@ """ import logging -import time -from dataclasses import dataclass, field +from dataclasses import dataclass from pathlib import Path from typing import List, Dict, Any, Optional, Callable, Tuple @@ -27,7 +26,7 @@ # Optional auth imports - available when urpm.auth is installed try: - from ..auth.context import AuthContext, Permission, AuthError + from ..auth.context import AuthContext, Permission from ..auth.audit import AuditLogger _HAS_AUTH = True except ImportError: diff --git a/urpm/core/peer_client.py b/urpm/core/peer_client.py index 5cfc886..b4ca9c2 100644 --- a/urpm/core/peer_client.py +++ b/urpm/core/peer_client.py @@ -12,7 +12,7 @@ import urllib.error from concurrent.futures import ThreadPoolExecutor, as_completed from dataclasses import dataclass, field -from typing import Dict, List, Optional, Set +from typing import Dict, List, Optional from .config import PROD_PORT, DEV_PORT, PROD_DISCOVERY_PORT, DEV_DISCOVERY_PORT, is_dev_mode from .. import __version__ @@ -249,7 +249,6 @@ def _scan_lan_udp(self) -> List[Peer]: sock.sendto(data, ('', self.discovery_port)) # Collect responses - end_time = socket.getdefaulttimeout() while True: try: response_data, addr = sock.recvfrom(4096) diff --git a/urpm/core/resolution/orphans.py b/urpm/core/resolution/orphans.py index 5e75077..70e3c25 100644 --- a/urpm/core/resolution/orphans.py +++ b/urpm/core/resolution/orphans.py @@ -928,7 +928,7 @@ def get_all_deps(pkg_name: str) -> set: f.write(f"Initial candidates: {len(to_remove) + len(removed_from_candidates)}\n") f.write(f"Removed from candidates: {len(removed_from_candidates)}\n") f.write(f"Final to_remove: {len(to_remove)}\n\n") - f.write(f"Packages that must stay (R=Requires, M=Recommends, S=Suggests):\n") + f.write("Packages that must stay (R=Requires, M=Recommends, S=Suggests):\n") for pkg in sorted(removed_from_candidates.keys()): blocker, dep_type, cap = removed_from_candidates[pkg] f.write(f" {pkg} <-[{dep_type}]- {blocker} (via {cap})\n") diff --git a/urpm/core/resolution/pool.py b/urpm/core/resolution/pool.py index dd1073d..11f3b07 100644 --- a/urpm/core/resolution/pool.py +++ b/urpm/core/resolution/pool.py @@ -36,7 +36,7 @@ def _create_pool(self) -> solv.Pool: """ from ..config import get_media_local_path, get_base_dir, get_system_version from ..compression import decompress_stream - from ..resolver import get_solver_debug, parse_capability, VersionConflictError + from ..resolver import get_solver_debug, VersionConflictError debug = get_solver_debug() diff --git a/urpm/core/resolver.py b/urpm/core/resolver.py index 9b9a95e..95774be 100644 --- a/urpm/core/resolver.py +++ b/urpm/core/resolver.py @@ -4,24 +4,18 @@ Uses the SAT-based libsolv library for fast, correct dependency resolution. """ +import importlib import re import solv -from pathlib import Path -from typing import List, Dict, Optional, Tuple +from typing import List, Dict from dataclasses import dataclass from enum import Enum -try: - import rpm - HAS_RPM = True -except ImportError: - HAS_RPM = False - from .database import PackageDatabase -from .config import get_media_local_path, get_base_dir, get_system_version -from .compression import decompress_stream from .resolution import PoolMixin, QueriesMixin, AlternativesMixin, OrphansMixin +HAS_RPM = importlib.util.find_spec('rpm') is not None + class VersionConflictError(Exception): """Raised when media configuration has ambiguous version mix (e.g., both mga10 and cauldron).""" @@ -485,6 +479,7 @@ def pkg_matches_preferences(solvable, patterns: list) -> bool: for name in package_names: # Parse version constraint if present (formats: "name >= ver" or "name[>= ver]") base_name = name + # TODO: version_constraint isn't used yet version_constraint = None # Handle "name op version" format (space-separated) @@ -719,6 +714,7 @@ def build_dependency_graph(self, resolution: Resolution, # Build dependency graph graph = {name: [] for name in resolved_names} + # TODO: requested_lower isn't used yet requested_lower = {n.lower() for n in requested_names} for name in resolved_names: diff --git a/urpm/core/sync.py b/urpm/core/sync.py index 2690c7e..ab4b73f 100644 --- a/urpm/core/sync.py +++ b/urpm/core/sync.py @@ -8,17 +8,19 @@ import shutil import tempfile import time -import urllib.request import urllib.error -from pathlib import Path -from typing import Optional, Callable, Tuple, List, Dict +import urllib.request from dataclasses import dataclass +from pathlib import Path +from typing import Callable, Dict, List, Optional, Tuple -from .compression import decompress, decompress_stream -from .synthesis import parse_synthesis -from .hdlist import parse_hdlist -from .database import PackageDatabase +# Import from config +from .config import build_media_url, get_base_dir, get_media_local_path, is_local_server +# Deprecated imports (kept for migration) +from .config import get_hostname_from_url, get_media_dir +from .database import PackageDatabase +from .synthesis import parse_synthesis # Default paths for media metadata SYNTHESIS_PATH = "media_info/synthesis.hdlist.cz" @@ -28,12 +30,6 @@ APPSTREAM_PATH = "media_info/appstream.xml.lzma" -# Import from config -from .config import get_base_dir, get_media_local_path, build_server_url, build_media_url, is_local_server -# Deprecated imports (kept for migration) -from .config import get_hostname_from_url, get_media_dir - - def get_media_cache_dir(media_name: str, media_url: str, base_dir: Path = None) -> Path: """DEPRECATED: Use get_media_local_path() instead. @@ -527,20 +523,19 @@ def import_progress(count, name): db.update_media_sync_info(media_id, result.md5) # Sync AppStream metadata - appstream_synced = False if not skip_appstream: if progress_callback: progress_callback("syncing appstream", 0, 0) try: from .appstream import AppStreamManager appstream_mgr = AppStreamManager(db, base_dir) + # TODO: appstream_result isn't used appstream_result = appstream_mgr.sync_media_appstream( media_id=media_id, media_name=media_name, media_url=media_url, progress_callback=lambda msg: progress_callback("appstream", 0, 0) if progress_callback else None ) - appstream_synced = appstream_result.success except Exception as e: # AppStream sync failure is not fatal import logging @@ -761,7 +756,7 @@ def sync_files_xml( if e.code == 404: continue # Try next server return FilesXmlResult(success=False, error=f"HTTP error: {e.code}") - except Exception as e: + except Exception: continue # Try next server if not files_xml_downloaded: @@ -967,9 +962,7 @@ def sync_all_files_xml( List of (media_name, FilesXmlResult) tuples """ from concurrent.futures import ThreadPoolExecutor, as_completed - from queue import PriorityQueue from .files_xml import parse_files_xml - import threading # Get all enabled media all_media = [m for m in db.list_media() if m.get('enabled', True)] diff --git a/urpm/core/synthesis.py b/urpm/core/synthesis.py index 79075a2..5dd2d9e 100644 --- a/urpm/core/synthesis.py +++ b/urpm/core/synthesis.py @@ -8,7 +8,7 @@ import re from pathlib import Path -from typing import Dict, Iterator, List, Any, Optional, Tuple +from typing import Dict, Iterator, List, Any, Tuple from .compression import decompress diff --git a/urpm/core/transaction_queue.py b/urpm/core/transaction_queue.py index de34e41..37771c8 100644 --- a/urpm/core/transaction_queue.py +++ b/urpm/core/transaction_queue.py @@ -439,7 +439,6 @@ def _execute_with_userns( def _child_process_standalone(self): """Child process logic for userns mode - writes to stdout.""" import sys - import rpm write_file = sys.stdout @@ -478,7 +477,7 @@ def _child_process_standalone(self): if op.op_type == OperationType.INSTALL: if DEBUG_USERNS: - print(f"[userns child] executing install...", file=sys.stderr) + print("[userns child] executing install...", file=sys.stderr) sys.stderr.flush() success, count, errors = self._execute_install(op, pipe_state, release_parent_after=False) if DEBUG_USERNS: @@ -617,7 +616,6 @@ def _parent_process( def _child_process(self, read_fd: int, write_fd: int): """Child: execute operations sequentially.""" - import rpm os.close(read_fd) write_file = os.fdopen(write_fd, 'w', buffering=1) # Line buffered @@ -796,7 +794,7 @@ def _execute_install( # Check dependencies if not op.force: if DEBUG_EXECINSTALL: - print(f"[_execute_install] checking dependencies...", file=sys.stderr) + print("[_execute_install] checking dependencies...", file=sys.stderr) sys.stderr.flush() unresolved = ts.check() if unresolved: @@ -805,13 +803,13 @@ def _execute_install( errors = [f"Dependency: {prob}" for prob in unresolved] return False, 0, errors if DEBUG_EXECINSTALL: - print(f"[_execute_install] dependencies OK", file=sys.stderr) + print("[_execute_install] dependencies OK", file=sys.stderr) sys.stderr.flush() # Order transaction ts.order() if DEBUG_EXECINSTALL: - print(f"[_execute_install] transaction ordered", file=sys.stderr) + print("[_execute_install] transaction ordered", file=sys.stderr) sys.stderr.flush() if op.test: diff --git a/urpm/daemon/__init__.py b/urpm/daemon/__init__.py index b5d82be..a3513e0 100644 --- a/urpm/daemon/__init__.py +++ b/urpm/daemon/__init__.py @@ -1,3 +1,3 @@ """urpmd - urpm daemon for intelligent cache management.""" -from .. import __version__ +from .. import __version__ # noqa: F401 diff --git a/urpm/daemon/daemon.py b/urpm/daemon/daemon.py index df796b8..e838abb 100644 --- a/urpm/daemon/daemon.py +++ b/urpm/daemon/daemon.py @@ -6,7 +6,6 @@ import signal import sys import threading -import time from datetime import datetime from pathlib import Path from typing import Optional, List, Dict, Any @@ -14,11 +13,11 @@ # Imports are relative to package - bin/urpmd handles sys.path from ..core.database import PackageDatabase from ..core.config import ( - PROD_BASE_DIR, PROD_DB_PATH, PROD_PID_FILE, PROD_PORT, - DEV_BASE_DIR, DEV_DB_PATH, DEV_PID_FILE, DEV_PORT, + PROD_PID_FILE, PROD_PORT, + DEV_PID_FILE, DEV_PORT, is_dev_mode, get_db_path, get_base_dir, ) -from .server import UrpmdServer, DEFAULT_PORT, DEFAULT_HOST +from .server import UrpmdServer, DEFAULT_HOST from .scheduler import Scheduler from .discovery import PeerDiscovery @@ -563,12 +562,12 @@ def main(): parser.add_argument( '--dev', action='store_true', - help=f'Force development mode (auto-detected from .urpm.local or dev tree)' + help='Force development mode (auto-detected from .urpm.local or dev tree)' ) parser.add_argument( '--prod', action='store_true', - help=f'Force production mode (ignore .urpm.local)' + help='Force production mode (ignore .urpm.local)' ) args = parser.parse_args() diff --git a/urpm/daemon/scheduler.py b/urpm/daemon/scheduler.py index c4503ed..84ea313 100644 --- a/urpm/daemon/scheduler.py +++ b/urpm/daemon/scheduler.py @@ -4,9 +4,9 @@ import random import threading import time -from datetime import datetime, timedelta +from datetime import datetime from pathlib import Path -from typing import Optional, Dict, TYPE_CHECKING +from typing import Optional, TYPE_CHECKING from urllib.request import Request, urlopen from urllib.error import URLError, HTTPError @@ -623,7 +623,6 @@ def _run_replication(self): logger.info(f"Seed set: {len(seed_names)} package names") - from ..core.download import Downloader, DownloadItem for media in media_to_replicate: try: @@ -644,7 +643,6 @@ def _compute_seed_set(self, media_list: list) -> set: Set of package names in the seed set """ import json - from pathlib import Path from ..core.rpmsrate import RpmsrateParser, DEFAULT_RPMSRATE_PATH # Default sections (same as DVD content) diff --git a/urpm/daemon/server.py b/urpm/daemon/server.py index 10c85f3..d063a1d 100644 --- a/urpm/daemon/server.py +++ b/urpm/daemon/server.py @@ -3,8 +3,6 @@ import json import logging import mimetypes -import os -import sys import threading from http.server import HTTPServer, BaseHTTPRequestHandler, ThreadingHTTPServer from pathlib import Path diff --git a/urpm/dbus/service.py b/urpm/dbus/service.py index 505e04a..f9962f3 100644 --- a/urpm/dbus/service.py +++ b/urpm/dbus/service.py @@ -17,14 +17,11 @@ import json import logging -import os import platform import signal import sys import threading import uuid -from pathlib import Path -from typing import Optional logger = logging.getLogger(__name__) @@ -382,7 +379,7 @@ def _run_install(self, op_id, context, package_names, invocation): actions = result.actions if not actions: - logger.info(f"_run_install: No actions - packages may already be installed") + logger.info("_run_install: No actions - packages may already be installed") self._emit_complete(op_id, True, "Nothing to do") self._return_invocation(invocation, True, "Nothing to do") return @@ -465,10 +462,10 @@ def install_progress(op, name, current, total): }) msg = json.dumps({'message': f"Installed {len(rpm_paths)} package(s)", 'packages': installed_pkgs}) - logger.info(f"_run_install: emitting complete, success=True") + logger.info("_run_install: emitting complete, success=True") self._emit_complete(op_id, True, msg) self._return_invocation(invocation, True, msg) - logger.info(f"_run_install: done") + logger.info("_run_install: done") except Exception as e: logger.exception(f"Install failed: {e}") diff --git a/urpm/tests/test_download.py b/urpm/tests/test_download.py index 7a5dd98..d1b04a9 100644 --- a/urpm/tests/test_download.py +++ b/urpm/tests/test_download.py @@ -1,8 +1,6 @@ import time -from urpm.cli.display import DownloadProgressDisplay, format_size -from urpm.core.download import DownloadProgress, Downloader, DownloadItem, DownloadResult -import pytest -from pathlib import Path +from urpm.cli.display import DownloadProgressDisplay +from urpm.core.download import DownloadProgress def test_download_progress_samples_and_speed(): # Test 1: Create DownloadProgress instance diff --git a/urpm/tests/test_rpmsrate.py b/urpm/tests/test_rpmsrate.py index f29021e..87fcfcf 100644 --- a/urpm/tests/test_rpmsrate.py +++ b/urpm/tests/test_rpmsrate.py @@ -2,7 +2,7 @@ import pytest from pathlib import Path -from urpm.core.rpmsrate import RpmsrateParser, PackageEntry, Section +from urpm.core.rpmsrate import RpmsrateParser # Sample rpmsrate content for testing diff --git a/urpm/tests/test_suggests.py b/urpm/tests/test_suggests.py index 68e4502..3a7714b 100644 --- a/urpm/tests/test_suggests.py +++ b/urpm/tests/test_suggests.py @@ -9,13 +9,11 @@ 6. Cycle detection (A->B->C->A) """ -import pytest -from unittest.mock import Mock, MagicMock, patch -from typing import List, Dict, Set +from typing import List, Dict import solv -from urpm.core.resolver import Resolver, Alternative, PackageAction +from urpm.core.resolver import Resolver class MockSolvable: diff --git a/urpm/tests/test_synthesis.py b/urpm/tests/test_synthesis.py index 5b812e8..24702e7 100644 --- a/urpm/tests/test_synthesis.py +++ b/urpm/tests/test_synthesis.py @@ -1,6 +1,5 @@ """Tests for synthesis parser""" -import pytest from urpm.core.synthesis import parse_nevra, parse_dependency