Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/pkg_resources/_vendor/packaging/specifiers.py: 41%

301 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2023-07-17 14:22 -0600

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. 

4from __future__ import absolute_import, division, print_function 

5 

6import abc 

7import functools 

8import itertools 

9import re 

10 

11from ._compat import string_types, with_metaclass 

12from .version import Version, LegacyVersion, parse 

13 

14 

15class InvalidSpecifier(ValueError): 

16 """ 

17 An invalid specifier was found, users should refer to PEP 440. 

18 """ 

19 

20 

21class BaseSpecifier(with_metaclass(abc.ABCMeta, object)): 

22 

23 @abc.abstractmethod 

24 def __str__(self): 

25 """ 

26 Returns the str representation of this Specifier like object. This 

27 should be representative of the Specifier itself. 

28 """ 

29 

30 @abc.abstractmethod 

31 def __hash__(self): 

32 """ 

33 Returns a hash value for this Specifier like object. 

34 """ 

35 

36 @abc.abstractmethod 

37 def __eq__(self, other): 

38 """ 

39 Returns a boolean representing whether or not the two Specifier like 

40 objects are equal. 

41 """ 

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 

50 @abc.abstractproperty 

51 def prereleases(self): 

52 """ 

53 Returns whether or not pre-releases as a whole are allowed by this 

54 specifier. 

55 """ 

56 

57 @prereleases.setter 

58 def prereleases(self, value): 

59 """ 

60 Sets whether or not pre-releases as a whole are allowed by this 

61 specifier. 

62 """ 

63 

64 @abc.abstractmethod 

65 def contains(self, item, prereleases=None): 

66 """ 

67 Determines if the given item is contained within this specifier. 

68 """ 

69 

70 @abc.abstractmethod 

71 def filter(self, iterable, prereleases=None): 

72 """ 

73 Takes an iterable of items and filters them so that only items which 

74 are contained within this specifier are allowed in it. 

75 """ 

76 

77 

78class _IndividualSpecifier(BaseSpecifier): 

79 

80 _operators = {} 

81 

82 def __init__(self, spec="", prereleases=None): 

83 match = self._regex.search(spec) 

84 if not match: 

85 raise InvalidSpecifier("Invalid specifier: '{0}'".format(spec)) 

86 

87 self._spec = ( 

88 match.group("operator").strip(), 

89 match.group("version").strip(), 

90 ) 

91 

92 # Store whether or not this Specifier should accept prereleases 

93 self._prereleases = prereleases 

94 

95 def __repr__(self): 

96 pre = ( 

97 ", prereleases={0!r}".format(self.prereleases) 

98 if self._prereleases is not None 

99 else "" 

100 ) 

101 

102 return "<{0}({1!r}{2})>".format( 

103 self.__class__.__name__, 

104 str(self), 

105 pre, 

106 ) 

107 

108 def __str__(self): 

109 return "{0}{1}".format(*self._spec) 

110 

111 def __hash__(self): 

112 return hash(self._spec) 

113 

114 def __eq__(self, other): 

115 if isinstance(other, string_types): 

116 try: 

117 other = self.__class__(other) 

118 except InvalidSpecifier: 

119 return NotImplemented 

120 elif not isinstance(other, self.__class__): 

121 return NotImplemented 

122 

123 return self._spec == other._spec 

124 

125 def __ne__(self, other): 

126 if isinstance(other, string_types): 

127 try: 

128 other = self.__class__(other) 

129 except InvalidSpecifier: 

130 return NotImplemented 

131 elif not isinstance(other, self.__class__): 

132 return NotImplemented 

133 

134 return self._spec != other._spec 

135 

136 def _get_operator(self, op): 

137 return getattr(self, "_compare_{0}".format(self._operators[op])) 

138 

139 def _coerce_version(self, version): 

140 if not isinstance(version, (LegacyVersion, Version)): 

141 version = parse(version) 

142 return version 

143 

144 @property 

145 def operator(self): 

146 return self._spec[0] 

147 

148 @property 

149 def version(self): 

150 return self._spec[1] 

151 

152 @property 

153 def prereleases(self): 

154 return self._prereleases 

155 

156 @prereleases.setter 

157 def prereleases(self, value): 

158 self._prereleases = value 

159 

160 def __contains__(self, item): 

161 return self.contains(item) 

162 

163 def contains(self, item, prereleases=None): 

164 # Determine if prereleases are to be allowed or not. 

165 if prereleases is None: 

