]> jfr.im git - dlqueue.git/blob - venv/lib/python3.11/site-packages/setuptools/_vendor/packaging/requirements.py
init: venv aand flask
[dlqueue.git] / venv / lib / python3.11 / site-packages / setuptools / _vendor / packaging / requirements.py
1 # This file is dual licensed under the terms of the Apache License, Version
2 # 2.0, and the BSD License. See the LICENSE file in the root of this repository
3 # for complete details.
4
5 import urllib.parse
6 from typing import Any, List, Optional, Set
7
8 from ._parser import parse_requirement as _parse_requirement
9 from ._tokenizer import ParserSyntaxError
10 from .markers import Marker, _normalize_extra_values
11 from .specifiers import SpecifierSet
12
13
14 class InvalidRequirement(ValueError):
15 """
16 An invalid requirement was found, users should refer to PEP 508.
17 """
18
19
20 class Requirement:
21 """Parse a requirement.
22
23 Parse a given requirement string into its parts, such as name, specifier,
24 URL, and extras. Raises InvalidRequirement on a badly-formed requirement
25 string.
26 """
27
28 # TODO: Can we test whether something is contained within a requirement?
29 # If so how do we do that? Do we need to test against the _name_ of
30 # the thing as well as the version? What about the markers?
31 # TODO: Can we normalize the name and extra name?
32
33 def __init__(self, requirement_string: str) -> None:
34 try:
35 parsed = _parse_requirement(requirement_string)
36 except ParserSyntaxError as e:
37 raise InvalidRequirement(str(e)) from e
38
39 self.name: str = parsed.name
40 if parsed.url:
41 parsed_url = urllib.parse.urlparse(parsed.url)
42 if parsed_url.scheme == "file":
43 if urllib.parse.urlunparse(parsed_url) != parsed.url:
44 raise InvalidRequirement("Invalid URL given")
45 elif not (parsed_url.scheme and parsed_url.netloc) or (
46 not parsed_url.scheme and not parsed_url.netloc
47 ):
48 raise InvalidRequirement(f"Invalid URL: {parsed.url}")
49 self.url: Optional[str] = parsed.url
50 else:
51 self.url = None
52 self.extras: Set[str] = set(parsed.extras if parsed.extras else [])
53 self.specifier: SpecifierSet = SpecifierSet(parsed.specifier)
54 self.marker: Optional[Marker] = None
55 if parsed.marker is not None:
56 self.marker = Marker.__new__(Marker)
57 self.marker._markers = _normalize_extra_values(parsed.marker)
58
59 def __str__(self) -> str:
60 parts: List[str] = [self.name]
61
62 if self.extras:
63 formatted_extras = ",".join(sorted(self.extras))
64 parts.append(f"[{formatted_extras}]")
65
66 if self.specifier:
67 parts.append(str(self.specifier))
68
69 if self.url:
70 parts.append(f"@ {self.url}")
71 if self.marker:
72 parts.append(" ")
73
74 if self.marker:
75 parts.append(f"; {self.marker}")
76
77 return "".join(parts)
78
79 def __repr__(self) -> str:
80 return f"<Requirement('{self}')>"
81
82 def __hash__(self) -> int:
83 return hash((self.__class__.__name__, str(self)))
84
85 def __eq__(self, other: Any) -> bool:
86 if not isinstance(other, Requirement):
87 return NotImplemented
88
89 return (
90 self.name == other.name
91 and self.extras == other.extras
92 and self.specifier == other.specifier
93 and self.url == other.url
94 and self.marker == other.marker
95 )