specifiers.py 70 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943
  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. .. testsetup::
  6. from packaging.specifiers import Specifier, SpecifierSet, InvalidSpecifier
  7. from packaging.version import Version
  8. """
  9. from __future__ import annotations
  10. import abc
  11. import enum
  12. import functools
  13. import itertools
  14. import re
  15. import sys
  16. import typing
  17. from typing import (
  18. TYPE_CHECKING,
  19. Any,
  20. Callable,
  21. Final,
  22. Iterable,
  23. Iterator,
  24. Sequence,
  25. TypeVar,
  26. Union,
  27. )
  28. from .utils import canonicalize_version
  29. from .version import InvalidVersion, Version
  30. if sys.version_info >= (3, 10):
  31. from typing import TypeGuard # pragma: no cover
  32. elif TYPE_CHECKING:
  33. from typing_extensions import TypeGuard
  34. __all__ = [
  35. "BaseSpecifier",
  36. "InvalidSpecifier",
  37. "Specifier",
  38. "SpecifierSet",
  39. ]
  40. def __dir__() -> list[str]:
  41. return __all__
  42. def _validate_spec(spec: object, /) -> TypeGuard[tuple[str, str]]:
  43. return (
  44. isinstance(spec, tuple)
  45. and len(spec) == 2
  46. and isinstance(spec[0], str)
  47. and isinstance(spec[1], str)
  48. )
  49. def _validate_pre(pre: object, /) -> TypeGuard[bool | None]:
  50. return pre is None or isinstance(pre, bool)
  51. T = TypeVar("T")
  52. UnparsedVersion = Union[Version, str]
  53. UnparsedVersionVar = TypeVar("UnparsedVersionVar", bound=UnparsedVersion)
  54. CallableOperator = Callable[[Version, str], bool]
  55. # The smallest possible PEP 440 version. No valid version is less than this.
  56. _MIN_VERSION: Final[Version] = Version("0.dev0")
  57. def _trim_release(release: tuple[int, ...]) -> tuple[int, ...]:
  58. """Strip trailing zeros from a release tuple for normalized comparison."""
  59. end = len(release)
  60. while end > 1 and release[end - 1] == 0:
  61. end -= 1
  62. return release if end == len(release) else release[:end]
  63. class _BoundaryKind(enum.Enum):
  64. """Where a boundary marker sits in the version ordering."""
  65. AFTER_LOCALS = enum.auto() # after V+local, before V.post0
  66. AFTER_POSTS = enum.auto() # after V.postN, before next release
  67. @functools.total_ordering
  68. class _BoundaryVersion:
  69. """A point on the version line between two real PEP 440 versions.
  70. Some specifier semantics imply boundaries between real versions:
  71. ``<=1.0`` includes ``1.0+local`` and ``>1.0`` excludes
  72. ``1.0.post0``. No real :class:`Version` falls on those boundaries,
  73. so this class creates values that sort between the real versions
  74. on either side.
  75. Two kinds exist, shown relative to a base version V::
  76. V < V+local < AFTER_LOCALS(V) < V.post0 < AFTER_POSTS(V)
  77. ``AFTER_LOCALS`` sits after V and every V+local, but before
  78. V.post0. Upper bound of ``<=V``, ``==V``, ``!=V``.
  79. ``AFTER_POSTS`` sits after every V.postN, but before the next
  80. release segment. Lower bound of ``>V`` (final or pre-release V)
  81. to exclude post-releases per PEP 440.
  82. """
  83. __slots__ = ("_kind", "_trimmed_release", "version")
  84. def __init__(self, version: Version, kind: _BoundaryKind) -> None:
  85. self.version = version
  86. self._kind = kind
  87. self._trimmed_release = _trim_release(version.release)
  88. def _is_family(self, other: Version) -> bool:
  89. """Is ``other`` a version that this boundary sorts above?"""
  90. v = self.version
  91. if not (
  92. other.epoch == v.epoch
  93. and _trim_release(other.release) == self._trimmed_release
  94. and other.pre == v.pre
  95. ):
  96. return False
  97. if self._kind == _BoundaryKind.AFTER_LOCALS:
  98. # Local family: exact same public version (any local label).
  99. return other.post == v.post and other.dev == v.dev
  100. # Post family: same base + any post-release (or identical).
  101. return other.dev == v.dev or other.post is not None
  102. def __eq__(self, other: object) -> bool:
  103. if isinstance(other, _BoundaryVersion):
  104. return self.version == other.version and self._kind == other._kind
  105. return NotImplemented
  106. def __lt__(self, other: _BoundaryVersion | Version) -> bool:
  107. if isinstance(other, _BoundaryVersion):
  108. if self.version != other.version:
  109. return self.version < other.version
  110. return self._kind.value < other._kind.value
  111. return not self._is_family(other) and self.version < other
  112. def __hash__(self) -> int:
  113. return hash((self.version, self._kind))
  114. def __repr__(self) -> str:
  115. return f"{self.__class__.__name__}({self.version!r}, {self._kind.name})"
  116. @functools.total_ordering
  117. class _LowerBound:
  118. """Lower bound of a version range.
  119. A version *v* of ``None`` means unbounded below (-inf).
  120. At equal versions, ``[v`` sorts before ``(v`` because an inclusive
  121. bound starts earlier.
  122. """
  123. __slots__ = ("inclusive", "version")
  124. def __init__(self, version: _VersionOrBoundary, inclusive: bool) -> None:
  125. self.version = version
  126. self.inclusive = inclusive
  127. def __eq__(self, other: object) -> bool:
  128. if not isinstance(other, _LowerBound):
  129. return NotImplemented # pragma: no cover
  130. return self.version == other.version and self.inclusive == other.inclusive
  131. def __lt__(self, other: _LowerBound) -> bool:
  132. if not isinstance(other, _LowerBound): # pragma: no cover
  133. return NotImplemented
  134. # -inf < anything (except -inf).
  135. if self.version is None:
  136. return other.version is not None
  137. if other.version is None:
  138. return False
  139. if self.version != other.version:
  140. return self.version < other.version
  141. # [v < (v: inclusive starts earlier.
  142. return self.inclusive and not other.inclusive
  143. def __hash__(self) -> int:
  144. return hash((self.version, self.inclusive))
  145. def __repr__(self) -> str:
  146. bracket = "[" if self.inclusive else "("
  147. return f"<{self.__class__.__name__} {bracket}{self.version!r}>"
  148. @functools.total_ordering
  149. class _UpperBound:
  150. """Upper bound of a version range.
  151. A version *v* of ``None`` means unbounded above (+inf).
  152. At equal versions, ``v)`` sorts before ``v]`` because an exclusive
  153. bound ends earlier.
  154. """
  155. __slots__ = ("inclusive", "version")
  156. def __init__(self, version: _VersionOrBoundary, inclusive: bool) -> None:
  157. self.version = version
  158. self.inclusive = inclusive
  159. def __eq__(self, other: object) -> bool:
  160. if not isinstance(other, _UpperBound):
  161. return NotImplemented # pragma: no cover
  162. return self.version == other.version and self.inclusive == other.inclusive
  163. def __lt__(self, other: _UpperBound) -> bool:
  164. if not isinstance(other, _UpperBound): # pragma: no cover
  165. return NotImplemented
  166. # Nothing < +inf (except +inf itself).
  167. if self.version is None:
  168. return False
  169. if other.version is None:
  170. return True
  171. if self.version != other.version:
  172. return self.version < other.version
  173. # v) < v]: exclusive ends earlier.
  174. return not self.inclusive and other.inclusive
  175. def __hash__(self) -> int:
  176. return hash((self.version, self.inclusive))
  177. def __repr__(self) -> str:
  178. bracket = "]" if self.inclusive else ")"
  179. return f"<{self.__class__.__name__} {self.version!r}{bracket}>"
  180. if typing.TYPE_CHECKING:
  181. _VersionOrBoundary = Union[Version, _BoundaryVersion, None]
  182. #: A single contiguous version range, represented as a
  183. #: (lower bound, upper bound) pair.
  184. _VersionRange = tuple[_LowerBound, _UpperBound]
  185. _NEG_INF = _LowerBound(None, False)
  186. _POS_INF = _UpperBound(None, False)
  187. _FULL_RANGE: tuple[_VersionRange] = ((_NEG_INF, _POS_INF),)
  188. def _range_is_empty(lower: _LowerBound, upper: _UpperBound) -> bool:
  189. """True when the range defined by *lower* and *upper* contains no versions."""
  190. if lower.version is None or upper.version is None:
  191. return False
  192. if lower.version == upper.version:
  193. return not (lower.inclusive and upper.inclusive)
  194. return lower.version > upper.version
  195. def _intersect_ranges(
  196. left: Sequence[_VersionRange],
  197. right: Sequence[_VersionRange],
  198. ) -> list[_VersionRange]:
  199. """Intersect two sorted, non-overlapping range lists (two-pointer merge)."""
  200. result: list[_VersionRange] = []
  201. left_index = right_index = 0
  202. while left_index < len(left) and right_index < len(right):
  203. left_lower, left_upper = left[left_index]
  204. right_lower, right_upper = right[right_index]
  205. lower = max(left_lower, right_lower)
  206. upper = min(left_upper, right_upper)
  207. if not _range_is_empty(lower, upper):
  208. result.append((lower, upper))
  209. # Advance whichever side has the smaller upper bound.
  210. if left_upper < right_upper:
  211. left_index += 1
  212. else:
  213. right_index += 1
  214. return result
  215. def _next_prefix_dev0(version: Version) -> Version:
  216. """Smallest version in the next prefix: 1.2 -> 1.3.dev0."""
  217. release = (*version.release[:-1], version.release[-1] + 1)
  218. return Version.from_parts(epoch=version.epoch, release=release, dev=0)
  219. def _base_dev0(version: Version) -> Version:
  220. """The .dev0 of a version's base release: 1.2 -> 1.2.dev0."""
  221. return Version.from_parts(epoch=version.epoch, release=version.release, dev=0)
  222. def _coerce_version(version: UnparsedVersion) -> Version | None:
  223. if not isinstance(version, Version):
  224. try:
  225. version = Version(version)
  226. except InvalidVersion:
  227. return None
  228. return version
  229. def _public_version(version: Version) -> Version:
  230. if version.local is None:
  231. return version
  232. return version.__replace__(local=None)
  233. def _post_base(version: Version) -> Version:
  234. """The version that *version* is a post-release of.
  235. 1.0.post1 -> 1.0, 1.0a1.post0 -> 1.0a1, 1.0.post0.dev1 -> 1.0.
  236. """
  237. return version.__replace__(post=None, dev=None, local=None)
  238. def _earliest_prerelease(version: Version) -> Version:
  239. """Earliest pre-release of *version*.
  240. 1.2 -> 1.2.dev0, 1.2.post1 -> 1.2.post1.dev0.
  241. """
  242. return version.__replace__(dev=0, local=None)
  243. def _nearest_non_prerelease(
  244. v: _VersionOrBoundary,
  245. ) -> Version | None:
  246. """Smallest non-pre-release version at or above *v*, or None."""
  247. if v is None:
  248. return None
  249. if isinstance(v, _BoundaryVersion):
  250. inner = v.version
  251. if inner.is_prerelease:
  252. # AFTER_LOCALS(1.0a1) -> nearest non-pre is 1.0
  253. return inner.__replace__(pre=None, dev=None, local=None)
  254. # AFTER_LOCALS(1.0) -> nearest non-pre is 1.0.post0
  255. # AFTER_LOCALS(1.0.post0) -> nearest non-pre is 1.0.post1
  256. k = (inner.post + 1) if inner.post is not None else 0
  257. return inner.__replace__(post=k, local=None)
  258. if not v.is_prerelease:
  259. return v
  260. # Strip pre/dev to get the final or post-release form.
  261. return v.__replace__(pre=None, dev=None, local=None)
  262. class InvalidSpecifier(ValueError):
  263. """
  264. Raised when attempting to create a :class:`Specifier` with a specifier
  265. string that is invalid.
  266. >>> Specifier("lolwat")
  267. Traceback (most recent call last):
  268. ...
  269. packaging.specifiers.InvalidSpecifier: Invalid specifier: 'lolwat'
  270. """
  271. class BaseSpecifier(metaclass=abc.ABCMeta):
  272. __slots__ = ()
  273. __match_args__ = ("_str",)
  274. @property
  275. def _str(self) -> str:
  276. """Internal property for match_args"""
  277. return str(self)
  278. @abc.abstractmethod
  279. def __str__(self) -> str:
  280. """
  281. Returns the str representation of this Specifier-like object. This
  282. should be representative of the Specifier itself.
  283. """
  284. @abc.abstractmethod
  285. def __hash__(self) -> int:
  286. """
  287. Returns a hash value for this Specifier-like object.
  288. """
  289. @abc.abstractmethod
  290. def __eq__(self, other: object) -> bool:
  291. """
  292. Returns a boolean representing whether or not the two Specifier-like
  293. objects are equal.
  294. :param other: The other object to check against.
  295. """
  296. @property
  297. @abc.abstractmethod
  298. def prereleases(self) -> bool | None:
  299. """Whether or not pre-releases as a whole are allowed.
  300. This can be set to either ``True`` or ``False`` to explicitly enable or disable
  301. prereleases or it can be set to ``None`` (the default) to use default semantics.
  302. """
  303. @prereleases.setter # noqa: B027
  304. def prereleases(self, value: bool) -> None:
  305. """Setter for :attr:`prereleases`.
  306. :param value: The value to set.
  307. """
  308. @abc.abstractmethod
  309. def contains(self, item: str, prereleases: bool | None = None) -> bool:
  310. """
  311. Determines if the given item is contained within this specifier.
  312. """
  313. @typing.overload
  314. def filter(
  315. self,
  316. iterable: Iterable[UnparsedVersionVar],
  317. prereleases: bool | None = None,
  318. key: None = ...,
  319. ) -> Iterator[UnparsedVersionVar]: ...
  320. @typing.overload
  321. def filter(
  322. self,
  323. iterable: Iterable[T],
  324. prereleases: bool | None = None,
  325. key: Callable[[T], UnparsedVersion] = ...,
  326. ) -> Iterator[T]: ...
  327. @abc.abstractmethod
  328. def filter(
  329. self,
  330. iterable: Iterable[Any],
  331. prereleases: bool | None = None,
  332. key: Callable[[Any], UnparsedVersion] | None = None,
  333. ) -> Iterator[Any]:
  334. """
  335. Takes an iterable of items and filters them so that only items which
  336. are contained within this specifier are allowed in it.
  337. """
  338. class Specifier(BaseSpecifier):
  339. """This class abstracts handling of version specifiers.
  340. .. tip::
  341. It is generally not required to instantiate this manually. You should instead
  342. prefer to work with :class:`SpecifierSet` instead, which can parse
  343. comma-separated version specifiers (which is what package metadata contains).
  344. Instances are safe to serialize with :mod:`pickle`. They use a stable
  345. format so the same pickle can be loaded in future packaging releases.
  346. .. versionchanged:: 26.2
  347. Added a stable pickle format. Pickles created with packaging 26.2+ can
  348. be unpickled with future releases. Backward compatibility with pickles
  349. from packaging < 26.2 is supported but may be removed in a future
  350. release.
  351. """
  352. __slots__ = (
  353. "_prereleases",
  354. "_ranges",
  355. "_spec",
  356. "_spec_version",
  357. "_wildcard_split",
  358. )
  359. _specifier_regex_str = r"""
  360. (?:
  361. (?:
  362. # The identity operators allow for an escape hatch that will
  363. # do an exact string match of the version you wish to install.
  364. # This will not be parsed by PEP 440 and we cannot determine
  365. # any semantic meaning from it. This operator is discouraged
  366. # but included entirely as an escape hatch.
  367. === # Only match for the identity operator
  368. \s*
  369. [^\s;)]* # The arbitrary version can be just about anything,
  370. # we match everything except for whitespace, a
  371. # semi-colon for marker support, and a closing paren
  372. # since versions can be enclosed in them.
  373. )
  374. |
  375. (?:
  376. # The (non)equality operators allow for wild card and local
  377. # versions to be specified so we have to define these two
  378. # operators separately to enable that.
  379. (?:==|!=) # Only match for equals and not equals
  380. \s*
  381. v?
  382. (?:[0-9]+!)? # epoch
  383. [0-9]+(?:\.[0-9]+)* # release
  384. # You cannot use a wild card and a pre-release, post-release, a dev or
  385. # local version together so group them with a | and make them optional.
  386. (?:
  387. \.\* # Wild card syntax of .*
  388. |
  389. (?a: # pre release
  390. [-_\.]?
  391. (alpha|beta|preview|pre|a|b|c|rc)
  392. [-_\.]?
  393. [0-9]*
  394. )?
  395. (?a: # post release
  396. (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*)
  397. )?
  398. (?a:[-_\.]?dev[-_\.]?[0-9]*)? # dev release
  399. (?a:\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*)? # local
  400. )?
  401. )
  402. |
  403. (?:
  404. # The compatible operator requires at least two digits in the
  405. # release segment.
  406. (?:~=) # Only match for the compatible operator
  407. \s*
  408. v?
  409. (?:[0-9]+!)? # epoch
  410. [0-9]+(?:\.[0-9]+)+ # release (We have a + instead of a *)
  411. (?: # pre release
  412. [-_\.]?
  413. (alpha|beta|preview|pre|a|b|c|rc)
  414. [-_\.]?
  415. [0-9]*
  416. )?
  417. (?: # post release
  418. (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*)
  419. )?
  420. (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release
  421. )
  422. |
  423. (?:
  424. # All other operators only allow a sub set of what the
  425. # (non)equality operators do. Specifically they do not allow
  426. # local versions to be specified nor do they allow the prefix
  427. # matching wild cards.
  428. (?:<=|>=|<|>)
  429. \s*
  430. v?
  431. (?:[0-9]+!)? # epoch
  432. [0-9]+(?:\.[0-9]+)* # release
  433. (?a: # pre release
  434. [-_\.]?
  435. (alpha|beta|preview|pre|a|b|c|rc)
  436. [-_\.]?
  437. [0-9]*
  438. )?
  439. (?a: # post release
  440. (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*)
  441. )?
  442. (?a:[-_\.]?dev[-_\.]?[0-9]*)? # dev release
  443. )
  444. )
  445. """
  446. _regex = re.compile(
  447. r"\s*" + _specifier_regex_str + r"\s*", re.VERBOSE | re.IGNORECASE
  448. )
  449. _operators: Final = {
  450. "~=": "compatible",
  451. "==": "equal",
  452. "!=": "not_equal",
  453. "<=": "less_than_equal",
  454. ">=": "greater_than_equal",
  455. "<": "less_than",
  456. ">": "greater_than",
  457. "===": "arbitrary",
  458. }
  459. def __init__(self, spec: str = "", prereleases: bool | None = None) -> None:
  460. """Initialize a Specifier instance.
  461. :param spec:
  462. The string representation of a specifier which will be parsed and
  463. normalized before use.
  464. :param prereleases:
  465. This tells the specifier if it should accept prerelease versions if
  466. applicable or not. The default of ``None`` will autodetect it from the
  467. given specifiers.
  468. :raises InvalidSpecifier:
  469. If the given specifier is invalid (i.e. bad syntax).
  470. """
  471. if not self._regex.fullmatch(spec):
  472. raise InvalidSpecifier(f"Invalid specifier: {spec!r}")
  473. spec = spec.strip()
  474. if spec.startswith("==="):
  475. operator, version = spec[:3], spec[3:].strip()
  476. elif spec.startswith(("~=", "==", "!=", "<=", ">=")):
  477. operator, version = spec[:2], spec[2:].strip()
  478. else:
  479. operator, version = spec[:1], spec[1:].strip()
  480. self._spec: tuple[str, str] = (operator, version)
  481. # Store whether or not this Specifier should accept prereleases
  482. self._prereleases = prereleases
  483. # Specifier version cache
  484. self._spec_version: tuple[str, Version] | None = None
  485. # Populated on first wildcard (==X.*) comparison
  486. self._wildcard_split: tuple[list[str], int] | None = None
  487. # Version range cache (populated by _to_ranges)
  488. self._ranges: Sequence[_VersionRange] | None = None
  489. def _get_spec_version(self, version: str) -> Version | None:
  490. """One element cache, as only one spec Version is needed per Specifier."""
  491. if self._spec_version is not None and self._spec_version[0] == version:
  492. return self._spec_version[1]
  493. version_specifier = _coerce_version(version)
  494. if version_specifier is None:
  495. return None
  496. self._spec_version = (version, version_specifier)
  497. return version_specifier
  498. def _require_spec_version(self, version: str) -> Version:
  499. """Get spec version, asserting it's valid (not for === operator).
  500. This method should only be called for operators where version
  501. strings are guaranteed to be valid PEP 440 versions (not ===).
  502. """
  503. spec_version = self._get_spec_version(version)
  504. assert spec_version is not None
  505. return spec_version
  506. def _to_ranges(self) -> Sequence[_VersionRange]:
  507. """Convert this specifier to sorted, non-overlapping version ranges.
  508. Each standard operator maps to one or two ranges. ``===`` is
  509. modeled as full range (actual check done separately). Cached.
  510. """
  511. if self._ranges is not None:
  512. return self._ranges
  513. op = self.operator
  514. ver_str = self.version
  515. if op == "===":
  516. self._ranges = _FULL_RANGE
  517. return _FULL_RANGE
  518. if ver_str.endswith(".*"):
  519. result = self._wildcard_ranges(op, ver_str)
  520. else:
  521. result = self._standard_ranges(op, ver_str)
  522. self._ranges = result
  523. return result
  524. def _wildcard_ranges(self, op: str, ver_str: str) -> list[_VersionRange]:
  525. # ==1.2.* -> [1.2.dev0, 1.3.dev0); !=1.2.* -> complement.
  526. base = self._require_spec_version(ver_str[:-2])
  527. lower = _base_dev0(base)
  528. upper = _next_prefix_dev0(base)
  529. if op == "==":
  530. return [(_LowerBound(lower, True), _UpperBound(upper, False))]
  531. # !=
  532. return [
  533. (_NEG_INF, _UpperBound(lower, False)),
  534. (_LowerBound(upper, True), _POS_INF),
  535. ]
  536. def _standard_ranges(self, op: str, ver_str: str) -> list[_VersionRange]:
  537. v = self._require_spec_version(ver_str)
  538. if op == ">=":
  539. return [(_LowerBound(v, True), _POS_INF)]
  540. if op == "<=":
  541. return [
  542. (
  543. _NEG_INF,
  544. _UpperBound(_BoundaryVersion(v, _BoundaryKind.AFTER_LOCALS), True),
  545. )
  546. ]
  547. if op == ">":
  548. if v.dev is not None:
  549. # >V.devN: dev versions have no post-releases, so the
  550. # next real version is V.dev(N+1).
  551. lower_ver = v.__replace__(dev=v.dev + 1, local=None)
  552. return [(_LowerBound(lower_ver, True), _POS_INF)]
  553. if v.post is not None:
  554. # >V.postN: next real version is V.post(N+1).dev0.
  555. lower_ver = v.__replace__(post=v.post + 1, dev=0, local=None)
  556. return [(_LowerBound(lower_ver, True), _POS_INF)]
  557. # >V (final or pre-release): skip V+local and all V.postN.
  558. return [
  559. (
  560. _LowerBound(_BoundaryVersion(v, _BoundaryKind.AFTER_POSTS), False),
  561. _POS_INF,
  562. )
  563. ]
  564. if op == "<":
  565. # <V excludes prereleases of V when V is not a prerelease.
  566. # V.dev0 is the earliest prerelease of V (final, post, etc.).
  567. bound = v if v.is_prerelease else v.__replace__(dev=0, local=None)
  568. if bound <= _MIN_VERSION:
  569. return []
  570. return [(_NEG_INF, _UpperBound(bound, False))]
  571. # ==, !=: local versions of V match when spec has no local segment.
  572. has_local = "+" in ver_str
  573. after_locals = _BoundaryVersion(v, _BoundaryKind.AFTER_LOCALS)
  574. upper = v if has_local else after_locals
  575. if op == "==":
  576. return [(_LowerBound(v, True), _UpperBound(upper, True))]
  577. if op == "!=":
  578. return [
  579. (_NEG_INF, _UpperBound(v, False)),
  580. (_LowerBound(upper, False), _POS_INF),
  581. ]
  582. if op == "~=":
  583. prefix = v.__replace__(release=v.release[:-1])
  584. return [
  585. (_LowerBound(v, True), _UpperBound(_next_prefix_dev0(prefix), False))
  586. ]
  587. raise ValueError(f"Unknown operator: {op!r}") # pragma: no cover
  588. @property
  589. def prereleases(self) -> bool | None:
  590. # If there is an explicit prereleases set for this, then we'll just
  591. # blindly use that.
  592. if self._prereleases is not None:
  593. return self._prereleases
  594. # Only the "!=" operator does not imply prereleases when
  595. # the version in the specifier is a prerelease.
  596. operator, version_str = self._spec
  597. if operator == "!=":
  598. return False
  599. # The == specifier with trailing .* cannot include prereleases
  600. # e.g. "==1.0a1.*" is not valid.
  601. if operator == "==" and version_str.endswith(".*"):
  602. return False
  603. # "===" can have arbitrary string versions, so we cannot parse
  604. # those, we take prereleases as unknown (None) for those.
  605. version = self._get_spec_version(version_str)
  606. if version is None:
  607. return None
  608. # For all other operators, use the check if spec Version
  609. # object implies pre-releases.
  610. return version.is_prerelease
  611. @prereleases.setter
  612. def prereleases(self, value: bool | None) -> None:
  613. self._prereleases = value
  614. def __getstate__(self) -> tuple[tuple[str, str], bool | None]:
  615. # Return state as a 2-item tuple for compactness:
  616. # ((operator, version), prereleases)
  617. # Cache members are excluded and will be recomputed on demand.
  618. return (self._spec, self._prereleases)
  619. def __setstate__(self, state: object) -> None:
  620. # Always discard cached values - they will be recomputed on demand.
  621. self._spec_version = None
  622. self._wildcard_split = None
  623. self._ranges = None
  624. if isinstance(state, tuple):
  625. if len(state) == 2:
  626. # New format (26.2+): ((operator, version), prereleases)
  627. spec, prereleases = state
  628. if _validate_spec(spec) and _validate_pre(prereleases):
  629. self._spec = spec
  630. self._prereleases = prereleases
  631. return
  632. if len(state) == 2 and isinstance(state[1], dict):
  633. # Format (packaging 26.0-26.1): (None, {slot: value}).
  634. _, slot_dict = state
  635. spec = slot_dict.get("_spec")
  636. prereleases = slot_dict.get("_prereleases", "invalid")
  637. if _validate_spec(spec) and _validate_pre(prereleases):
  638. self._spec = spec
  639. self._prereleases = prereleases
  640. return
  641. if isinstance(state, dict):
  642. # Old format (packaging <= 25.x, no __slots__): state is a plain dict.
  643. spec = state.get("_spec")
  644. prereleases = state.get("_prereleases", "invalid")
  645. if _validate_spec(spec) and _validate_pre(prereleases):
  646. self._spec = spec
  647. self._prereleases = prereleases
  648. return
  649. raise TypeError(f"Cannot restore Specifier from {state!r}")
  650. @property
  651. def operator(self) -> str:
  652. """The operator of this specifier.
  653. >>> Specifier("==1.2.3").operator
  654. '=='
  655. """
  656. return self._spec[0]
  657. @property
  658. def version(self) -> str:
  659. """The version of this specifier.
  660. >>> Specifier("==1.2.3").version
  661. '1.2.3'
  662. """
  663. return self._spec[1]
  664. def __repr__(self) -> str:
  665. """A representation of the Specifier that shows all internal state.
  666. >>> Specifier('>=1.0.0')
  667. <Specifier('>=1.0.0')>
  668. >>> Specifier('>=1.0.0', prereleases=False)
  669. <Specifier('>=1.0.0', prereleases=False)>
  670. >>> Specifier('>=1.0.0', prereleases=True)
  671. <Specifier('>=1.0.0', prereleases=True)>
  672. """
  673. pre = (
  674. f", prereleases={self.prereleases!r}"
  675. if self._prereleases is not None
  676. else ""
  677. )
  678. return f"<{self.__class__.__name__}({str(self)!r}{pre})>"
  679. def __str__(self) -> str:
  680. """A string representation of the Specifier that can be round-tripped.
  681. >>> str(Specifier('>=1.0.0'))
  682. '>=1.0.0'
  683. >>> str(Specifier('>=1.0.0', prereleases=False))
  684. '>=1.0.0'
  685. """
  686. return "{}{}".format(*self._spec)
  687. @property
  688. def _canonical_spec(self) -> tuple[str, str]:
  689. operator, version = self._spec
  690. if operator == "===" or version.endswith(".*"):
  691. return operator, version
  692. spec_version = self._require_spec_version(version)
  693. canonical_version = canonicalize_version(
  694. spec_version, strip_trailing_zero=(operator != "~=")
  695. )
  696. return operator, canonical_version
  697. def __hash__(self) -> int:
  698. return hash(self._canonical_spec)
  699. def __eq__(self, other: object) -> bool:
  700. """Whether or not the two Specifier-like objects are equal.
  701. :param other: The other object to check against.
  702. The value of :attr:`prereleases` is ignored.
  703. >>> Specifier("==1.2.3") == Specifier("== 1.2.3.0")
  704. True
  705. >>> (Specifier("==1.2.3", prereleases=False) ==
  706. ... Specifier("==1.2.3", prereleases=True))
  707. True
  708. >>> Specifier("==1.2.3") == "==1.2.3"
  709. True
  710. >>> Specifier("==1.2.3") == Specifier("==1.2.4")
  711. False
  712. >>> Specifier("==1.2.3") == Specifier("~=1.2.3")
  713. False
  714. """
  715. if isinstance(other, str):
  716. try:
  717. other = self.__class__(str(other))
  718. except InvalidSpecifier:
  719. return NotImplemented
  720. elif not isinstance(other, self.__class__):
  721. return NotImplemented
  722. return self._canonical_spec == other._canonical_spec
  723. def _get_operator(self, op: str) -> CallableOperator:
  724. operator_callable: CallableOperator = getattr(
  725. self, f"_compare_{self._operators[op]}"
  726. )
  727. return operator_callable
  728. def _compare_compatible(self, prospective: Version, spec: str) -> bool:
  729. # Compatible releases have an equivalent combination of >= and ==. That
  730. # is that ~=2.2 is equivalent to >=2.2,==2.*. This allows us to
  731. # implement this in terms of the other specifiers instead of
  732. # implementing it ourselves. The only thing we need to do is construct
  733. # the other specifiers.
  734. # We want everything but the last item in the version, but we want to
  735. # ignore suffix segments.
  736. prefix = _version_join(
  737. list(itertools.takewhile(_is_not_suffix, _version_split(spec)))[:-1]
  738. )
  739. # Add the prefix notation to the end of our string
  740. prefix += ".*"
  741. return (self._compare_greater_than_equal(prospective, spec)) and (
  742. self._compare_equal(prospective, prefix)
  743. )
  744. def _get_wildcard_split(self, spec: str) -> tuple[list[str], int]:
  745. """Cached split of a wildcard spec into components and numeric length.
  746. >>> Specifier("==1.*")._get_wildcard_split("1.*")
  747. (['0', '1'], 2)
  748. >>> Specifier("==3.10.*")._get_wildcard_split("3.10.*")
  749. (['0', '3', '10'], 3)
  750. """
  751. wildcard_split = self._wildcard_split
  752. if wildcard_split is None:
  753. normalized = canonicalize_version(spec[:-2], strip_trailing_zero=False)
  754. split_spec = _version_split(normalized)
  755. wildcard_split = (split_spec, _numeric_prefix_len(split_spec))
  756. self._wildcard_split = wildcard_split
  757. return wildcard_split
  758. def _compare_equal(self, prospective: Version, spec: str) -> bool:
  759. # We need special logic to handle prefix matching
  760. if spec.endswith(".*"):
  761. split_spec, spec_numeric_len = self._get_wildcard_split(spec)
  762. # In the case of prefix matching we want to ignore local segment.
  763. normalized_prospective = canonicalize_version(
  764. _public_version(prospective), strip_trailing_zero=False
  765. )
  766. # Split the prospective version out by bangs and dots, and pretend
  767. # that there is an implicit dot in between a release segment and
  768. # a pre-release segment.
  769. split_prospective = _version_split(normalized_prospective)
  770. # 0-pad the prospective version before shortening it to get the correct
  771. # shortened version.
  772. padded_prospective = _left_pad(split_prospective, spec_numeric_len)
  773. # Shorten the prospective version to be the same length as the spec
  774. # so that we can determine if the specifier is a prefix of the
  775. # prospective version or not.
  776. shortened_prospective = padded_prospective[: len(split_spec)]
  777. return shortened_prospective == split_spec
  778. else:
  779. # Convert our spec string into a Version
  780. spec_version = self._require_spec_version(spec)
  781. # If the specifier does not have a local segment, then we want to
  782. # act as if the prospective version also does not have a local
  783. # segment.
  784. if not spec_version.local:
  785. prospective = _public_version(prospective)
  786. return prospective == spec_version
  787. def _compare_not_equal(self, prospective: Version, spec: str) -> bool:
  788. return not self._compare_equal(prospective, spec)
  789. def _compare_less_than_equal(self, prospective: Version, spec: str) -> bool:
  790. # NB: Local version identifiers are NOT permitted in the version
  791. # specifier, so local version labels can be universally removed from
  792. # the prospective version.
  793. return _public_version(prospective) <= self._require_spec_version(spec)
  794. def _compare_greater_than_equal(self, prospective: Version, spec: str) -> bool:
  795. # NB: Local version identifiers are NOT permitted in the version
  796. # specifier, so local version labels can be universally removed from
  797. # the prospective version.
  798. return _public_version(prospective) >= self._require_spec_version(spec)
  799. def _compare_less_than(self, prospective: Version, spec_str: str) -> bool:
  800. # Convert our spec to a Version instance, since we'll want to work with
  801. # it as a version.
  802. spec = self._require_spec_version(spec_str)
  803. # Check to see if the prospective version is less than the spec
  804. # version. If it's not we can short circuit and just return False now
  805. # instead of doing extra unneeded work.
  806. if not prospective < spec:
  807. return False
  808. # The spec says: "<V MUST NOT allow a pre-release of the specified
  809. # version unless the specified version is itself a pre-release."
  810. if (
  811. not spec.is_prerelease
  812. and prospective.is_prerelease
  813. and prospective >= _earliest_prerelease(spec)
  814. ):
  815. return False
  816. # If we've gotten to here, it means that prospective version is both
  817. # less than the spec version *and* it's not a pre-release of the same
  818. # version in the spec.
  819. return True
  820. def _compare_greater_than(self, prospective: Version, spec_str: str) -> bool:
  821. # Convert our spec to a Version instance, since we'll want to work with
  822. # it as a version.
  823. spec = self._require_spec_version(spec_str)
  824. # Check to see if the prospective version is greater than the spec
  825. # version. If it's not we can short circuit and just return False now
  826. # instead of doing extra unneeded work.
  827. if not prospective > spec:
  828. return False
  829. # The spec says: ">V MUST NOT allow a post-release of the specified
  830. # version unless the specified version is itself a post-release."
  831. if (
  832. not spec.is_postrelease
  833. and prospective.is_postrelease
  834. and _post_base(prospective) == spec
  835. ):
  836. return False
  837. # Per the spec: ">V MUST NOT match a local version of the specified
  838. # version". A "local version of V" is any version whose public part
  839. # equals V. So >1.0a1 must not match 1.0a1+local, but must still
  840. # match 1.0a2+local.
  841. if prospective.local is not None and _public_version(prospective) == spec:
  842. return False
  843. # If we've gotten to here, it means that prospective version is both
  844. # greater than the spec version *and* it's not a pre-release of the
  845. # same version in the spec.
  846. return True
  847. def _compare_arbitrary(self, prospective: Version | str, spec: str) -> bool:
  848. return str(prospective).lower() == str(spec).lower()
  849. def __contains__(self, item: str | Version) -> bool:
  850. """Return whether or not the item is contained in this specifier.
  851. :param item: The item to check for.
  852. This is used for the ``in`` operator and behaves the same as
  853. :meth:`contains` with no ``prereleases`` argument passed.
  854. >>> "1.2.3" in Specifier(">=1.2.3")
  855. True
  856. >>> Version("1.2.3") in Specifier(">=1.2.3")
  857. True
  858. >>> "1.0.0" in Specifier(">=1.2.3")
  859. False
  860. >>> "1.3.0a1" in Specifier(">=1.2.3")
  861. True
  862. >>> "1.3.0a1" in Specifier(">=1.2.3", prereleases=True)
  863. True
  864. """
  865. return self.contains(item)
  866. def contains(self, item: UnparsedVersion, prereleases: bool | None = None) -> bool:
  867. """Return whether or not the item is contained in this specifier.
  868. :param item:
  869. The item to check for, which can be a version string or a
  870. :class:`Version` instance.
  871. :param prereleases:
  872. Whether or not to match prereleases with this Specifier. If set to
  873. ``None`` (the default), it will follow the recommendation from
  874. :pep:`440` and match prereleases, as there are no other versions.
  875. >>> Specifier(">=1.2.3").contains("1.2.3")
  876. True
  877. >>> Specifier(">=1.2.3").contains(Version("1.2.3"))
  878. True
  879. >>> Specifier(">=1.2.3").contains("1.0.0")
  880. False
  881. >>> Specifier(">=1.2.3").contains("1.3.0a1")
  882. True
  883. >>> Specifier(">=1.2.3", prereleases=False).contains("1.3.0a1")
  884. False
  885. >>> Specifier(">=1.2.3").contains("1.3.0a1")
  886. True
  887. """
  888. return bool(list(self.filter([item], prereleases=prereleases)))
  889. @typing.overload
  890. def filter(
  891. self,
  892. iterable: Iterable[UnparsedVersionVar],
  893. prereleases: bool | None = None,
  894. key: None = ...,
  895. ) -> Iterator[UnparsedVersionVar]: ...
  896. @typing.overload
  897. def filter(
  898. self,
  899. iterable: Iterable[T],
  900. prereleases: bool | None = None,
  901. key: Callable[[T], UnparsedVersion] = ...,
  902. ) -> Iterator[T]: ...
  903. def filter(
  904. self,
  905. iterable: Iterable[Any],
  906. prereleases: bool | None = None,
  907. key: Callable[[Any], UnparsedVersion] | None = None,
  908. ) -> Iterator[Any]:
  909. """Filter items in the given iterable, that match the specifier.
  910. :param iterable:
  911. An iterable that can contain version strings and :class:`Version` instances.
  912. The items in the iterable will be filtered according to the specifier.
  913. :param prereleases:
  914. Whether or not to allow prereleases in the returned iterator. If set to
  915. ``None`` (the default), it will follow the recommendation from :pep:`440`
  916. and match prereleases if there are no other versions.
  917. :param key:
  918. A callable that takes a single argument (an item from the iterable) and
  919. returns a version string or :class:`Version` instance to be used for
  920. filtering.
  921. >>> list(Specifier(">=1.2.3").filter(["1.2", "1.3", "1.5a1"]))
  922. ['1.3']
  923. >>> list(Specifier(">=1.2.3").filter(["1.2", "1.2.3", "1.3", Version("1.4")]))
  924. ['1.2.3', '1.3', <Version('1.4')>]
  925. >>> list(Specifier(">=1.2.3").filter(["1.2", "1.5a1"]))
  926. ['1.5a1']
  927. >>> list(Specifier(">=1.2.3").filter(["1.3", "1.5a1"], prereleases=True))
  928. ['1.3', '1.5a1']
  929. >>> list(Specifier(">=1.2.3", prereleases=True).filter(["1.3", "1.5a1"]))
  930. ['1.3', '1.5a1']
  931. >>> list(Specifier(">=1.2.3").filter(
  932. ... [{"ver": "1.2"}, {"ver": "1.3"}],
  933. ... key=lambda x: x["ver"]))
  934. [{'ver': '1.3'}]
  935. """
  936. prereleases_versions = []
  937. found_non_prereleases = False
  938. # Determine if to include prereleases by default
  939. include_prereleases = (
  940. prereleases if prereleases is not None else self.prereleases
  941. )
  942. # Get the matching operator
  943. operator_callable = self._get_operator(self.operator)
  944. # Filter versions
  945. for version in iterable:
  946. parsed_version = _coerce_version(version if key is None else key(version))
  947. match = False
  948. if parsed_version is None:
  949. # === operator can match arbitrary (non-version) strings
  950. if self.operator == "===" and self._compare_arbitrary(
  951. version, self.version
  952. ):
  953. yield version
  954. elif self.operator == "===":
  955. match = self._compare_arbitrary(
  956. version if key is None else key(version), self.version
  957. )
  958. else:
  959. match = operator_callable(parsed_version, self.version)
  960. if match and parsed_version is not None:
  961. # If it's not a prerelease or prereleases are allowed, yield it directly
  962. if not parsed_version.is_prerelease or include_prereleases:
  963. found_non_prereleases = True
  964. yield version
  965. # Otherwise collect prereleases for potential later use
  966. elif prereleases is None and self._prereleases is not False:
  967. prereleases_versions.append(version)
  968. # If no non-prereleases were found and prereleases weren't
  969. # explicitly forbidden, yield the collected prereleases
  970. if (
  971. not found_non_prereleases
  972. and prereleases is None
  973. and self._prereleases is not False
  974. ):
  975. yield from prereleases_versions
  976. _prefix_regex = re.compile(r"([0-9]+)((?:a|b|c|rc)[0-9]+)")
  977. def _pep440_filter_prereleases(
  978. iterable: Iterable[Any], key: Callable[[Any], UnparsedVersion] | None
  979. ) -> Iterator[Any]:
  980. """Filter per PEP 440: exclude prereleases unless no finals exist."""
  981. # Two lists used:
  982. # * all_nonfinal to preserve order if no finals exist
  983. # * arbitrary_strings for streaming when first final found
  984. all_nonfinal: list[Any] = []
  985. arbitrary_strings: list[Any] = []
  986. found_final = False
  987. for item in iterable:
  988. parsed = _coerce_version(item if key is None else key(item))
  989. if parsed is None:
  990. # Arbitrary strings are always included as it is not
  991. # possible to determine if they are prereleases,
  992. # and they have already passed all specifiers.
  993. if found_final:
  994. yield item
  995. else:
  996. arbitrary_strings.append(item)
  997. all_nonfinal.append(item)
  998. continue
  999. if not parsed.is_prerelease:
  1000. # Final release found - flush arbitrary strings, then yield
  1001. if not found_final:
  1002. yield from arbitrary_strings
  1003. found_final = True
  1004. yield item
  1005. continue
  1006. # Prerelease - buffer if no finals yet, otherwise skip
  1007. if not found_final:
  1008. all_nonfinal.append(item)
  1009. # No finals found - yield all buffered items
  1010. if not found_final:
  1011. yield from all_nonfinal
  1012. def _version_split(version: str) -> list[str]:
  1013. """Split version into components.
  1014. The split components are intended for version comparison. The logic does
  1015. not attempt to retain the original version string, so joining the
  1016. components back with :func:`_version_join` may not produce the original
  1017. version string.
  1018. """
  1019. result: list[str] = []
  1020. epoch, _, rest = version.rpartition("!")
  1021. result.append(epoch or "0")
  1022. for item in rest.split("."):
  1023. match = _prefix_regex.fullmatch(item)
  1024. if match:
  1025. result.extend(match.groups())
  1026. else:
  1027. result.append(item)
  1028. return result
  1029. def _version_join(components: list[str]) -> str:
  1030. """Join split version components into a version string.
  1031. This function assumes the input came from :func:`_version_split`, where the
  1032. first component must be the epoch (either empty or numeric), and all other
  1033. components numeric.
  1034. """
  1035. epoch, *rest = components
  1036. return f"{epoch}!{'.'.join(rest)}"
  1037. def _is_not_suffix(segment: str) -> bool:
  1038. return not any(
  1039. segment.startswith(prefix) for prefix in ("dev", "a", "b", "rc", "post")
  1040. )
  1041. def _numeric_prefix_len(split: list[str]) -> int:
  1042. """Count leading numeric components in a :func:`_version_split` result.
  1043. >>> _numeric_prefix_len(["0", "1", "2", "a1"])
  1044. 3
  1045. """
  1046. count = 0
  1047. for segment in split:
  1048. if not segment.isdigit():
  1049. break
  1050. count += 1
  1051. return count
  1052. def _left_pad(split: list[str], target_numeric_len: int) -> list[str]:
  1053. """Pad a :func:`_version_split` result with ``"0"`` segments to reach
  1054. ``target_numeric_len`` numeric components. Suffix segments are preserved.
  1055. >>> _left_pad(["0", "1", "a1"], 4)
  1056. ['0', '1', '0', '0', 'a1']
  1057. """
  1058. numeric_len = _numeric_prefix_len(split)
  1059. pad_needed = target_numeric_len - numeric_len
  1060. if pad_needed <= 0:
  1061. return split
  1062. return [*split[:numeric_len], *(["0"] * pad_needed), *split[numeric_len:]]
  1063. def _operator_cost(op_entry: tuple[CallableOperator, str, str]) -> int:
  1064. """Sort key for Cost Based Ordering of specifier operators in _filter_versions.
  1065. Operators run sequentially on a shrinking candidate set, so operators that
  1066. reject the most versions should run first to minimize work for later ones.
  1067. Tier 0: Exact equality (==, ===), likely to narrow candidates to one version
  1068. Tier 1: Range checks (>=, <=, >, <), cheap and usually reject a large portion
  1069. Tier 2: Wildcard equality (==.*) and compatible release (~=), more expensive
  1070. Tier 3: Exact !=, cheap but rarely rejects
  1071. Tier 4: Wildcard !=.*, expensive and rarely rejects
  1072. """
  1073. _, ver, op = op_entry
  1074. if op == "==":
  1075. return 0 if not ver.endswith(".*") else 2
  1076. if op in (">=", "<=", ">", "<"):
  1077. return 1
  1078. if op == "~=":
  1079. return 2
  1080. if op == "!=":
  1081. return 3 if not ver.endswith(".*") else 4
  1082. if op == "===":
  1083. return 0
  1084. raise ValueError(f"Unknown operator: {op!r}") # pragma: no cover
  1085. class SpecifierSet(BaseSpecifier):
  1086. """This class abstracts handling of a set of version specifiers.
  1087. It can be passed a single specifier (``>=3.0``), a comma-separated list of
  1088. specifiers (``>=3.0,!=3.1``), or no specifier at all.
  1089. Instances are safe to serialize with :mod:`pickle`. They use a stable
  1090. format so the same pickle can be loaded in future packaging
  1091. releases.
  1092. .. versionchanged:: 26.2
  1093. Added a stable pickle format. Pickles created with
  1094. packaging 26.2+ can be unpickled with future releases.
  1095. Backward compatibility with pickles from
  1096. packaging < 26.2 is supported but may be removed in a future
  1097. release.
  1098. """
  1099. __slots__ = (
  1100. "_canonicalized",
  1101. "_has_arbitrary",
  1102. "_is_unsatisfiable",
  1103. "_prereleases",
  1104. "_resolved_ops",
  1105. "_specs",
  1106. )
  1107. def __init__(
  1108. self,
  1109. specifiers: str | Iterable[Specifier] = "",
  1110. prereleases: bool | None = None,
  1111. ) -> None:
  1112. """Initialize a SpecifierSet instance.
  1113. :param specifiers:
  1114. The string representation of a specifier or a comma-separated list of
  1115. specifiers which will be parsed and normalized before use.
  1116. May also be an iterable of ``Specifier`` instances, which will be used
  1117. as is.
  1118. :param prereleases:
  1119. This tells the SpecifierSet if it should accept prerelease versions if
  1120. applicable or not. The default of ``None`` will autodetect it from the
  1121. given specifiers.
  1122. :raises InvalidSpecifier:
  1123. If the given ``specifiers`` are not parseable than this exception will be
  1124. raised.
  1125. """
  1126. if isinstance(specifiers, str):
  1127. # Split on `,` to break each individual specifier into its own item, and
  1128. # strip each item to remove leading/trailing whitespace.
  1129. split_specifiers = [s.strip() for s in specifiers.split(",") if s.strip()]
  1130. self._specs: tuple[Specifier, ...] = tuple(map(Specifier, split_specifiers))
  1131. # Fast substring check; avoids iterating parsed specs.
  1132. self._has_arbitrary = "===" in specifiers
  1133. else:
  1134. self._specs = tuple(specifiers)
  1135. # Substring check works for both Specifier objects and plain
  1136. # strings (setuptools passes lists of strings).
  1137. self._has_arbitrary = any("===" in str(s) for s in self._specs)
  1138. self._canonicalized = len(self._specs) <= 1
  1139. self._resolved_ops: list[tuple[CallableOperator, str, str]] | None = None
  1140. # Store our prereleases value so we can use it later to determine if
  1141. # we accept prereleases or not.
  1142. self._prereleases = prereleases
  1143. self._is_unsatisfiable: bool | None = None
  1144. def _canonical_specs(self) -> tuple[Specifier, ...]:
  1145. """Deduplicate, sort, and cache specs for order-sensitive operations."""
  1146. if not self._canonicalized:
  1147. self._specs = tuple(dict.fromkeys(sorted(self._specs, key=str)))
  1148. self._canonicalized = True
  1149. self._resolved_ops = None
  1150. self._is_unsatisfiable = None
  1151. return self._specs
  1152. @property
  1153. def prereleases(self) -> bool | None:
  1154. # If we have been given an explicit prerelease modifier, then we'll
  1155. # pass that through here.
  1156. if self._prereleases is not None:
  1157. return self._prereleases
  1158. # If we don't have any specifiers, and we don't have a forced value,
  1159. # then we'll just return None since we don't know if this should have
  1160. # pre-releases or not.
  1161. if not self._specs:
  1162. return None
  1163. # Otherwise we'll see if any of the given specifiers accept
  1164. # prereleases, if any of them do we'll return True, otherwise False.
  1165. if any(s.prereleases for s in self._specs):
  1166. return True
  1167. return None
  1168. @prereleases.setter
  1169. def prereleases(self, value: bool | None) -> None:
  1170. self._prereleases = value
  1171. self._is_unsatisfiable = None
  1172. def __getstate__(self) -> tuple[tuple[Specifier, ...], bool | None]:
  1173. # Return state as a 2-item tuple for compactness:
  1174. # (specs, prereleases)
  1175. # Cache members are excluded and will be recomputed on demand.
  1176. return (self._specs, self._prereleases)
  1177. def __setstate__(self, state: object) -> None:
  1178. # Always discard cached values - they will be recomputed on demand.
  1179. self._resolved_ops = None
  1180. self._is_unsatisfiable = None
  1181. if isinstance(state, tuple):
  1182. if len(state) == 2:
  1183. # New format (26.2+): (specs, prereleases)
  1184. specs, prereleases = state
  1185. if (
  1186. isinstance(specs, tuple)
  1187. and all(isinstance(s, Specifier) for s in specs)
  1188. and _validate_pre(prereleases)
  1189. ):
  1190. self._specs = specs
  1191. self._prereleases = prereleases
  1192. self._canonicalized = len(specs) <= 1
  1193. self._has_arbitrary = any("===" in str(s) for s in specs)
  1194. return
  1195. if len(state) == 2 and isinstance(state[1], dict):
  1196. # Format (packaging 26.0-26.1): (None, {slot: value}).
  1197. _, slot_dict = state
  1198. specs = slot_dict.get("_specs", ())
  1199. prereleases = slot_dict.get("_prereleases")
  1200. # Convert frozenset to tuple (26.0 stored as frozenset)
  1201. if isinstance(specs, frozenset):
  1202. specs = tuple(sorted(specs, key=str))
  1203. if (
  1204. isinstance(specs, tuple)
  1205. and all(isinstance(s, Specifier) for s in specs)
  1206. and _validate_pre(prereleases)
  1207. ):
  1208. self._specs = specs
  1209. self._prereleases = prereleases
  1210. self._canonicalized = len(self._specs) <= 1
  1211. self._has_arbitrary = any("===" in str(s) for s in self._specs)
  1212. return
  1213. if isinstance(state, dict):
  1214. # Old format (packaging <= 25.x, no __slots__): state is a plain dict.
  1215. specs = state.get("_specs", ())
  1216. prereleases = state.get("_prereleases")
  1217. # Convert frozenset to tuple (26.0 stored as frozenset)
  1218. if isinstance(specs, frozenset):
  1219. specs = tuple(sorted(specs, key=str))
  1220. if (
  1221. isinstance(specs, tuple)
  1222. and all(isinstance(s, Specifier) for s in specs)
  1223. and _validate_pre(prereleases)
  1224. ):
  1225. self._specs = specs
  1226. self._prereleases = prereleases
  1227. self._canonicalized = len(self._specs) <= 1
  1228. self._has_arbitrary = any("===" in str(s) for s in self._specs)
  1229. return
  1230. raise TypeError(f"Cannot restore SpecifierSet from {state!r}")
  1231. def __repr__(self) -> str:
  1232. """A representation of the specifier set that shows all internal state.
  1233. Note that the ordering of the individual specifiers within the set may not
  1234. match the input string.
  1235. >>> SpecifierSet('>=1.0.0,!=2.0.0')
  1236. <SpecifierSet('!=2.0.0,>=1.0.0')>
  1237. >>> SpecifierSet('>=1.0.0,!=2.0.0', prereleases=False)
  1238. <SpecifierSet('!=2.0.0,>=1.0.0', prereleases=False)>
  1239. >>> SpecifierSet('>=1.0.0,!=2.0.0', prereleases=True)
  1240. <SpecifierSet('!=2.0.0,>=1.0.0', prereleases=True)>
  1241. """
  1242. pre = (
  1243. f", prereleases={self.prereleases!r}"
  1244. if self._prereleases is not None
  1245. else ""
  1246. )
  1247. return f"<{self.__class__.__name__}({str(self)!r}{pre})>"
  1248. def __str__(self) -> str:
  1249. """A string representation of the specifier set that can be round-tripped.
  1250. Note that the ordering of the individual specifiers within the set may not
  1251. match the input string.
  1252. >>> str(SpecifierSet(">=1.0.0,!=1.0.1"))
  1253. '!=1.0.1,>=1.0.0'
  1254. >>> str(SpecifierSet(">=1.0.0,!=1.0.1", prereleases=False))
  1255. '!=1.0.1,>=1.0.0'
  1256. """
  1257. return ",".join(str(s) for s in self._canonical_specs())
  1258. def __hash__(self) -> int:
  1259. return hash(self._canonical_specs())
  1260. def __and__(self, other: SpecifierSet | str) -> SpecifierSet:
  1261. """Return a SpecifierSet which is a combination of the two sets.
  1262. :param other: The other object to combine with.
  1263. >>> SpecifierSet(">=1.0.0,!=1.0.1") & '<=2.0.0,!=2.0.1'
  1264. <SpecifierSet('!=1.0.1,!=2.0.1,<=2.0.0,>=1.0.0')>
  1265. >>> SpecifierSet(">=1.0.0,!=1.0.1") & SpecifierSet('<=2.0.0,!=2.0.1')
  1266. <SpecifierSet('!=1.0.1,!=2.0.1,<=2.0.0,>=1.0.0')>
  1267. """
  1268. if isinstance(other, str):
  1269. other = SpecifierSet(other)
  1270. elif not isinstance(other, SpecifierSet):
  1271. return NotImplemented
  1272. specifier = SpecifierSet()
  1273. specifier._specs = self._specs + other._specs
  1274. specifier._canonicalized = len(specifier._specs) <= 1
  1275. specifier._has_arbitrary = self._has_arbitrary or other._has_arbitrary
  1276. specifier._resolved_ops = None
  1277. # Combine prerelease settings: use common or non-None value
  1278. if self._prereleases is None or self._prereleases == other._prereleases:
  1279. specifier._prereleases = other._prereleases
  1280. elif other._prereleases is None:
  1281. specifier._prereleases = self._prereleases
  1282. else:
  1283. raise ValueError(
  1284. "Cannot combine SpecifierSets with True and False prerelease overrides."
  1285. )
  1286. return specifier
  1287. def __eq__(self, other: object) -> bool:
  1288. """Whether or not the two SpecifierSet-like objects are equal.
  1289. :param other: The other object to check against.
  1290. The value of :attr:`prereleases` is ignored.
  1291. >>> SpecifierSet(">=1.0.0,!=1.0.1") == SpecifierSet(">=1.0.0,!=1.0.1")
  1292. True
  1293. >>> (SpecifierSet(">=1.0.0,!=1.0.1", prereleases=False) ==
  1294. ... SpecifierSet(">=1.0.0,!=1.0.1", prereleases=True))
  1295. True
  1296. >>> SpecifierSet(">=1.0.0,!=1.0.1") == ">=1.0.0,!=1.0.1"
  1297. True
  1298. >>> SpecifierSet(">=1.0.0,!=1.0.1") == SpecifierSet(">=1.0.0")
  1299. False
  1300. >>> SpecifierSet(">=1.0.0,!=1.0.1") == SpecifierSet(">=1.0.0,!=1.0.2")
  1301. False
  1302. """
  1303. if isinstance(other, (str, Specifier)):
  1304. other = SpecifierSet(str(other))
  1305. elif not isinstance(other, SpecifierSet):
  1306. return NotImplemented
  1307. return self._canonical_specs() == other._canonical_specs()
  1308. def __len__(self) -> int:
  1309. """Returns the number of specifiers in this specifier set."""
  1310. return len(self._specs)
  1311. def __iter__(self) -> Iterator[Specifier]:
  1312. """
  1313. Returns an iterator over all the underlying :class:`Specifier` instances
  1314. in this specifier set.
  1315. >>> sorted(SpecifierSet(">=1.0.0,!=1.0.1"), key=str)
  1316. [<Specifier('!=1.0.1')>, <Specifier('>=1.0.0')>]
  1317. """
  1318. return iter(self._specs)
  1319. def _get_ranges(self) -> Sequence[_VersionRange]:
  1320. """Intersect all specifiers into a single list of version ranges.
  1321. Returns an empty list when unsatisfiable. ``===`` specs are
  1322. modeled as full range; string matching is checked separately
  1323. by :meth:`_check_arbitrary_unsatisfiable`.
  1324. """
  1325. specs = self._specs
  1326. result: Sequence[_VersionRange] | None = None
  1327. for s in specs:
  1328. if result is None:
  1329. result = s._to_ranges()
  1330. else:
  1331. result = _intersect_ranges(result, s._to_ranges())
  1332. if not result:
  1333. break
  1334. if result is None: # pragma: no cover
  1335. raise RuntimeError("_get_ranges called with no specs")
  1336. return result
  1337. def is_unsatisfiable(self) -> bool:
  1338. """Check whether this specifier set can never be satisfied.
  1339. Returns True if no version can satisfy all specifiers simultaneously.
  1340. >>> SpecifierSet(">=2.0,<1.0").is_unsatisfiable()
  1341. True
  1342. >>> SpecifierSet(">=1.0,<2.0").is_unsatisfiable()
  1343. False
  1344. >>> SpecifierSet("").is_unsatisfiable()
  1345. False
  1346. >>> SpecifierSet("==1.0,!=1.0").is_unsatisfiable()
  1347. True
  1348. """
  1349. cached = self._is_unsatisfiable
  1350. if cached is not None:
  1351. return cached
  1352. if not self._specs:
  1353. self._is_unsatisfiable = False
  1354. return False
  1355. result = not self._get_ranges()
  1356. if not result:
  1357. result = self._check_arbitrary_unsatisfiable()
  1358. if not result and self.prereleases is False:
  1359. result = self._check_prerelease_only_ranges()
  1360. self._is_unsatisfiable = result
  1361. return result
  1362. def _check_prerelease_only_ranges(self) -> bool:
  1363. """With prereleases=False, check if every range contains only
  1364. pre-release versions (which would be excluded from matching)."""
  1365. for lower, upper in self._get_ranges():
  1366. nearest = _nearest_non_prerelease(lower.version)
  1367. if nearest is None:
  1368. return False
  1369. if upper.version is None or nearest < upper.version:
  1370. return False
  1371. if nearest == upper.version and upper.inclusive:
  1372. return False
  1373. return True
  1374. def _check_arbitrary_unsatisfiable(self) -> bool:
  1375. """Check === (arbitrary equality) specs for unsatisfiability.
  1376. === uses case-insensitive string comparison, so the only candidate
  1377. that can match ``===V`` is the literal string V. This method
  1378. checks whether that candidate is excluded by other specifiers.
  1379. """
  1380. arbitrary = [s for s in self._specs if s.operator == "==="]
  1381. if not arbitrary:
  1382. return False
  1383. # Multiple === must agree on the same string (case-insensitive).
  1384. first = arbitrary[0].version.lower()
  1385. if any(s.version.lower() != first for s in arbitrary[1:]):
  1386. return True
  1387. # The sole candidate is the === version string. Check whether
  1388. # it can satisfy every standard spec.
  1389. candidate = _coerce_version(arbitrary[0].version)
  1390. # With prereleases=False, a prerelease candidate is excluded
  1391. # by contains() before the === string check even runs.
  1392. if (
  1393. self.prereleases is False
  1394. and candidate is not None
  1395. and candidate.is_prerelease
  1396. ):
  1397. return True
  1398. standard = [s for s in self._specs if s.operator != "==="]
  1399. if not standard:
  1400. return False
  1401. if candidate is None:
  1402. # Unparsable string cannot satisfy any standard spec.
  1403. return True
  1404. return not all(s.contains(candidate) for s in standard)
  1405. def __contains__(self, item: UnparsedVersion) -> bool:
  1406. """Return whether or not the item is contained in this specifier.
  1407. :param item: The item to check for.
  1408. This is used for the ``in`` operator and behaves the same as
  1409. :meth:`contains` with no ``prereleases`` argument passed.
  1410. >>> "1.2.3" in SpecifierSet(">=1.0.0,!=1.0.1")
  1411. True
  1412. >>> Version("1.2.3") in SpecifierSet(">=1.0.0,!=1.0.1")
  1413. True
  1414. >>> "1.0.1" in SpecifierSet(">=1.0.0,!=1.0.1")
  1415. False
  1416. >>> "1.3.0a1" in SpecifierSet(">=1.0.0,!=1.0.1")
  1417. True
  1418. >>> "1.3.0a1" in SpecifierSet(">=1.0.0,!=1.0.1", prereleases=True)
  1419. True
  1420. """
  1421. return self.contains(item)
  1422. def contains(
  1423. self,
  1424. item: UnparsedVersion,
  1425. prereleases: bool | None = None,
  1426. installed: bool | None = None,
  1427. ) -> bool:
  1428. """Return whether or not the item is contained in this SpecifierSet.
  1429. :param item:
  1430. The item to check for, which can be a version string or a
  1431. :class:`Version` instance.
  1432. :param prereleases:
  1433. Whether or not to match prereleases with this SpecifierSet. If set to
  1434. ``None`` (the default), it will follow the recommendation from :pep:`440`
  1435. and match prereleases, as there are no other versions.
  1436. :param installed:
  1437. Whether or not the item is installed. If set to ``True``, it will
  1438. accept prerelease versions even if the specifier does not allow them.
  1439. >>> SpecifierSet(">=1.0.0,!=1.0.1").contains("1.2.3")
  1440. True
  1441. >>> SpecifierSet(">=1.0.0,!=1.0.1").contains(Version("1.2.3"))
  1442. True
  1443. >>> SpecifierSet(">=1.0.0,!=1.0.1").contains("1.0.1")
  1444. False
  1445. >>> SpecifierSet(">=1.0.0,!=1.0.1").contains("1.3.0a1")
  1446. True
  1447. >>> SpecifierSet(">=1.0.0,!=1.0.1", prereleases=False).contains("1.3.0a1")
  1448. False
  1449. >>> SpecifierSet(">=1.0.0,!=1.0.1").contains("1.3.0a1", prereleases=True)
  1450. True
  1451. """
  1452. version = _coerce_version(item)
  1453. if version is not None and installed and version.is_prerelease:
  1454. prereleases = True
  1455. # When item is a string and === is involved, keep it as-is
  1456. # so the comparison isn't done against the normalized form.
  1457. if version is None or (self._has_arbitrary and not isinstance(item, Version)):
  1458. check_item = item
  1459. else:
  1460. check_item = version
  1461. return bool(list(self.filter([check_item], prereleases=prereleases)))
  1462. @typing.overload
  1463. def filter(
  1464. self,
  1465. iterable: Iterable[UnparsedVersionVar],
  1466. prereleases: bool | None = None,
  1467. key: None = ...,
  1468. ) -> Iterator[UnparsedVersionVar]: ...
  1469. @typing.overload
  1470. def filter(
  1471. self,
  1472. iterable: Iterable[T],
  1473. prereleases: bool | None = None,
  1474. key: Callable[[T], UnparsedVersion] = ...,
  1475. ) -> Iterator[T]: ...
  1476. def filter(
  1477. self,
  1478. iterable: Iterable[Any],
  1479. prereleases: bool | None = None,
  1480. key: Callable[[Any], UnparsedVersion] | None = None,
  1481. ) -> Iterator[Any]:
  1482. """Filter items in the given iterable, that match the specifiers in this set.
  1483. :param iterable:
  1484. An iterable that can contain version strings and :class:`Version` instances.
  1485. The items in the iterable will be filtered according to the specifier.
  1486. :param prereleases:
  1487. Whether or not to allow prereleases in the returned iterator. If set to
  1488. ``None`` (the default), it will follow the recommendation from :pep:`440`
  1489. and match prereleases if there are no other versions.
  1490. :param key:
  1491. A callable that takes a single argument (an item from the iterable) and
  1492. returns a version string or :class:`Version` instance to be used for
  1493. filtering.
  1494. >>> list(SpecifierSet(">=1.2.3").filter(["1.2", "1.3", "1.5a1"]))
  1495. ['1.3']
  1496. >>> list(SpecifierSet(">=1.2.3").filter(["1.2", "1.3", Version("1.4")]))
  1497. ['1.3', <Version('1.4')>]
  1498. >>> list(SpecifierSet(">=1.2.3").filter(["1.2", "1.5a1"]))
  1499. ['1.5a1']
  1500. >>> list(SpecifierSet(">=1.2.3").filter(["1.3", "1.5a1"], prereleases=True))
  1501. ['1.3', '1.5a1']
  1502. >>> list(SpecifierSet(">=1.2.3", prereleases=True).filter(["1.3", "1.5a1"]))
  1503. ['1.3', '1.5a1']
  1504. >>> list(SpecifierSet(">=1.2.3").filter(
  1505. ... [{"ver": "1.2"}, {"ver": "1.3"}],
  1506. ... key=lambda x: x["ver"]))
  1507. [{'ver': '1.3'}]
  1508. An "empty" SpecifierSet will filter items based on the presence of prerelease
  1509. versions in the set.
  1510. >>> list(SpecifierSet("").filter(["1.3", "1.5a1"]))
  1511. ['1.3']
  1512. >>> list(SpecifierSet("").filter(["1.5a1"]))
  1513. ['1.5a1']
  1514. >>> list(SpecifierSet("", prereleases=True).filter(["1.3", "1.5a1"]))
  1515. ['1.3', '1.5a1']
  1516. >>> list(SpecifierSet("").filter(["1.3", "1.5a1"], prereleases=True))
  1517. ['1.3', '1.5a1']
  1518. """
  1519. # Determine if we're forcing a prerelease or not, if we're not forcing
  1520. # one for this particular filter call, then we'll use whatever the
  1521. # SpecifierSet thinks for whether or not we should support prereleases.
  1522. if prereleases is None and self.prereleases is not None:
  1523. prereleases = self.prereleases
  1524. # Filter versions that match all specifiers using Cost Based Ordering.
  1525. if self._specs:
  1526. # When prereleases is None, we need to let all versions through
  1527. # the individual filters, then decide about prereleases at the end
  1528. # based on whether any non-prereleases matched ALL specs.
  1529. # Fast path: single specifier, delegate directly.
  1530. if len(self._specs) == 1:
  1531. filtered = self._specs[0].filter(
  1532. iterable,
  1533. prereleases=True if prereleases is None else prereleases,
  1534. key=key,
  1535. )
  1536. else:
  1537. filtered = self._filter_versions(
  1538. iterable,
  1539. key,
  1540. prereleases=True if prereleases is None else prereleases,
  1541. )
  1542. if prereleases is not None:
  1543. return filtered
  1544. return _pep440_filter_prereleases(filtered, key)
  1545. # Handle Empty SpecifierSet.
  1546. if prereleases is True:
  1547. return iter(iterable)
  1548. if prereleases is False:
  1549. return (
  1550. item
  1551. for item in iterable
  1552. if (
  1553. (version := _coerce_version(item if key is None else key(item)))
  1554. is None
  1555. or not version.is_prerelease
  1556. )
  1557. )
  1558. # PEP 440: exclude prereleases unless no final releases matched
  1559. return _pep440_filter_prereleases(iterable, key)
  1560. def _filter_versions(
  1561. self,
  1562. iterable: Iterable[Any],
  1563. key: Callable[[Any], UnparsedVersion] | None,
  1564. prereleases: bool | None = None,
  1565. ) -> Iterator[Any]:
  1566. """Filter versions against all specifiers in a single pass.
  1567. Uses Cost Based Ordering: specifiers are sorted by _operator_cost so
  1568. that cheap range operators reject versions early, avoiding expensive
  1569. wildcard or compatible operators on versions that would have been
  1570. rejected anyway.
  1571. """
  1572. # Pre-resolve operators and sort (cached after first call).
  1573. if self._resolved_ops is None:
  1574. self._resolved_ops = sorted(
  1575. (
  1576. (spec._get_operator(spec.operator), spec.version, spec.operator)
  1577. for spec in self._specs
  1578. ),
  1579. key=_operator_cost,
  1580. )
  1581. ops = self._resolved_ops
  1582. exclude_prereleases = prereleases is False
  1583. for item in iterable:
  1584. parsed = _coerce_version(item if key is None else key(item))
  1585. if parsed is None:
  1586. # Only === can match non-parseable versions.
  1587. if all(
  1588. op == "===" and str(item).lower() == ver.lower()
  1589. for _, ver, op in ops
  1590. ):
  1591. yield item
  1592. elif exclude_prereleases and parsed.is_prerelease:
  1593. pass
  1594. elif all(
  1595. str(item if key is None else key(item)).lower() == ver.lower()
  1596. if op == "==="
  1597. else op_fn(parsed, ver)
  1598. for op_fn, ver, op in ops
  1599. ):
  1600. # Short-circuits on the first failing operator.
  1601. yield item