166 prereleases = self.prereleases 

167 

168 # Normalize item to a Version or LegacyVersion, this allows us to have 

169 # a shortcut for ``"2.0" in Specifier(">=2") 

170 item = self._coerce_version(item) 

171 

172 # Determine if we should be supporting prereleases in this specifier 

173 # or not, if we do not support prereleases than we can short circuit 

174 # logic if this version is a prereleases. 

175 if item.is_prerelease and not prereleases: 175 ↛ 176line 175 didn't jump to line 176, because the condition on line 175 was never true

176 return False 

177 

178 # Actually do the comparison to determine if this item is contained 

179 # within this Specifier or not. 

180 return self._get_operator(self.operator)(item, self.version) 

181 

182 def filter(self, iterable, prereleases=None): 

183 yielded = False 

184 found_prereleases = [] 

185 

186 kw = {"prereleases": prereleases if prereleases is not None else True} 

187 

188 # Attempt to iterate over all the values in the iterable and if any of 

189 # them match, yield them. 

190 for version in iterable: 

191 parsed_version = self._coerce_version(version) 

192 

193 if self.contains(parsed_version, **kw): 

194 # If our version is a prerelease, and we were not set to allow 

195 # prereleases, then we'll store it for later incase nothing 

196 # else matches this specifier. 

197 if (parsed_version.is_prerelease and not 

198 (prereleases or self.prereleases)): 

199 found_prereleases.append(version) 

200 # Either this is not a prerelease, or we should have been 

201 # accepting prereleases from the begining. 

202 else: 

203 yielded = True 

204 yield version 

205 

206 # Now that we've iterated over everything, determine if we've yielded 

207 # any values, and if we have not and we have any prereleases stored up 

208 # then we will go ahead and yield the prereleases. 

209 if not yielded and found_prereleases: 

210 for version in found_prereleases: 

211 yield version 

212 

213 

214class LegacySpecifier(_IndividualSpecifier): 

215 

216 _regex_str = ( 

217 r""" 

218 (?P<operator>(==|!=|<=|>=|<|>)) 

219 \s* 

220 (?P<version> 

221 [^,;\s)]* # Since this is a "legacy" specifier, and the version 

222 # string can be just about anything, we match everything 

223 # except for whitespace, a semi-colon for marker support, 

224 # a closing paren since versions can be enclosed in 

225 # them, and a comma since it's a version separator. 

226 ) 

227 """ 

228 ) 

229 

230 _regex = re.compile( 

231 r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE) 

232 

233 _operators = { 

234 "==": "equal", 

235 "!=": "not_equal", 

236 "<=": "less_than_equal", 

237 ">=": "greater_than_equal", 

238 "<": "less_than", 

239 ">": "greater_than", 

240 } 

241 

242 def _coerce_version(self, version): 

243 if not isinstance(version, LegacyVersion): 

244 version = LegacyVersion(str(version)) 

245 return version 

246 

247 def _compare_equal(self, prospective, spec): 

248 return prospective == self._coerce_version(spec) 

249 

250 def _compare_not_equal(self, prospective, spec): 

251 return prospective != self._coerce_version(spec) 

252 

253 def _compare_less_than_equal(self, prospective, spec): 

254 return prospective <= self._coerce_version(spec) 

255 

256 def _compare_greater_than_equal(self, prospective, spec): 

257 return prospective >= self._coerce_version(spec) 

258 

259 def _compare_less_than(self, prospective, spec): 

260 return prospective < self._coerce_version(spec) 

261 

262 def _compare_greater_than(self, prospective, spec): 

263 return prospective > self._coerce_version(spec) 

264 

265 

266def _require_version_compare(fn): 

267 @functools.wraps(fn) 

268 def wrapped(self, prospective, spec): 

269 if not isinstance(prospective, Version): 269 ↛ 270line 269 didn't jump to line 270, because the condition on line 269 was never true

270 return False 

271 return fn(self, prospective, spec) 

272 return wrapped 

273 

274 

275class Specifier(_IndividualSpecifier): 

276 

