From cb984f6d4399ba0fcbfd306db7a73df39541270f Mon Sep 17 00:00:00 2001 From: Qubasa Date: Tue, 5 Dec 2023 18:16:51 +0100 Subject: [PATCH] clan_cli: Remodeled ClanURI parser --- pkgs/clan-cli/clan_cli/clan_uri.py | 65 +++++++++++++++------------- pkgs/clan-cli/tests/test_clan_uri.py | 23 ++++++---- 2 files changed, 51 insertions(+), 37 deletions(-) diff --git a/pkgs/clan-cli/clan_cli/clan_uri.py b/pkgs/clan-cli/clan_cli/clan_uri.py index 15b515f2..f0a8121f 100644 --- a/pkgs/clan-cli/clan_cli/clan_uri.py +++ b/pkgs/clan-cli/clan_cli/clan_uri.py @@ -1,44 +1,50 @@ # Import the urllib.parse, enum and dataclasses modules -import urllib.parse -from enum import Enum, member -from dataclasses import dataclass import dataclasses - +import urllib.parse +from dataclasses import dataclass +from enum import Enum, member from pathlib import Path +from typing import Dict + from .errors import ClanError -from typing import List + # Define an enum with different members that have different values class ClanScheme(Enum): # Use the dataclass decorator to add fields and methods to the members @member @dataclass - class HTTP(): - url: str # The url field holds the HTTP URL - def __str__(self): - return f"HTTP({self.url})" # The __str__ method returns a custom string representation - @member - @dataclass - class HTTPS(): - url: str # The url field holds the HTTPS URL - def __str__(self): - return f"HTTPS({self.url})" # The __str__ method returns a custom string representation + class HTTP: + url: str # The url field holds the HTTP URL + + def __str__(self) -> str: + return f"HTTP({self.url})" # The __str__ method returns a custom string representation @member @dataclass - class FILE(): - path: Path # The path field holds the local path - def __str__(self): - return f"FILE({self.path})" # The __str__ method returns a custom string representation + class HTTPS: + url: str # The url field holds the HTTPS URL + + def __str__(self) -> str: + return f"HTTPS({self.url})" # The __str__ method returns a custom string representation + + @member + @dataclass + class FILE: + path: Path # The path field holds the local path + + def __str__(self) -> str: + return f"FILE({self.path})" # The __str__ method returns a custom string representation # Parameters defined here will be DELETED from the nested uri # so make sure there are no conflicts with other webservices @dataclass -class ClanParameters(): +class ClanParameters: flake_attr: str | None machine: str | None + # Define the ClanURI class class ClanURI: # Initialize the class with a clan:// URI @@ -56,7 +62,7 @@ class ClanURI: # Parse the query string into a dictionary self._query = urllib.parse.parse_qs(self._components.query) - params = {} + params: Dict[str, str | None] = {} for field in dataclasses.fields(ClanParameters): if field.name in self._query: # Check if the field type is a list @@ -66,7 +72,9 @@ class ClanURI: else: values = self._query[field.name] if len(values) > 1: - raise ClanError("Multiple values for parameter: {}".format(field.name)) + raise ClanError( + "Multiple values for parameter: {}".format(field.name) + ) setattr(params, field.name, values[0]) # Remove the field from the query dictionary @@ -81,13 +89,12 @@ class ClanURI: # Use the match statement to check the scheme and create a ClanScheme member with the value match self._components.scheme: case "http": - self.scheme = ClanScheme.HTTP.value(self._components.geturl()) + self.scheme = ClanScheme.HTTP.value(self._components.geturl()) # type: ignore case "https": - self.scheme = ClanScheme.HTTPS.value(self._components.geturl()) + self.scheme = ClanScheme.HTTPS.value(self._components.geturl()) # type: ignore case "file": - self.scheme = ClanScheme.FILE.value(Path(self._components.path)) + self.scheme = ClanScheme.FILE.value(Path(self._components.path)) # type: ignore case _: - raise ClanError("Unsupported scheme: {}".format(self._components.scheme)) - - - + raise ClanError( + "Unsupported scheme: {}".format(self._components.scheme) + ) diff --git a/pkgs/clan-cli/tests/test_clan_uri.py b/pkgs/clan-cli/tests/test_clan_uri.py index b2677264..3a4aac59 100644 --- a/pkgs/clan-cli/tests/test_clan_uri.py +++ b/pkgs/clan-cli/tests/test_clan_uri.py @@ -1,18 +1,21 @@ +from pathlib import Path + import pytest -from clan_cli.clan_uri import ClanURI, ClanScheme +from clan_cli.clan_uri import ClanScheme, ClanURI from clan_cli.errors import ClanError -from pathlib import Path + def test_local_uri() -> None: # Create a ClanURI object from a local URI uri = ClanURI("clan://file:///home/user/Downloads") match uri.scheme: case ClanScheme.FILE.value(path): - assert path == Path("/home/user/Downloads") # type: ignore + assert path == Path("/home/user/Downloads") # type: ignore case _: assert False + def test_unsupported_schema() -> None: with pytest.raises(ClanError, match="Unsupported scheme: ftp"): # Create a ClanURI object from an unsupported URI @@ -25,10 +28,11 @@ def test_is_remote() -> None: match uri.scheme: case ClanScheme.HTTPS.value(url): - assert url == "https://example.com" # type: ignore + assert url == "https://example.com" # type: ignore case _: assert False + def remote_with_clanparams() -> None: # Create a ClanURI object from a remote URI with parameters uri = ClanURI("clan://https://example.com?flake_attr=defaultVM") @@ -37,19 +41,22 @@ def remote_with_clanparams() -> None: match uri.scheme: case ClanScheme.HTTPS.value(url): - assert url == "https://example.com" # type: ignore + assert url == "https://example.com" # type: ignore case _: assert False + def remote_with_all_params() -> None: # Create a ClanURI object from a remote URI with parameters - uri = ClanURI("clan://https://example.com?flake_attr=defaultVM&machine=vm1&password=1234") + uri = ClanURI( + "clan://https://example.com?flake_attr=defaultVM&machine=vm1&password=1234" + ) assert uri.params.flake_attr == "defaultVM" assert uri.params.machine == "vm1" match uri.scheme: case ClanScheme.HTTPS.value(url): - assert url == "https://example.com&password=1234" # type: ignore + assert url == "https://example.com&password=1234" # type: ignore case _: - assert False \ No newline at end of file + assert False