11"""Helper functions for private use."""
22
33import json
4+ from dataclasses import dataclass
45from enum import Enum
56from itertools import repeat
67from pathlib import Path
78from typing import Any
9+ from urllib import parse
810
911from cyclopts .annotations import get_hint_name
1012from cyclopts .help import HelpEntry
@@ -18,18 +20,54 @@ class BuildStyle(Enum):
1820 quarto_resource_tables = "quarto_resource_tables"
1921
2022
21- # Output maybe str? Path?
22- # Use `match` inside for strictness on URI types? Or use a library for URI parsing?
23- # TODO Extend to parse strings and return either URL or Path
24- def _resolve_uri (uri : str ) -> Path :
25- return Path (uri )
23+ @dataclass (frozen = True )
24+ class Uri :
25+ """A parsed URI with its normalised value and locality flag."""
2626
27+ value : str
28+ local : bool
2729
28- # TODO Extend to also read properties from URLs
29- def _read_properties (path : Path ) -> dict [str , Any ]:
30- with open (path ) as properties_file :
31- datapackage : dict [str , Any ] = json .load (properties_file )
32- return datapackage
30+
31+ def _parse_uri (uri : str ) -> Uri :
32+ split_uri = parse .urlsplit (uri )
33+ if split_uri .scheme == "" :
34+ split_uri = split_uri ._replace (scheme = "file" )
35+ match split_uri .scheme :
36+ case "file" :
37+ return _convert_to_file_uri (split_uri )
38+ case "https" :
39+ return _convert_to_https_uri (split_uri )
40+ case "gh" | "github" :
41+ return _convert_to_github_uri (split_uri )
42+ case _:
43+ raise ValueError (
44+ "The uri must be either a path to an existing file/folder "
45+ "or a URI with one of the following URI prefixes: "
46+ "`file:`, `https:`, `gh:`, `github:`"
47+ )
48+
49+
50+ def _convert_to_file_uri (split_file_uri : parse .SplitResult ) -> Uri :
51+ path = Path (split_file_uri .path ).resolve ()
52+ if path .is_dir ():
53+ path /= "datapackage.json"
54+ split_file_uri = split_file_uri ._replace (path = path .as_posix ())
55+ return Uri (value = split_file_uri .geturl (), local = True )
56+
57+
58+ def _convert_to_https_uri (split_https_uri : parse .SplitResult ) -> Uri :
59+ return Uri (value = split_https_uri .geturl (), local = False )
60+
61+
62+ def _convert_to_github_uri (split_gh_uri : parse .SplitResult ) -> Uri :
63+ return Uri (
64+ value = split_gh_uri ._replace (
65+ scheme = "https" ,
66+ netloc = "raw.githubusercontent.com" ,
67+ path = f"/{ split_gh_uri .path } /refs/heads/main/datapackage.json" ,
68+ ).geturl (),
69+ local = False ,
70+ )
3371
3472
3573def _format_param_help (entry : HelpEntry ) -> str :
@@ -51,3 +89,13 @@ def _add_highlight_syntax(name: str, entry_type: type | None) -> str:
5189 if get_hint_name (entry_type ) == "bool" :
5290 formatted_name = ""
5391 return formatted_name
92+
93+
94+ def _read_properties (uri : Uri ) -> dict [str , Any ]:
95+ if uri .local :
96+ path = Path (parse .urlsplit (uri .value ).path )
97+ with open (path ) as properties_file :
98+ return json .load (properties_file ) # type: ignore # TODO fix in read_prop PR
99+ else :
100+ # TODO read from remote file
101+ return {"placeholder" : uri .value }
0 commit comments