277 _regex_str = ( 

278 r""" 

279 (?P<operator>(~=|==|!=|<=|>=|<|>|===)) 

280 (?P<version> 

281 (?: 

282 # The identity operators allow for an escape hatch that will 

283 # do an exact string match of the version you wish to install. 

284 # This will not be parsed by PEP 440 and we cannot determine 

285 # any semantic meaning from it. This operator is discouraged 

286 # but included entirely as an escape hatch. 

287 (?<====) # Only match for the identity operator 

288 \s* 

289 [^\s]* # We just match everything, except for whitespace 

290 # since we are only testing for strict identity. 

291 ) 

292 | 

293 (?: 

294 # The (non)equality operators allow for wild card and local 

295 # versions to be specified so we have to define these two 

296 # operators separately to enable that. 

297 (?<===|!=) # Only match for equals and not equals 

298 

299 \s* 

300 v? 

301 (?:[0-9]+!)? # epoch 

302 [0-9]+(?:\.[0-9]+)* # release 

303 (?: # pre release 

304 [-_\.]? 

305 (a|b|c|rc|alpha|beta|pre|preview) 

306 [-_\.]? 

307 [0-9]* 

308 )? 

309 (?: # post release 

310 (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) 

311 )? 

312 

313 # You cannot use a wild card and a dev or local version 

314 # together so group them with a | and make them optional. 

315 (?: 

316 (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release 

317 (?:\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*)? # local 

318 | 

319 \.\* # Wild card syntax of .* 

320 )? 

321 ) 

322 | 

323 (?: 

324 # The compatible operator requires at least two digits in the 

325 # release segment. 

326 (?<=~=) # Only match for the compatible operator 

327 

328 \s* 

329 v? 

330 (?:[0-9]+!)? # epoch 

331 [0-9]+(?:\.[0-9]+)+ # release (We have a + instead of a *) 

332 (?: # pre release 

333 [-_\.]? 

334 (a|b|c|rc|alpha|beta|pre|preview) 

335 [-_\.]? 

336 [0-9]* 

337 )? 

338 (?: # post release 

339 (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) 

340 )? 

341 (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release 

342 ) 

343 | 

344 (?: 

345 # All other operators only allow a sub set of what the 

346 # (non)equality operators do. Specifically they do not allow 

347 # local versions to be specified nor do they allow the prefix 

348 # matching wild cards. 

349 (?<!==|!=|~=) # We have special cases for these 

350 # operators so we want to make sure they 

351 # don't match here. 

352 

353 \s* 

354 v? 

355 (?:[0-9]+!)? # epoch 

356 [0-9]+(?:\.[0-9]+)* # release 

357 (?: # pre release 

358 [-_\.]? 

359 (a|b|c|rc|alpha|beta|pre|preview) 

360 [-_\.]? 

361 [0-9]* 

362 )? 

363 (?: # post release 

364 (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) 

365 )? 

366 (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release 

367 ) 

368 ) 

369 """ 

370 ) 

371 

372 _regex = re.compile( 

373 r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE) 

374 

375 _operators = { 

376 "~=": "compatible", 

377 "==": "equal", 

378 "!=": "not_equal", 

379 "<=": "less_than_equal", 

380 ">=": "greater_than_equal", 

381 "<": "less_than", 

382 ">": "greater_than", 

383 "===": "arbitrary", 

384 } 

385 

386 @_require_version_compare 

387 def _compare_compatible(self, prospective, spec): 

388 # Compatible releases have an equivalent combination of >= and ==. That 

389 # is that ~=2.2 is equivalent to >=2.2,==2.*. This allows us to 

390 # implement this in terms of the other specifiers instead of 

391 # implementing it ourselves. The only thing we need to do is construct 

392 # the other specifiers. 

393 

394 # We want everything but the last item in the version, but we want to 

395 # ignore post and dev releases and we want to treat the pre-release as 

396 # it's own separate segment. 

397 prefix = ".".join( 

398 list( 

399 itertools.takewhile( 

400 lambda x: (not x.startswith("post") and not 

401 x.startswith("dev")), 

402 _version_split(spec), 

403 ) 

404 )[:-1] 

405 ) 

406 

407 # Add the prefix notation to the end of our string 

408 prefix += ".*" 

409 

410 return (self._get_operator(">=")(prospective, spec) and 

411 self._get_operator("==")(prospective, prefix)) 

412 

413 @_require_version_compare 

414 def _compare_equal(self, prospective, spec): 

415 # We need special logic to handle prefix matching 

416 if spec.endswith(".*"): 

417 # In the case of prefix matching we want to ignore local segment. 

418 prospective = Version(prospective.public) 

419 # Split the spec out by dots, and pretend that there is an implicit 

420 # dot in between a release segment and a pre-release segment. 

421 spec = _version_split(spec[:-2]) # Remove the trailing .* 

422 

423 # Split the prospective version out by dots, and pretend that there 

