• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

abravalheri / validate-pyproject / 6173991897923584

11 Nov 2024 04:41PM CUT coverage: 97.859%. Remained the same
6173991897923584

Pull #218

cirrus-ci

pre-commit-ci[bot]
[pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci
Pull Request #218: [pre-commit.ci] pre-commit autoupdate

293 of 306 branches covered (95.75%)

Branch coverage included in aggregate %.

1 of 1 new or added line in 1 file covered. (100.0%)

941 of 955 relevant lines covered (98.53%)

6.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.06
/src/validate_pyproject/remote.py
1
import json
7✔
2
import logging
7✔
3
import typing
7✔
4
import urllib.parse
7✔
5
from typing import Generator, Optional, Tuple
7✔
6

7
from . import caching, errors, http
7✔
8
from .types import Schema
7✔
9

10
if typing.TYPE_CHECKING:
11
    import sys
12

13
    if sys.version_info < (3, 11):
14
        from typing_extensions import Self
15
    else:
16
        from typing import Self
17

18

19
__all__ = ["RemotePlugin", "load_store"]
7✔
20

21

22
_logger = logging.getLogger(__name__)
7✔
23

24

25
def load_from_uri(
7✔
26
    tool_uri: str, cache_dir: Optional[caching.PathLike] = None
27
) -> Tuple[str, Schema]:
28
    tool_info = urllib.parse.urlparse(tool_uri)
7✔
29
    if tool_info.netloc:
7✔
30
        url = f"{tool_info.scheme}://{tool_info.netloc}{tool_info.path}"
7✔
31
        download = caching.as_file(http.open_url, url, cache_dir)
7✔
32
        with download as f:
7✔
33
            contents = json.load(f)
7✔
34
    else:
35
        with open(tool_info.path, "rb") as f:
7✔
36
            contents = json.load(f)
7✔
37
    return tool_info.fragment, contents
7✔
38

39

40
class RemotePlugin:
7✔
41
    def __init__(self, *, tool: str, schema: Schema, fragment: str = ""):
7✔
42
        self.tool = tool
7✔
43
        self.schema = schema
7✔
44
        self.fragment = fragment
7✔
45
        self.id = self.schema["$id"]
7✔
46
        self.help_text = f"{tool} <external>"
7✔
47

48
    @classmethod
7✔
49
    def from_url(cls, tool: str, url: str) -> "Self":
7✔
50
        fragment, schema = load_from_uri(url)
7✔
51
        return cls(tool=tool, schema=schema, fragment=fragment)
7✔
52

53
    @classmethod
7✔
54
    def from_str(cls, tool_url: str) -> "Self":
7✔
55
        tool, _, url = tool_url.partition("=")
7✔
56
        if not url:
7✔
57
            raise errors.URLMissingTool(tool)
7✔
58
        return cls.from_url(tool, url)
7✔
59

60

61
def load_store(pyproject_url: str) -> Generator[RemotePlugin, None, None]:
7✔
62
    """
63
    Takes a URL / Path and loads the tool table, assuming it is a set of ref's.
64
    Currently ignores "inline" sections. This is the format that SchemaStore
65
    (https://json.schemastore.org/pyproject.json) is in.
66
    """
67

68
    fragment, contents = load_from_uri(pyproject_url)
7✔
69
    if fragment:
7!
70
        _logger.error(f"Must not be called with a fragment, got {fragment!r}")
×
71
    table = contents["properties"]["tool"]["properties"]
7✔
72
    for tool, info in table.items():
7✔
73
        if tool in {"setuptools", "distutils"}:
7✔
74
            pass  # built-in
7✔
75
        elif "$ref" in info:
7✔
76
            _logger.info(f"Loading {tool} from store: {pyproject_url}")
7✔
77
            yield RemotePlugin.from_url(tool, info["$ref"])
7✔
78
        else:
79
            _logger.warning(f"{tool!r} does not contain $ref")
7✔
80

81

82
if typing.TYPE_CHECKING:
83
    from .plugins import PluginProtocol
84

85
    _: PluginProtocol = typing.cast(RemotePlugin, None)
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc