10000 vcs-registry · vcs-python/libvcs@7e236f8 · GitHub
[go: up one dir, main page]

Skip to content

Commit 7e236f8

Browse files
committed
vcs-registry
1 parent 1921043 commit 7e236f8

File tree

2 files changed

+137
-0
lines changed

2 files changed

+137
-0
lines changed

src/libvcs/url/parse.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import typing as t
2+
3+
from libvcs._internal.module_loading import import_string
4+
5+
from .base import URLProtocol
6+
7+
if t.TYPE_CHECKING:
8+
from typing_extensions import TypeAlias
9+
10+
ParserLazyMap: TypeAlias = t.Dict[str, t.Union[t.Type[URLProtocol], str]]
11+
ParserMap: TypeAlias = t.Dict[str, t.Type[URLProtocol]]
12+
13+
DEFAULT_PARSERS: "ParserLazyMap" = {
14+
"git": "libvcs.url.git.GitURL",
15+
"hg": "libvcs.url.hg.HgURL",
16+
"svn": "libvcs.url.svn.SvnURL",
17+
}
18+
19+
20+
class ParserMatch(t.NamedTuple):
21+
vcs: str
22+
match: URLProtocol
23+
24+
25+
class VCSRegistry:
26+
"""Index of parsers"""
27+
28+
parser_map: t.ClassVar["ParserMap"] = {}
29+
30+
def __init__(self, parsers: "ParserLazyMap"):
31+
for k, v in parsers.items():
32+
if isinstance(v, str):
33+
v = import_string(v)
34+
assert callable(v)
35+
self.parser_map[k] = v
36+
37+
def match(self, url: str, is_explicit: bool = False) -> t.List["ParserMatch"]:
38+
matches: t.List[ParserMatch] = []
39+
for vcs, parser in self.parser_map.items():
40+
if parser.is_valid(url=url, is_explicit=is_explicit):
41+
matches.append(ParserMatch(vcs=vcs, match=parser(url)))
42+
return matches
43+
44+
45+
detect_vcs = VCSRegistry(parsers=DEFAULT_PARSERS)

tests/url/test_parse.py

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import typing as t
2+
3+
import pytest
4+
5+
from libvcs.url import parse
6+
from libvcs.url.git import GitURL
7+
from libvcs.url.hg import HgURL
8+
from libvcs.url.svn import SvnURL
9+
10+
if t.TYPE_CHECKING:
11+
from typing_extensions import TypeAlias
12+
13+
ParserMatchLazy: TypeAlias = t.Callable[[str], parse.ParserMatch]
14+
DetectVCSFixtureExpectedMatch: TypeAlias = t.Union[
15+
parse.ParserMatch, ParserMatchLazy
16+
]
17+
18+
19+
class DetectVCSFixture(t.NamedTuple):
20+
url: str
21+
expected_matches_lazy: t.List["DetectVCSFixtureExpectedMatch"]
22+
is_explicit: bool
23+
24+
25+
TEST_FIXTURES: list[DetectVCSFixture] = [
26+
*[
27+
DetectVCSFixture(
28+
url=url,
29+
expected_matches_lazy=[
30+
lambda url: parse.ParserMatch(vcs="git", match=GitURL(url))
31+
],
32+
is_explicit=True,
33+
)
34+
for url in [
35+
"git+https://github.com/vcs-python/libvcs",
36+
"git+https://github.com/vcs-python/libvcs.git",
37+
"git+https://github.com:vcs-python/libvcs.git",
38+
"git+ssh://git@github.com:vcs-python/libvcs.git",
39+
"git+ssh://git@github.com:vcs-python/libvcs",
40+
]
41+
],
42+
*[
43+
DetectVCSFixture(
44+
url=url,
45+
expected_matches_lazy=[
46+
lambda url: parse.ParserMatch(vcs="hg", match=HgURL(url))
47+
],
48+
is_explicit=True,
49+
)
50+
for url in [
51+
"hg+http://hg.example.com/MyProject@da39a3ee5e6b",
52+
"hg+ssh://hg.example.com:MyProject@da39a3ee5e6b",
53+
]
54+
],
55+
*[
56+
DetectVCSFixture(
57+
url=url,
58+
expected_matches_lazy=[
59+
lambda url: parse.ParserMatch(vcs="svn", match=SvnURL(url))
60+
],
61+
is_explicit=True,
62+
)
63+
for url in [
64+
"svn+http://svn.example.com/MyProject@da39a3ee5e6b",
65+
"svn+ssh://svn.example.com:MyProject@da39a3ee5e6b",
66+
]
67+
],
68+
]
69+
70+
71+
@pytest.mark.parametrize(
72+
list(DetectVCSFixture._fields),
73+
TEST_FIXTURES,
74+
)
75+
def test_registry(
76+
url: str,
77+
expected_matches_lazy: t.List["DetectVCSFixtureExpectedMatch"],
78+
is_explicit: bool,
79+
) -> None:
80+
assert url
81+
assert parse.detect_vcs
82+
83+
matches = parse.detect_vcs.match(url, is_explicit=is_explicit)
84+
85+
# Just add water
86+
expected_matches: t.List["DetectVCSFixtureExpectedMatch"] = []
87+
for idx, expected_match in enumerate(expected_matches_lazy):
88+
if callable(expected_match):
89+
assert callable(expected_match)
90+
expected_matches.append(expected_match(url))
91+
92+
assert matches == expected_matches

0 commit comments

Comments
 (0)
0