424 # is an implicit dot in between a release segment and a pre-release 

425 # segment. 

426 prospective = _version_split(str(prospective)) 

427 

428 # Shorten the prospective version to be the same length as the spec 

429 # so that we can determine if the specifier is a prefix of the 

430 # prospective version or not. 

431 prospective = prospective[:len(spec)] 

432 

433 # Pad out our two sides with zeros so that they both equal the same 

434 # length. 

435 spec, prospective = _pad_version(spec, prospective) 

436 else: 

437 # Convert our spec string into a Version 

438 spec = Version(spec) 

439 

440 # If the specifier does not have a local segment, then we want to 

441 # act as if the prospective version also does not have a local 

442 # segment. 

443 if not spec.local: 

444 prospective = Version(prospective.public) 

445 

446 return prospective == spec 

447 

448 @_require_version_compare 

449 def _compare_not_equal(self, prospective, spec): 

450 return not self._compare_equal(prospective, spec) 

451 

452 @_require_version_compare 

453 def _compare_less_than_equal(self, prospective, spec): 

454 return prospective <= Version(spec) 

455 

456 @_require_version_compare 

457 def _compare_greater_than_equal(self, prospective, spec): 

458 return prospective >= Version(spec) 

459 

460 @_require_version_compare 

461 def _compare_less_than(self, prospective, spec): 

462 # Convert our spec to a Version instance, since we'll want to work with 

463 # it as a version. 

464 spec = Version(spec) 

465 

466 # Check to see if the prospective version is less than the spec 

467 # version. If it's not we can short circuit and just return False now 

468 # instead of doing extra unneeded work. 

469 if not prospective < spec: 

470 return False 

471 

472 # This special case is here so that, unless the specifier itself 

473 # includes is a pre-release version, that we do not accept pre-release 

474 # versions for the version mentioned in the specifier (e.g. <3.1 should 

475 # not match 3.1.dev0, but should match 3.0.dev0). 

476 if not spec.is_prerelease and prospective.is_prerelease: 476 ↛ 477line 476 didn't jump to line 477, because the condition on line 476 was never true

477 if Version(prospective.base_version) == Version(spec.base_version): 

478 return False 

479 

480 # If we've gotten to here, it means that prospective version is both 

481 # less than the spec version *and* it's not a pre-release of the same 

482 # version in the spec. 

483 return True 

484 

485 @_require_version_compare 

486 def _compare_greater_than(self, prospective, spec): 

487 # Convert our spec to a Version instance, since we'll want to work with 

488 # it as a version. 

489 spec = Version(spec) 

490 

491 # Check to see if the prospective version is greater than the spec 

492 # version. If it's not we can short circuit and just return False now 

493 # instead of doing extra unneeded work. 

494 if not prospective > spec: 

495 return False 

496 

497 # This special case is here so that, unless the specifier itself 

498 # includes is a post-release version, that we do not accept 

499 # post-release versions for the version mentioned in the specifier 

500 # (e.g. >3.1 should not match 3.0.post0, but should match 3.2.post0). 

501 if not spec.is_postrelease and prospective.is_postrelease: 

502 if Version(prospective.base_version) == Version(spec.base_version): 

503 return False 

504 

505 # Ensure that we do not allow a local version of the version mentioned 

506 # in the specifier, which is techincally greater than, to match. 

507 if prospective.local is not None: 

508 if Version(prospective.base_version) == Version(spec.base_version): 

509 return False 

510 

511 # If we've gotten to here, it means that prospective version is both 

512 # greater than the spec version *and* it's not a pre-release of the 

513 # same version in the spec. 

514 return True 

515 

516 def _compare_arbitrary(self, prospective, spec): 

517 return str(prospective).lower() == str(spec).lower() 

518 

519 @property 

520 def prereleases(self): 

521 # If there is an explicit prereleases set for this, then we'll just 

522 # blindly use that. 

523 if self._prereleases is not None: 523 ↛ 524line 523 didn't jump to line 524, because the condition on line 523 was never true

524 return self._prereleases 

525 

526 # Look at all of our specifiers and determine if they are inclusive 

527 # operators, and if they are if they are including an explicit 

528 # prerelease. 

529 operator, version = self._spec 

530 if operator in ["==", ">=", "<=", "~=", "==="]: 530 ↛ 533line 530 didn't jump to line 533, because the condition on line 530 was never true

531 # The == specifier can include a trailing .*, if it does we 

