Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/pkg_resources/_vendor/packaging/specifiers.py: 23%

306 statements  

« prev     ^ index     » next       coverage.py v7.2.2, created at 2023-03-26 06:25 +0000

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: 

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): 

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: 

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: 

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 ["==", ">=", "<=", "~=", "==="]: 

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)): 

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: 

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: 

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