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

abravalheri / validate-pyproject / 11034501584

25 Sep 2024 01:49PM CUT coverage: 97.823% (-0.2%) from 97.976%
11034501584

push

github

abravalheri
Prevent Github action for ignoring files for cache

551 of 571 branches covered (96.5%)

Branch coverage included in aggregate %.

932 of 945 relevant lines covered (98.62%)

5.91 hits per line

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

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

7
from . import caching, errors, http
6✔
8
from .types import Schema
6✔
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"]
6✔
20

21

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

24

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

39

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

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

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

60

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