532 # want to remove before parsing. 

533 if operator == "==" and version.endswith(".*"): 

534 version = version[:-2] 

535 

536 # Parse the version, and if it is a pre-release than this 

537 # specifier allows pre-releases. 

538 if parse(version).is_prerelease: 

539 return True 

540 

541 return False 

542 

543 @prereleases.setter 

544 def prereleases(self, value): 

545 self._prereleases = value 

546 

547 

548_prefix_regex = re.compile(r"^([0-9]+)((?:a|b|c|rc)[0-9]+)$") 

549 

550 

551def _version_split(version): 

552 result = [] 

553 for item in version.split("."): 

554 match = _prefix_regex.search(item) 

555 if match: 

556 result.extend(match.groups()) 

557 else: 

558 result.append(item) 

559 return result 

560 

561 

562def _pad_version(left, right): 

563 left_split, right_split = [], [] 

564 

565 # Get the release segment of our versions 

566 left_split.append(list(itertools.takewhile(lambda x: x.isdigit(), left))) 

567 right_split.append(list(itertools.takewhile(lambda x: x.isdigit(), right))) 

568 

569 # Get the rest of our versions 

570 left_split.append(left[len(left_split[0]):]) 

571 right_split.append(right[len(right_split[0]):]) 

572 

573 # Insert our padding 

574 left_split.insert( 

575 1, 

576 ["0"] * max(0, len(right_split[0]) - len(left_split[0])), 

577 ) 

578 right_split.insert( 

579 1, 

580 ["0"] * max(0, len(left_split[0]) - len(right_split[0])), 

581 ) 

582 

583 return ( 

584 list(itertools.chain(*left_split)), 

585 list(itertools.chain(*right_split)), 

586 ) 

587 

588 

589class SpecifierSet(BaseSpecifier): 

590 

591 def __init__(self, specifiers="", prereleases=None): 

592 # Split on , to break each indidivual specifier into it's own item, and 

593 # strip each item to remove leading/trailing whitespace. 

594 specifiers = [s.strip() for s in specifiers.split(",") if s.strip()] 

595 

596 # Parsed each individual specifier, attempting first to make it a 

597 # Specifier and falling back to a LegacySpecifier. 

598 parsed = set() 

599 for specifier in specifiers: 

600 try: 

601 parsed.add(Specifier(specifier)) 

602 except InvalidSpecifier: 

603 parsed.add(LegacySpecifier(specifier)) 

604 

605 # Turn our parsed specifiers into a frozen set and save them for later. 

606 self._specs = frozenset(parsed) 

607 

608 # Store our prereleases value so we can use it later to determine if 

609 # we accept prereleases or not. 

610 self._prereleases = prereleases 

611 

612 def __repr__(self): 

613 pre = ( 

614 ", prereleases={0!r}".format(self.prereleases) 

615 if self._prereleases is not None 

616 else "" 

617 ) 

618 

619 return "<SpecifierSet({0!r}{1})>".format(str(self), pre) 

620 

621 def __str__(self): 

622 return ",".join(sorted(str(s) for s in self._specs)) 

623 

624 def __hash__(self): 

625 return hash(self._specs) 

626 

627 def __and__(self, other): 

628 if isinstance(other, string_types): 

629 other = SpecifierSet(other) 

630 elif not isinstance(other, SpecifierSet): 

631 return NotImplemented 

632 

633 specifier = SpecifierSet() 

634 specifier._specs = frozenset(self._specs | other._specs) 

635 

636 if self._prereleases is None and other._prereleases is not None: 

637 specifier._prereleases = other._prereleases 

638 elif self._prereleases is not None and other._prereleases is None: 

639 specifier._prereleases = self._prereleases 

640 elif self._prereleases == other._prereleases: 

641 specifier._prereleases = self._prereleases 

642 else: 

643 raise ValueError( 

644 "Cannot combine SpecifierSets with True and False prerelease " 

645 "overrides." 

646 ) 

647 

648 return specifier 

649 

650 def __eq__(self, other): 

651 if isinstance(other, string_types): 

652 other = SpecifierSet(other) 

653 elif isinstance(other, _IndividualSpecifier): 

654 other = SpecifierSet(str(other)) 

655 elif not isinstance(other, SpecifierSet): 

656 return NotImplemented 

657 

658 return self._specs == other._specs 

659 

660 def __ne__(self, other): 

661 if isinstance(other, string_types): 

662 other = SpecifierSet(other) 

