From 5dbf954f40e45747ff21cabd87a96e39dcd7312b Mon Sep 17 00:00:00 2001 From: ScarletEmanu Date: Wed, 17 Jun 2026 11:15:57 +0200 Subject: [PATCH 1/4] change behaviour to load plugin --- archinstall/lib/args.py | 32 +++++++++++++++++++++++++++++--- archinstall/lib/plugins.py | 35 ++++------------------------------- 2 files changed, 33 insertions(+), 34 deletions(-) diff --git a/archinstall/lib/args.py b/archinstall/lib/args.py index e3729504dd..bb71ad5ce2 100644 --- a/archinstall/lib/args.py +++ b/archinstall/lib/args.py @@ -2,6 +2,7 @@ import json import os import sys +import tempfile import urllib.error import urllib.parse from argparse import ArgumentParser, Namespace @@ -56,7 +57,8 @@ class Arguments: debug: bool = False offline: bool = False no_pkg_lookups: bool = False - plugin: str | None = None + plugin: Path | None = None + plugin_url: str | None = None skip_version_check: bool = False skip_wifi_check: bool = False advanced: bool = False @@ -517,10 +519,17 @@ def _define_arguments(self) -> ArgumentParser: parser.add_argument( '--plugin', nargs='?', - type=str, + type=Path, default=None, help='File path to a plugin to load', ) + parser.add_argument( + '--plugin-url', + type=str, + nargs='?', + default=None, + help='Url to a plugin file to load', + ) parser.add_argument( '--skip-version-check', action='store_true', @@ -560,7 +569,11 @@ def _parse_args(self) -> Arguments: warn(f'Warning: --debug mode will write certain credentials to {logger.path}!') if args.plugin: - plugin_path = Path(args.plugin) + load_plugin(args.plugin) + + if args.plugin_url: + plugin_data = self._fetch_from_url(args.plugin_url) + plugin_path = self._write_plugin_to_temp_file(plugin_data) load_plugin(plugin_path) if args.creds_decryption_key is None: @@ -652,6 +665,19 @@ def _fetch_from_url(self, url: str) -> str: sys.exit(1) + def _write_plugin_to_temp_file(self, plugin_data: str) -> Path: + tmp_file = tempfile.NamedTemporaryFile( + mode='w', + suffix='.py', + prefix='archinstall_plugin_', + delete=False, + ) + + with tmp_file as f: + f.write(plugin_data) + + return Path(tmp_file.name) + def _read_file(self, path: Path) -> str: if not path.exists(): error(f'Could not find file {path}') diff --git a/archinstall/lib/plugins.py b/archinstall/lib/plugins.py index ac8383b117..6019f114a0 100644 --- a/archinstall/lib/plugins.py +++ b/archinstall/lib/plugins.py @@ -1,9 +1,6 @@ -import hashlib import importlib.util import os import sys -import urllib.parse -import urllib.request from importlib import metadata from pathlib import Path @@ -34,23 +31,6 @@ def plugin(f, *args, **kwargs) -> None: # type: ignore[no-untyped-def] plugins[f.__name__] = f -def _localize_path(path: Path) -> Path: - """ - Support structures for load_plugin() - """ - url = urllib.parse.urlparse(str(path)) - - if url.scheme and url.scheme in ('https', 'http'): - converted_path = Path(f'/tmp/{path.stem}_{hashlib.md5(os.urandom(12)).hexdigest()}.py') - - with open(converted_path, 'w') as temp_file: - temp_file.write(urllib.request.urlopen(url.geturl()).read().decode('utf-8')) - - return converted_path - else: - return path - - def _import_via_path(path: Path, namespace: str | None = None) -> str: if not namespace: namespace = os.path.basename(path) @@ -82,17 +62,10 @@ def _import_via_path(path: Path, namespace: str | None = None) -> str: def load_plugin(path: Path) -> None: namespace: str | None = None - parsed_url = urllib.parse.urlparse(str(path)) - info(f'Loading plugin from url {parsed_url}') - - # The Profile was not a direct match on a remote URL - if not parsed_url.scheme: - # Path was not found in any known examples, check if it's an absolute path - if os.path.isfile(path): - namespace = _import_via_path(path) - elif parsed_url.scheme in ('https', 'http'): - localized = _localize_path(path) - namespace = _import_via_path(localized) + info(f'Loading plugin from {path}') + + if os.path.isfile(path): + namespace = _import_via_path(path) if namespace and namespace in sys.modules: # Version dependency via __archinstall__version__ variable (if present) in the plugin From 24c170f4ef76d121b72648e6bab00182415c214b Mon Sep 17 00:00:00 2001 From: ScarletEmanu Date: Wed, 17 Jun 2026 13:01:00 +0200 Subject: [PATCH 2/4] add checks in _write_plugin_to_temp_file --- archinstall/lib/args.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/archinstall/lib/args.py b/archinstall/lib/args.py index bb71ad5ce2..cfcfd4780a 100644 --- a/archinstall/lib/args.py +++ b/archinstall/lib/args.py @@ -666,6 +666,10 @@ def _fetch_from_url(self, url: str) -> str: sys.exit(1) def _write_plugin_to_temp_file(self, plugin_data: str) -> Path: + if not plugin_data.strip(): + error('The downloaded plugin is empty') + sys.exit(1) + tmp_file = tempfile.NamedTemporaryFile( mode='w', suffix='.py', @@ -673,8 +677,12 @@ def _write_plugin_to_temp_file(self, plugin_data: str) -> Path: delete=False, ) - with tmp_file as f: - f.write(plugin_data) + try: + with tmp_file as f: + f.write(plugin_data) + except OSError as err: + error(f'Could not write the downloaded plugin to a temporary file: {err}') + sys.exit(1) return Path(tmp_file.name) From 9c4d82250f8259c31ceb731ac1133fd8a74f3db5 Mon Sep 17 00:00:00 2001 From: ScarletEmanu Date: Wed, 17 Jun 2026 13:01:20 +0200 Subject: [PATCH 3/4] modify test --- tests/test_args.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/test_args.py b/tests/test_args.py index 4cbad41bae..65f01a5bb6 100644 --- a/tests/test_args.py +++ b/tests/test_args.py @@ -50,6 +50,7 @@ def test_default_args(monkeypatch: MonkeyPatch) -> None: offline=False, no_pkg_lookups=False, plugin=None, + plugin_url=None, skip_version_check=False, advanced=False, ) @@ -82,6 +83,8 @@ def test_correct_parsing_args( '--no-pkg-lookups', '--plugin', 'pytest_plugin.py', + '--plugin-url', + 'https://example.com/plugin.py', '--skip-version-check', '--advanced', '--dry-run', @@ -106,7 +109,8 @@ def test_correct_parsing_args( debug=True, offline=True, no_pkg_lookups=True, - plugin='pytest_plugin.py', + plugin=Path('pytest_plugin.py'), + plugin_url='https://example.com/plugin.py', skip_version_check=True, advanced=True, ) From 1fccdfd9b1c5ff35cca9680071301cdc799c5080 Mon Sep 17 00:00:00 2001 From: ScarletEmanu Date: Wed, 17 Jun 2026 13:10:30 +0200 Subject: [PATCH 4/4] fixed test --- tests/test_args.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/test_args.py b/tests/test_args.py index 65f01a5bb6..324f5a1173 100644 --- a/tests/test_args.py +++ b/tests/test_args.py @@ -83,8 +83,6 @@ def test_correct_parsing_args( '--no-pkg-lookups', '--plugin', 'pytest_plugin.py', - '--plugin-url', - 'https://example.com/plugin.py', '--skip-version-check', '--advanced', '--dry-run', @@ -110,7 +108,7 @@ def test_correct_parsing_args( offline=True, no_pkg_lookups=True, plugin=Path('pytest_plugin.py'), - plugin_url='https://example.com/plugin.py', + plugin_url=None, skip_version_check=True, advanced=True, )