clan_cli: Remodeled ClanURI parser
This commit is contained in:
@@ -1,44 +1,50 @@
|
|||||||
# Import the urllib.parse, enum and dataclasses modules
|
# Import the urllib.parse, enum and dataclasses modules
|
||||||
import urllib.parse
|
|
||||||
from enum import Enum, member
|
|
||||||
from dataclasses import dataclass
|
|
||||||
import dataclasses
|
import dataclasses
|
||||||
|
import urllib.parse
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from enum import Enum, member
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from typing import Dict
|
||||||
|
|
||||||
from .errors import ClanError
|
from .errors import ClanError
|
||||||
from typing import List
|
|
||||||
|
|
||||||
# Define an enum with different members that have different values
|
# Define an enum with different members that have different values
|
||||||
class ClanScheme(Enum):
|
class ClanScheme(Enum):
|
||||||
# Use the dataclass decorator to add fields and methods to the members
|
# Use the dataclass decorator to add fields and methods to the members
|
||||||
@member
|
@member
|
||||||
@dataclass
|
@dataclass
|
||||||
class HTTP():
|
class HTTP:
|
||||||
url: str # The url field holds the HTTP URL
|
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
|
def __str__(self) -> str:
|
||||||
@member
|
return f"HTTP({self.url})" # The __str__ method returns a custom string representation
|
||||||
@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
|
|
||||||
|
|
||||||
@member
|
@member
|
||||||
@dataclass
|
@dataclass
|
||||||
class FILE():
|
class HTTPS:
|
||||||
path: Path # The path field holds the local path
|
url: str # The url field holds the HTTPS URL
|
||||||
def __str__(self):
|
|
||||||
return f"FILE({self.path})" # The __str__ method returns a custom string representation
|
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
|
# Parameters defined here will be DELETED from the nested uri
|
||||||
# so make sure there are no conflicts with other webservices
|
# so make sure there are no conflicts with other webservices
|
||||||
@dataclass
|
@dataclass
|
||||||
class ClanParameters():
|
class ClanParameters:
|
||||||
flake_attr: str | None
|
flake_attr: str | None
|
||||||
machine: str | None
|
machine: str | None
|
||||||
|
|
||||||
|
|
||||||
# Define the ClanURI class
|
# Define the ClanURI class
|
||||||
class ClanURI:
|
class ClanURI:
|
||||||
# Initialize the class with a clan:// URI
|
# Initialize the class with a clan:// URI
|
||||||
@@ -56,7 +62,7 @@ class ClanURI:
|
|||||||
# Parse the query string into a dictionary
|
# Parse the query string into a dictionary
|
||||||
self._query = urllib.parse.parse_qs(self._components.query)
|
self._query = urllib.parse.parse_qs(self._components.query)
|
||||||
|
|
||||||
params = {}
|
params: Dict[str, str | None] = {}
|
||||||
for field in dataclasses.fields(ClanParameters):
|
for field in dataclasses.fields(ClanParameters):
|
||||||
if field.name in self._query:
|
if field.name in self._query:
|
||||||
# Check if the field type is a list
|
# Check if the field type is a list
|
||||||
@@ -66,7 +72,9 @@ class ClanURI:
|
|||||||
else:
|
else:
|
||||||
values = self._query[field.name]
|
values = self._query[field.name]
|
||||||
if len(values) > 1:
|
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])
|
setattr(params, field.name, values[0])
|
||||||
|
|
||||||
# Remove the field from the query dictionary
|
# 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
|
# Use the match statement to check the scheme and create a ClanScheme member with the value
|
||||||
match self._components.scheme:
|
match self._components.scheme:
|
||||||
case "http":
|
case "http":
|
||||||
self.scheme = ClanScheme.HTTP.value(self._components.geturl())
|
self.scheme = ClanScheme.HTTP.value(self._components.geturl()) # type: ignore
|
||||||
case "https":
|
case "https":
|
||||||
self.scheme = ClanScheme.HTTPS.value(self._components.geturl())
|
self.scheme = ClanScheme.HTTPS.value(self._components.geturl()) # type: ignore
|
||||||
case "file":
|
case "file":
|
||||||
self.scheme = ClanScheme.FILE.value(Path(self._components.path))
|
self.scheme = ClanScheme.FILE.value(Path(self._components.path)) # type: ignore
|
||||||
case _:
|
case _:
|
||||||
raise ClanError("Unsupported scheme: {}".format(self._components.scheme))
|
raise ClanError(
|
||||||
|
"Unsupported scheme: {}".format(self._components.scheme)
|
||||||
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,21 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
|
||||||
import pytest
|
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 clan_cli.errors import ClanError
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
def test_local_uri() -> None:
|
def test_local_uri() -> None:
|
||||||
# Create a ClanURI object from a local URI
|
# Create a ClanURI object from a local URI
|
||||||
uri = ClanURI("clan://file:///home/user/Downloads")
|
uri = ClanURI("clan://file:///home/user/Downloads")
|
||||||
match uri.scheme:
|
match uri.scheme:
|
||||||
case ClanScheme.FILE.value(path):
|
case ClanScheme.FILE.value(path):
|
||||||
assert path == Path("/home/user/Downloads") # type: ignore
|
assert path == Path("/home/user/Downloads") # type: ignore
|
||||||
case _:
|
case _:
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
|
|
||||||
def test_unsupported_schema() -> None:
|
def test_unsupported_schema() -> None:
|
||||||
with pytest.raises(ClanError, match="Unsupported scheme: ftp"):
|
with pytest.raises(ClanError, match="Unsupported scheme: ftp"):
|
||||||
# Create a ClanURI object from an unsupported URI
|
# Create a ClanURI object from an unsupported URI
|
||||||
@@ -25,10 +28,11 @@ def test_is_remote() -> None:
|
|||||||
|
|
||||||
match uri.scheme:
|
match uri.scheme:
|
||||||
case ClanScheme.HTTPS.value(url):
|
case ClanScheme.HTTPS.value(url):
|
||||||
assert url == "https://example.com" # type: ignore
|
assert url == "https://example.com" # type: ignore
|
||||||
case _:
|
case _:
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
|
|
||||||
def remote_with_clanparams() -> None:
|
def remote_with_clanparams() -> None:
|
||||||
# Create a ClanURI object from a remote URI with parameters
|
# Create a ClanURI object from a remote URI with parameters
|
||||||
uri = ClanURI("clan://https://example.com?flake_attr=defaultVM")
|
uri = ClanURI("clan://https://example.com?flake_attr=defaultVM")
|
||||||
@@ -37,19 +41,22 @@ def remote_with_clanparams() -> None:
|
|||||||
|
|
||||||
match uri.scheme:
|
match uri.scheme:
|
||||||
case ClanScheme.HTTPS.value(url):
|
case ClanScheme.HTTPS.value(url):
|
||||||
assert url == "https://example.com" # type: ignore
|
assert url == "https://example.com" # type: ignore
|
||||||
case _:
|
case _:
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
|
|
||||||
def remote_with_all_params() -> None:
|
def remote_with_all_params() -> None:
|
||||||
# Create a ClanURI object from a remote URI with parameters
|
# 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.flake_attr == "defaultVM"
|
||||||
assert uri.params.machine == "vm1"
|
assert uri.params.machine == "vm1"
|
||||||
|
|
||||||
match uri.scheme:
|
match uri.scheme:
|
||||||
case ClanScheme.HTTPS.value(url):
|
case ClanScheme.HTTPS.value(url):
|
||||||
assert url == "https://example.com&password=1234" # type: ignore
|
assert url == "https://example.com&password=1234" # type: ignore
|
||||||
case _:
|
case _:
|
||||||
assert False
|
assert False
|
||||||
|
|||||||
Reference in New Issue
Block a user