663 elif isinstance(other, _IndividualSpecifier): 

664 other = SpecifierSet(str(other)) 

665 elif not isinstance(other, SpecifierSet): 

666 return NotImplemented 

667 

668 return self._specs != other._specs 

669 

670 def __len__(self): 

671 return len(self._specs) 

672 

673 def __iter__(self): 

674 return iter(self._specs) 

675 

676 @property 

677 def prereleases(self): 

678 # If we have been given an explicit prerelease modifier, then we'll 

679 # pass that through here. 

680 if self._prereleases is not None: 

681 return self._prereleases 

682 

683 # If we don't have any specifiers, and we don't have a forced value, 

684 # then we'll just return None since we don't know if this should have 

685 # pre-releases or not. 

686 if not self._specs: 

687 return None 

688 

689 # Otherwise we'll see if any of the given specifiers accept 

690 # prereleases, if any of them do we'll return True, otherwise False. 

691 return any(s.prereleases for s in self._specs) 

692 

693 @prereleases.setter 

694 def prereleases(self, value): 

695 self._prereleases = value 

696 

697 def __contains__(self, item): 

698 return self.contains(item) 

699 

700 def contains(self, item, prereleases=None): 

701 # Ensure that our item is a Version or LegacyVersion instance. 

702 if not isinstance(item, (LegacyVersion, Version)): 702 ↛ 708line 702 didn't jump to line 708, because the condition on line 702 was never false

703 item = parse(item) 

704 

705 # Determine if we're forcing a prerelease or not, if we're not forcing 

706 # one for this particular filter call, then we'll use whatever the 

707 # SpecifierSet thinks for whether or not we should support prereleases. 

708 if prereleases is None: 708 ↛ 709line 708 didn't jump to line 709, because the condition on line 708 was never true

709 prereleases = self.prereleases 

710 

711 # We can determine if we're going to allow pre-releases by looking to 

712 # see if any of the underlying items supports them. If none of them do 

713 # and this item is a pre-release then we do not allow it and we can 

714 # short circuit that here. 

715 # Note: This means that 1.0.dev1 would not be contained in something 

716 # like >=1.0.devabc however it would be in >=1.0.debabc,>0.0.dev0 

717 if not prereleases and item.is_prerelease: 717 ↛ 718line 717 didn't jump to line 718, because the condition on line 717 was never true

718 return False 

719 

720 # We simply dispatch to the underlying specs here to make sure that the 

721 # given version is contained within all of them. 

722 # Note: This use of all() here means that an empty set of specifiers 

723 # will always return True, this is an explicit design decision. 

724 return all( 

725 s.contains(item, prereleases=prereleases) 

726 for s in self._specs 

727 ) 

728 

729 def filter(self, iterable, prereleases=None): 

730 # Determine if we're forcing a prerelease or not, if we're not forcing 

731 # one for this particular filter call, then we'll use whatever the 

732 # SpecifierSet thinks for whether or not we should support prereleases. 

733 if prereleases is None: 

734 prereleases = self.prereleases 

735 

736 # If we have any specifiers, then we want to wrap our iterable in the 

737 # filter method for each one, this will act as a logical AND amongst 

738 # each specifier. 

739 if self._specs: 

740 for spec in self._specs: 

741 iterable = spec.filter(iterable, prereleases=bool(prereleases)) 

742 return iterable 

743 # If we do not have any specifiers, then we need to have a rough filter 

744 # which will filter out any pre-releases, unless there are no final 

745 # releases, and which will filter out LegacyVersion in general. 

746 else: 

747 filtered = [] 

748 found_prereleases = [] 

749 

750 for item in iterable: 

751 # Ensure that we some kind of Version class for this item. 

752 if not isinstance(item, (LegacyVersion, Version)): 

753 parsed_version = parse(item) 

754 else: 

755 parsed_version = item 

756 

757 # Filter out any item which is parsed as a LegacyVersion 

758 if isinstance(parsed_version, LegacyVersion): 

759 continue 

760 

761 # Store any item which is a pre-release for later unless we've 

762 # already found a final version or we are accepting prereleases 

763 if parsed_version.is_prerelease and not prereleases: 

764 if not filtered: 

765 found_prereleases.append(item) 

766 else: 

767 filtered.append(item) 

768 

769 # If we've found no items except for pre-releases, then we'll go 

770 # ahead and use the pre-releases 

771 if not filtered and found_prereleases and prereleases is None: 

772 return found_prereleases 

773 

774 return filtered