specifiers.py 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772
  1. # Copyright 2014 Donald Stufft
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. from __future__ import absolute_import, division, print_function
  15. import abc
  16. import functools
  17. import itertools
  18. import re
  19. from ._compat import string_types, with_metaclass
  20. from .version import Version, LegacyVersion, parse
  21. class InvalidSpecifier(ValueError):
  22. """
  23. An invalid specifier was found, users should refer to PEP 440.
  24. """
  25. class BaseSpecifier(with_metaclass(abc.ABCMeta, object)):
  26. @abc.abstractmethod
  27. def __str__(self):
  28. """
  29. Returns the str representation of this Specifier like object. This
  30. should be representative of the Specifier itself.
  31. """
  32. @abc.abstractmethod
  33. def __hash__(self):
  34. """
  35. Returns a hash value for this Specifier like object.
  36. """
  37. @abc.abstractmethod
  38. def __eq__(self, other):
  39. """
  40. Returns a boolean representing whether or not the two Specifier like
  41. objects are equal.
  42. """
  43. @abc.abstractmethod
  44. def __ne__(self, other):
  45. """
  46. Returns a boolean representing whether or not the two Specifier like
  47. objects are not equal.
  48. """
  49. @abc.abstractproperty
  50. def prereleases(self):
  51. """
  52. Returns whether or not pre-releases as a whole are allowed by this
  53. specifier.
  54. """
  55. @prereleases.setter
  56. def prereleases(self, value):
  57. """
  58. Sets whether or not pre-releases as a whole are allowed by this
  59. specifier.
  60. """
  61. @abc.abstractmethod
  62. def contains(self, item, prereleases=None):
  63. """
  64. Determines if the given item is contained within this specifier.
  65. """
  66. @abc.abstractmethod
  67. def filter(self, iterable, prereleases=None):
  68. """
  69. Takes an iterable of items and filters them so that only items which
  70. are contained within this specifier are allowed in it.
  71. """
  72. class _IndividualSpecifier(BaseSpecifier):
  73. _operators = {}
  74. def __init__(self, spec="", prereleases=None):
  75. match = self._regex.search(spec)
  76. if not match:
  77. raise InvalidSpecifier("Invalid specifier: '{0}'".format(spec))
  78. self._spec = (
  79. match.group("operator").strip(),
  80. match.group("version").strip(),
  81. )
  82. # Store whether or not this Specifier should accept prereleases
  83. self._prereleases = prereleases
  84. def __repr__(self):
  85. pre = (
  86. ", prereleases={0!r}".format(self.prereleases)
  87. if self._prereleases is not None
  88. else ""
  89. )
  90. return "<{0}({1!r}{2})>".format(
  91. self.__class__.__name__,
  92. str(self),
  93. pre,
  94. )
  95. def __str__(self):
  96. return "{0}{1}".format(*self._spec)
  97. def __hash__(self):
  98. return hash(self._spec)
  99. def __eq__(self, other):
  100. if isinstance(other, string_types):
  101. try:
  102. other = self.__class__(other)
  103. except InvalidSpecifier:
  104. return NotImplemented
  105. elif not isinstance(other, self.__class__):
  106. return NotImplemented
  107. return self._spec == other._spec
  108. def __ne__(self, other):
  109. if isinstance(other, string_types):
  110. try:
  111. other = self.__class__(other)
  112. except InvalidSpecifier:
  113. return NotImplemented
  114. elif not isinstance(other, self.__class__):
  115. return NotImplemented
  116. return self._spec != other._spec
  117. def _get_operator(self, op):
  118. return getattr(self, "_compare_{0}".format(self._operators[op]))
  119. def _coerce_version(self, version):
  120. if not isinstance(version, (LegacyVersion, Version)):
  121. version = parse(version)
  122. return version
  123. @property
  124. def prereleases(self):
  125. return self._prereleases
  126. @prereleases.setter
  127. def prereleases(self, value):
  128. self._prereleases = value
  129. def contains(self, item, prereleases=None):
  130. # Determine if prereleases are to be allowed or not.
  131. if prereleases is None:
  132. prereleases = self.prereleases
  133. # Normalize item to a Version or LegacyVersion, this allows us to have
  134. # a shortcut for ``"2.0" in Specifier(">=2")
  135. item = self._coerce_version(item)
  136. # Determine if we should be supporting prereleases in this specifier
  137. # or not, if we do not support prereleases than we can short circuit
  138. # logic if this version is a prereleases.
  139. if item.is_prerelease and not prereleases:
  140. return False
  141. # Actually do the comparison to determine if this item is contained
  142. # within this Specifier or not.
  143. return self._get_operator(self._spec[0])(item, self._spec[1])
  144. def filter(self, iterable, prereleases=None):
  145. yielded = False
  146. found_prereleases = []
  147. kw = {"prereleases": prereleases if prereleases is not None else True}
  148. # Attempt to iterate over all the values in the iterable and if any of
  149. # them match, yield them.
  150. for version in iterable:
  151. parsed_version = self._coerce_version(version)
  152. if self.contains(parsed_version, **kw):
  153. # If our version is a prerelease, and we were not set to allow
  154. # prereleases, then we'll store it for later incase nothing
  155. # else matches this specifier.
  156. if (parsed_version.is_prerelease
  157. and not (prereleases or self.prereleases)):
  158. found_prereleases.append(version)
  159. # Either this is not a prerelease, or we should have been
  160. # accepting prereleases from the begining.
  161. else:
  162. yielded = True
  163. yield version
  164. # Now that we've iterated over everything, determine if we've yielded
  165. # any values, and if we have not and we have any prereleases stored up
  166. # then we will go ahead and yield the prereleases.
  167. if not yielded and found_prereleases:
  168. for version in found_prereleases:
  169. yield version
  170. class LegacySpecifier(_IndividualSpecifier):
  171. _regex = re.compile(
  172. r"""
  173. ^
  174. \s*
  175. (?P<operator>(==|!=|<=|>=|<|>))
  176. \s*
  177. (?P<version>
  178. [^\s]* # We just match everything, except for whitespace since this
  179. # is a "legacy" specifier and the version string can be just
  180. # about anything.
  181. )
  182. \s*
  183. $
  184. """,
  185. re.VERBOSE | re.IGNORECASE,
  186. )
  187. _operators = {
  188. "==": "equal",
  189. "!=": "not_equal",
  190. "<=": "less_than_equal",
  191. ">=": "greater_than_equal",
  192. "<": "less_than",
  193. ">": "greater_than",
  194. }
  195. def _coerce_version(self, version):
  196. if not isinstance(version, LegacyVersion):
  197. version = LegacyVersion(str(version))
  198. return version
  199. def _compare_equal(self, prospective, spec):
  200. return prospective == self._coerce_version(spec)
  201. def _compare_not_equal(self, prospective, spec):
  202. return prospective != self._coerce_version(spec)
  203. def _compare_less_than_equal(self, prospective, spec):
  204. return prospective <= self._coerce_version(spec)
  205. def _compare_greater_than_equal(self, prospective, spec):
  206. return prospective >= self._coerce_version(spec)
  207. def _compare_less_than(self, prospective, spec):
  208. return prospective < self._coerce_version(spec)
  209. def _compare_greater_than(self, prospective, spec):
  210. return prospective > self._coerce_version(spec)
  211. def _require_version_compare(fn):
  212. @functools.wraps(fn)
  213. def wrapped(self, prospective, spec):
  214. if not isinstance(prospective, Version):
  215. return False
  216. return fn(self, prospective, spec)
  217. return wrapped
  218. class Specifier(_IndividualSpecifier):
  219. _regex = re.compile(
  220. r"""
  221. ^
  222. \s*
  223. (?P<operator>(~=|==|!=|<=|>=|<|>|===))
  224. (?P<version>
  225. (?:
  226. # The identity operators allow for an escape hatch that will
  227. # do an exact string match of the version you wish to install.
  228. # This will not be parsed by PEP 440 and we cannot determine
  229. # any semantic meaning from it. This operator is discouraged
  230. # but included entirely as an escape hatch.
  231. (?<====) # Only match for the identity operator
  232. \s*
  233. [^\s]* # We just match everything, except for whitespace
  234. # since we are only testing for strict identity.
  235. )
  236. |
  237. (?:
  238. # The (non)equality operators allow for wild card and local
  239. # versions to be specified so we have to define these two
  240. # operators separately to enable that.
  241. (?<===|!=) # Only match for equals and not equals
  242. \s*
  243. v?
  244. (?:[0-9]+!)? # epoch
  245. [0-9]+(?:\.[0-9]+)* # release
  246. (?: # pre release
  247. [-_\.]?
  248. (a|b|c|rc|alpha|beta|pre|preview)
  249. [-_\.]?
  250. [0-9]*
  251. )?
  252. (?: # post release
  253. (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*)
  254. )?
  255. # You cannot use a wild card and a dev or local version
  256. # together so group them with a | and make them optional.
  257. (?:
  258. (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release
  259. (?:\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*)? # local
  260. |
  261. \.\* # Wild card syntax of .*
  262. )?
  263. )
  264. |
  265. (?:
  266. # The compatible operator requires at least two digits in the
  267. # release segment.
  268. (?<=~=) # Only match for the compatible operator
  269. \s*
  270. v?
  271. (?:[0-9]+!)? # epoch
  272. [0-9]+(?:\.[0-9]+)+ # release (We have a + instead of a *)
  273. (?: # pre release
  274. [-_\.]?
  275. (a|b|c|rc|alpha|beta|pre|preview)
  276. [-_\.]?
  277. [0-9]*
  278. )?
  279. (?: # post release
  280. (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*)
  281. )?
  282. (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release
  283. )
  284. |
  285. (?:
  286. # All other operators only allow a sub set of what the
  287. # (non)equality operators do. Specifically they do not allow
  288. # local versions to be specified nor do they allow the prefix
  289. # matching wild cards.
  290. (?<!==|!=|~=) # We have special cases for these
  291. # operators so we want to make sure they
  292. # don't match here.
  293. \s*
  294. v?
  295. (?:[0-9]+!)? # epoch
  296. [0-9]+(?:\.[0-9]+)* # release
  297. (?: # pre release
  298. [-_\.]?
  299. (a|b|c|rc|alpha|beta|pre|preview)
  300. [-_\.]?
  301. [0-9]*
  302. )?
  303. (?: # post release
  304. (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*)
  305. )?
  306. (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release
  307. )
  308. )
  309. \s*
  310. $
  311. """,
  312. re.VERBOSE | re.IGNORECASE,
  313. )
  314. _operators = {
  315. "~=": "compatible",
  316. "==": "equal",
  317. "!=": "not_equal",
  318. "<=": "less_than_equal",
  319. ">=": "greater_than_equal",
  320. "<": "less_than",
  321. ">": "greater_than",
  322. "===": "arbitrary",
  323. }
  324. @_require_version_compare
  325. def _compare_compatible(self, prospective, spec):
  326. # Compatible releases have an equivalent combination of >= and ==. That
  327. # is that ~=2.2 is equivalent to >=2.2,==2.*. This allows us to
  328. # implement this in terms of the other specifiers instead of
  329. # implementing it ourselves. The only thing we need to do is construct
  330. # the other specifiers.
  331. # We want everything but the last item in the version, but we want to
  332. # ignore post and dev releases and we want to treat the pre-release as
  333. # it's own separate segment.
  334. prefix = ".".join(
  335. list(
  336. itertools.takewhile(
  337. lambda x: (not x.startswith("post")
  338. and not x.startswith("dev")),
  339. _version_split(spec),
  340. )
  341. )[:-1]
  342. )
  343. # Add the prefix notation to the end of our string
  344. prefix += ".*"
  345. return (self._get_operator(">=")(prospective, spec)
  346. and self._get_operator("==")(prospective, prefix))
  347. @_require_version_compare
  348. def _compare_equal(self, prospective, spec):
  349. # We need special logic to handle prefix matching
  350. if spec.endswith(".*"):
  351. # Split the spec out by dots, and pretend that there is an implicit
  352. # dot in between a release segment and a pre-release segment.
  353. spec = _version_split(spec[:-2]) # Remove the trailing .*
  354. # Split the prospective version out by dots, and pretend that there
  355. # is an implicit dot in between a release segment and a pre-release
  356. # segment.
  357. prospective = _version_split(str(prospective))
  358. # Shorten the prospective version to be the same length as the spec
  359. # so that we can determine if the specifier is a prefix of the
  360. # prospective version or not.
  361. prospective = prospective[:len(spec)]
  362. # Pad out our two sides with zeros so that they both equal the same
  363. # length.
  364. spec, prospective = _pad_version(spec, prospective)
  365. else:
  366. # Convert our spec string into a Version
  367. spec = Version(spec)
  368. # If the specifier does not have a local segment, then we want to
  369. # act as if the prospective version also does not have a local
  370. # segment.
  371. if not spec.local:
  372. prospective = Version(prospective.public)
  373. return prospective == spec
  374. @_require_version_compare
  375. def _compare_not_equal(self, prospective, spec):
  376. return not self._compare_equal(prospective, spec)
  377. @_require_version_compare
  378. def _compare_less_than_equal(self, prospective, spec):
  379. return prospective <= Version(spec)
  380. @_require_version_compare
  381. def _compare_greater_than_equal(self, prospective, spec):
  382. return prospective >= Version(spec)
  383. @_require_version_compare
  384. def _compare_less_than(self, prospective, spec):
  385. # Convert our spec to a Version instance, since we'll want to work with
  386. # it as a version.
  387. spec = Version(spec)
  388. # Check to see if the prospective version is less than the spec
  389. # version. If it's not we can short circuit and just return False now
  390. # instead of doing extra unneeded work.
  391. if not prospective < spec:
  392. return False
  393. # This special case is here so that, unless the specifier itself
  394. # includes is a pre-release version, that we do not accept pre-release
  395. # versions for the version mentioned in the specifier (e.g. <3.1 should
  396. # not match 3.1.dev0, but should match 3.0.dev0).
  397. if not spec.is_prerelease and prospective.is_prerelease:
  398. if Version(prospective.base_version) == Version(spec.base_version):
  399. return False
  400. # If we've gotten to here, it means that prospective version is both
  401. # less than the spec version *and* it's not a pre-release of the same
  402. # version in the spec.
  403. return True
  404. @_require_version_compare
  405. def _compare_greater_than(self, prospective, spec):
  406. # Convert our spec to a Version instance, since we'll want to work with
  407. # it as a version.
  408. spec = Version(spec)
  409. # Check to see if the prospective version is greater than the spec
  410. # version. If it's not we can short circuit and just return False now
  411. # instead of doing extra unneeded work.
  412. if not prospective > spec:
  413. return False
  414. # This special case is here so that, unless the specifier itself
  415. # includes is a post-release version, that we do not accept
  416. # post-release versions for the version mentioned in the specifier
  417. # (e.g. >3.1 should not match 3.0.post0, but should match 3.2.post0).
  418. if not spec.is_postrelease and prospective.is_postrelease:
  419. if Version(prospective.base_version) == Version(spec.base_version):
  420. return False
  421. # Ensure that we do not allow a local version of the version mentioned
  422. # in the specifier, which is techincally greater than, to match.
  423. if prospective.local is not None:
  424. if Version(prospective.base_version) == Version(spec.base_version):
  425. return False
  426. # If we've gotten to here, it means that prospective version is both
  427. # greater than the spec version *and* it's not a pre-release of the
  428. # same version in the spec.
  429. return True
  430. def _compare_arbitrary(self, prospective, spec):
  431. return str(prospective).lower() == str(spec).lower()
  432. @property
  433. def prereleases(self):
  434. # If there is an explicit prereleases set for this, then we'll just
  435. # blindly use that.
  436. if self._prereleases is not None:
  437. return self._prereleases
  438. # Look at all of our specifiers and determine if they are inclusive
  439. # operators, and if they are if they are including an explicit
  440. # prerelease.
  441. operator, version = self._spec
  442. if operator in ["==", ">=", "<=", "~="]:
  443. # The == specifier can include a trailing .*, if it does we
  444. # want to remove before parsing.
  445. if operator == "==" and version.endswith(".*"):
  446. version = version[:-2]
  447. # Parse the version, and if it is a pre-release than this
  448. # specifier allows pre-releases.
  449. if parse(version).is_prerelease:
  450. return True
  451. return False
  452. @prereleases.setter
  453. def prereleases(self, value):
  454. self._prereleases = value
  455. _prefix_regex = re.compile(r"^([0-9]+)((?:a|b|c|rc)[0-9]+)$")
  456. def _version_split(version):
  457. result = []
  458. for item in version.split("."):
  459. match = _prefix_regex.search(item)
  460. if match:
  461. result.extend(match.groups())
  462. else:
  463. result.append(item)
  464. return result
  465. def _pad_version(left, right):
  466. left_split, right_split = [], []
  467. # Get the release segment of our versions
  468. left_split.append(list(itertools.takewhile(lambda x: x.isdigit(), left)))
  469. right_split.append(list(itertools.takewhile(lambda x: x.isdigit(), right)))
  470. # Get the rest of our versions
  471. left_split.append(left[len(left_split):])
  472. right_split.append(left[len(right_split):])
  473. # Insert our padding
  474. left_split.insert(
  475. 1,
  476. ["0"] * max(0, len(right_split[0]) - len(left_split[0])),
  477. )
  478. right_split.insert(
  479. 1,
  480. ["0"] * max(0, len(left_split[0]) - len(right_split[0])),
  481. )
  482. return (
  483. list(itertools.chain(*left_split)),
  484. list(itertools.chain(*right_split)),
  485. )
  486. class SpecifierSet(BaseSpecifier):
  487. def __init__(self, specifiers="", prereleases=None):
  488. # Split on , to break each indidivual specifier into it's own item, and
  489. # strip each item to remove leading/trailing whitespace.
  490. specifiers = [s.strip() for s in specifiers.split(",") if s.strip()]
  491. # Parsed each individual specifier, attempting first to make it a
  492. # Specifier and falling back to a LegacySpecifier.
  493. parsed = set()
  494. for specifier in specifiers:
  495. try:
  496. parsed.add(Specifier(specifier))
  497. except InvalidSpecifier:
  498. parsed.add(LegacySpecifier(specifier))
  499. # Turn our parsed specifiers into a frozen set and save them for later.
  500. self._specs = frozenset(parsed)
  501. # Store our prereleases value so we can use it later to determine if
  502. # we accept prereleases or not.
  503. self._prereleases = prereleases
  504. def __repr__(self):
  505. pre = (
  506. ", prereleases={0!r}".format(self.prereleases)
  507. if self._prereleases is not None
  508. else ""
  509. )
  510. return "<SpecifierSet({0!r}{1})>".format(str(self), pre)
  511. def __str__(self):
  512. return ",".join(sorted(str(s) for s in self._specs))
  513. def __hash__(self):
  514. return hash(self._specs)
  515. def __and__(self, other):
  516. if isinstance(other, string_types):
  517. other = SpecifierSet(other)
  518. elif not isinstance(other, SpecifierSet):
  519. return NotImplemented
  520. specifier = SpecifierSet()
  521. specifier._specs = frozenset(self._specs | other._specs)
  522. if self._prereleases is None and other._prereleases is not None:
  523. specifier._prereleases = other._prereleases
  524. elif self._prereleases is not None and other._prereleases is None:
  525. specifier._prereleases = self._prereleases
  526. elif self._prereleases == other._prereleases:
  527. specifier._prereleases = self._prereleases
  528. else:
  529. raise ValueError(
  530. "Cannot combine SpecifierSets with True and False prerelease "
  531. "overrides."
  532. )
  533. return specifier
  534. def __eq__(self, other):
  535. if isinstance(other, string_types):
  536. other = SpecifierSet(other)
  537. elif isinstance(other, _IndividualSpecifier):
  538. other = SpecifierSet(str(other))
  539. elif not isinstance(other, SpecifierSet):
  540. return NotImplemented
  541. return self._specs == other._specs
  542. def __ne__(self, other):
  543. if isinstance(other, string_types):
  544. other = SpecifierSet(other)
  545. elif isinstance(other, _IndividualSpecifier):
  546. other = SpecifierSet(str(other))
  547. elif not isinstance(other, SpecifierSet):
  548. return NotImplemented
  549. return self._specs != other._specs
  550. @property
  551. def prereleases(self):
  552. # If we have been given an explicit prerelease modifier, then we'll
  553. # pass that through here.
  554. if self._prereleases is not None:
  555. return self._prereleases
  556. # Otherwise we'll see if any of the given specifiers accept
  557. # prereleases, if any of them do we'll return True, otherwise False.
  558. # Note: The use of any() here means that an empty set of specifiers
  559. # will always return False, this is an explicit design decision.
  560. return any(s.prereleases for s in self._specs)
  561. @prereleases.setter
  562. def prereleases(self, value):
  563. self._prereleases = value
  564. def contains(self, item, prereleases=None):
  565. # Ensure that our item is a Version or LegacyVersion instance.
  566. if not isinstance(item, (LegacyVersion, Version)):
  567. item = parse(item)
  568. # We can determine if we're going to allow pre-releases by looking to
  569. # see if any of the underlying items supports them. If none of them do
  570. # and this item is a pre-release then we do not allow it and we can
  571. # short circuit that here.
  572. # Note: This means that 1.0.dev1 would not be contained in something
  573. # like >=1.0.devabc however it would be in >=1.0.debabc,>0.0.dev0
  574. if (not (self.prereleases or prereleases)) and item.is_prerelease:
  575. return False
  576. # Determine if we're forcing a prerelease or not, we bypass
  577. # self.prereleases here and use self._prereleases because we want to
  578. # only take into consideration actual *forced* values. The underlying
  579. # specifiers will handle the other logic.
  580. # The logic here is: If prereleases is anything but None, we'll just
  581. # go aheand and continue to use that. However if
  582. # prereleases is None, then we'll use whatever the
  583. # value of self._prereleases is as long as it is not
  584. # None itself.
  585. if prereleases is None and self._prereleases is not None:
  586. prereleases = self._prereleases
  587. # We simply dispatch to the underlying specs here to make sure that the
  588. # given version is contained within all of them.
  589. # Note: This use of all() here means that an empty set of specifiers
  590. # will always return True, this is an explicit design decision.
  591. return all(
  592. s.contains(item, prereleases=prereleases)
  593. for s in self._specs
  594. )
  595. def filter(self, iterable, prereleases=None):
  596. # Determine if we're forcing a prerelease or not, we bypass
  597. # self.prereleases here and use self._prereleases because we want to
  598. # only take into consideration actual *forced* values. The underlying
  599. # specifiers will handle the other logic.
  600. # The logic here is: If prereleases is anything but None, we'll just
  601. # go aheand and continue to use that. However if
  602. # prereleases is None, then we'll use whatever the
  603. # value of self._prereleases is as long as it is not
  604. # None itself.
  605. if prereleases is None and self._prereleases is not None:
  606. prereleases = self._prereleases
  607. # If we have any specifiers, then we want to wrap our iterable in the
  608. # filter method for each one, this will act as a logical AND amongst
  609. # each specifier.
  610. if self._specs:
  611. for spec in self._specs:
  612. iterable = spec.filter(iterable, prereleases=prereleases)
  613. return iterable
  614. # If we do not have any specifiers, then we need to have a rough filter
  615. # which will filter out any pre-releases, unless there are no final
  616. # releases, and which will filter out LegacyVersion in general.
  617. else:
  618. filtered = []
  619. found_prereleases = []
  620. for item in iterable:
  621. # Ensure that we some kind of Version class for this item.
  622. if not isinstance(item, (LegacyVersion, Version)):
  623. parsed_version = parse(item)
  624. else:
  625. parsed_version = item
  626. # Filter out any item which is parsed as a LegacyVersion
  627. if isinstance(parsed_version, LegacyVersion):
  628. continue
  629. # Store any item which is a pre-release for later unless we've
  630. # already found a final version or we are accepting prereleases
  631. if parsed_version.is_prerelease and not prereleases:
  632. if not filtered:
  633. found_prereleases.append(item)
  634. else:
  635. filtered.append(item)
  636. # If we've found no items except for pre-releases, then we'll go
  637. # ahead and use the pre-releases
  638. if not filtered and found_prereleases and prereleases is None:
  639. return found_prereleases
  640. return filtered