pip 25.3__py3-none-any.whl → 26.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. pip/__init__.py +1 -1
  2. pip/_internal/build_env.py +194 -5
  3. pip/_internal/cli/base_command.py +11 -0
  4. pip/_internal/cli/cmdoptions.py +157 -0
  5. pip/_internal/cli/index_command.py +20 -0
  6. pip/_internal/cli/main.py +11 -6
  7. pip/_internal/cli/main_parser.py +3 -1
  8. pip/_internal/cli/parser.py +93 -33
  9. pip/_internal/cli/progress_bars.py +4 -2
  10. pip/_internal/cli/req_command.py +99 -23
  11. pip/_internal/commands/cache.py +24 -0
  12. pip/_internal/commands/completion.py +2 -1
  13. pip/_internal/commands/download.py +8 -4
  14. pip/_internal/commands/index.py +13 -6
  15. pip/_internal/commands/install.py +36 -29
  16. pip/_internal/commands/list.py +14 -16
  17. pip/_internal/commands/lock.py +16 -8
  18. pip/_internal/commands/wheel.py +8 -13
  19. pip/_internal/exceptions.py +76 -3
  20. pip/_internal/index/collector.py +2 -3
  21. pip/_internal/index/package_finder.py +84 -18
  22. pip/_internal/locations/__init__.py +1 -2
  23. pip/_internal/locations/_sysconfig.py +4 -1
  24. pip/_internal/models/link.py +18 -14
  25. pip/_internal/models/release_control.py +92 -0
  26. pip/_internal/models/selection_prefs.py +6 -3
  27. pip/_internal/network/auth.py +6 -2
  28. pip/_internal/network/download.py +4 -5
  29. pip/_internal/network/session.py +14 -10
  30. pip/_internal/operations/install/wheel.py +1 -2
  31. pip/_internal/operations/prepare.py +2 -3
  32. pip/_internal/req/constructors.py +3 -1
  33. pip/_internal/req/pep723.py +41 -0
  34. pip/_internal/req/req_file.py +10 -1
  35. pip/_internal/resolution/resolvelib/factory.py +12 -1
  36. pip/_internal/resolution/resolvelib/requirements.py +7 -3
  37. pip/_internal/self_outdated_check.py +6 -13
  38. pip/_internal/utils/datetime.py +18 -0
  39. pip/_internal/utils/filesystem.py +40 -1
  40. pip/_internal/utils/logging.py +34 -2
  41. pip/_internal/utils/misc.py +18 -12
  42. pip/_internal/utils/pylock.py +116 -0
  43. pip/_internal/utils/unpacking.py +1 -1
  44. pip/_internal/vcs/versioncontrol.py +3 -1
  45. pip/_vendor/cachecontrol/__init__.py +6 -3
  46. pip/_vendor/cachecontrol/adapter.py +0 -1
  47. pip/_vendor/cachecontrol/controller.py +1 -1
  48. pip/_vendor/cachecontrol/filewrapper.py +3 -1
  49. pip/_vendor/certifi/__init__.py +1 -1
  50. pip/_vendor/certifi/cacert.pem +0 -332
  51. pip/_vendor/idna/LICENSE.md +1 -1
  52. pip/_vendor/idna/codec.py +1 -1
  53. pip/_vendor/idna/core.py +1 -1
  54. pip/_vendor/idna/idnadata.py +72 -6
  55. pip/_vendor/idna/package_data.py +1 -1
  56. pip/_vendor/idna/uts46data.py +891 -731
  57. pip/_vendor/packaging/__init__.py +1 -1
  58. pip/_vendor/packaging/_elffile.py +0 -1
  59. pip/_vendor/packaging/_manylinux.py +36 -36
  60. pip/_vendor/packaging/_musllinux.py +1 -1
  61. pip/_vendor/packaging/_parser.py +22 -10
  62. pip/_vendor/packaging/_structures.py +8 -0
  63. pip/_vendor/packaging/_tokenizer.py +23 -25
  64. pip/_vendor/packaging/licenses/__init__.py +13 -11
  65. pip/_vendor/packaging/licenses/_spdx.py +41 -1
  66. pip/_vendor/packaging/markers.py +64 -38
  67. pip/_vendor/packaging/metadata.py +143 -27
  68. pip/_vendor/packaging/pylock.py +635 -0
  69. pip/_vendor/packaging/requirements.py +5 -10
  70. pip/_vendor/packaging/specifiers.py +219 -170
  71. pip/_vendor/packaging/tags.py +15 -20
  72. pip/_vendor/packaging/utils.py +19 -24
  73. pip/_vendor/packaging/version.py +315 -105
  74. pip/_vendor/platformdirs/version.py +2 -2
  75. pip/_vendor/platformdirs/windows.py +7 -1
  76. pip/_vendor/vendor.txt +5 -5
  77. {pip-25.3.dist-info → pip-26.0.dist-info}/METADATA +2 -2
  78. {pip-25.3.dist-info → pip-26.0.dist-info}/RECORD +103 -100
  79. {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/AUTHORS.txt +18 -0
  80. {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/idna/LICENSE.md +1 -1
  81. pip/_internal/models/pylock.py +0 -188
  82. {pip-25.3.dist-info → pip-26.0.dist-info}/WHEEL +0 -0
  83. {pip-25.3.dist-info → pip-26.0.dist-info}/entry_points.txt +0 -0
  84. {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/LICENSE.txt +0 -0
  85. {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/cachecontrol/LICENSE.txt +0 -0
  86. {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/certifi/LICENSE +0 -0
  87. {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/dependency_groups/LICENSE.txt +0 -0
  88. {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/distlib/LICENSE.txt +0 -0
  89. {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/distro/LICENSE +0 -0
  90. {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/msgpack/COPYING +0 -0
  91. {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/packaging/LICENSE +0 -0
  92. {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/packaging/LICENSE.APACHE +0 -0
  93. {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/packaging/LICENSE.BSD +0 -0
  94. {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/pkg_resources/LICENSE +0 -0
  95. {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/platformdirs/LICENSE +0 -0
  96. {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/pygments/LICENSE +0 -0
  97. {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/pyproject_hooks/LICENSE +0 -0
  98. {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/requests/LICENSE +0 -0
  99. {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/resolvelib/LICENSE +0 -0
  100. {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/rich/LICENSE +0 -0
  101. {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/tomli/LICENSE +0 -0
  102. {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/tomli_w/LICENSE +0 -0
  103. {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/truststore/LICENSE +0 -0
  104. {pip-25.3.dist-info → pip-26.0.dist-info}/licenses/src/pip/_vendor/urllib3/LICENSE.txt +0 -0
@@ -12,7 +12,7 @@ class SPDXException(TypedDict):
12
12
  deprecated: bool
13
13
 
14
14
 
15
- VERSION = '3.25.0'
15
+ VERSION = '3.27.0'
16
16
 
17
17
  LICENSES: dict[str, SPDXLicense] = {
18
18
  '0bsd': {'id': '0BSD', 'deprecated': False},
@@ -46,6 +46,7 @@ LICENSES: dict[str, SPDXLicense] = {
46
46
  'antlr-pd': {'id': 'ANTLR-PD', 'deprecated': False},
47
47
  'antlr-pd-fallback': {'id': 'ANTLR-PD-fallback', 'deprecated': False},
48
48
  'any-osi': {'id': 'any-OSI', 'deprecated': False},
49
+ 'any-osi-perl-modules': {'id': 'any-OSI-perl-modules', 'deprecated': False},
49
50
  'apache-1.0': {'id': 'Apache-1.0', 'deprecated': False},
50
51
  'apache-1.1': {'id': 'Apache-1.1', 'deprecated': False},
51
52
  'apache-2.0': {'id': 'Apache-2.0', 'deprecated': False},
@@ -61,6 +62,8 @@ LICENSES: dict[str, SPDXLicense] = {
61
62
  'artistic-1.0-cl8': {'id': 'Artistic-1.0-cl8', 'deprecated': False},
62
63
  'artistic-1.0-perl': {'id': 'Artistic-1.0-Perl', 'deprecated': False},
63
64
  'artistic-2.0': {'id': 'Artistic-2.0', 'deprecated': False},
65
+ 'artistic-dist': {'id': 'Artistic-dist', 'deprecated': False},
66
+ 'aspell-ru': {'id': 'Aspell-RU', 'deprecated': False},
64
67
  'aswf-digital-assets-1.0': {'id': 'ASWF-Digital-Assets-1.0', 'deprecated': False},
65
68
  'aswf-digital-assets-1.1': {'id': 'ASWF-Digital-Assets-1.1', 'deprecated': False},
66
69
  'baekmuk': {'id': 'Baekmuk', 'deprecated': False},
@@ -75,6 +78,7 @@ LICENSES: dict[str, SPDXLicense] = {
75
78
  'blessing': {'id': 'blessing', 'deprecated': False},
76
79
  'blueoak-1.0.0': {'id': 'BlueOak-1.0.0', 'deprecated': False},
77
80
  'boehm-gc': {'id': 'Boehm-GC', 'deprecated': False},
81
+ 'boehm-gc-without-fee': {'id': 'Boehm-GC-without-fee', 'deprecated': False},
78
82
  'borceux': {'id': 'Borceux', 'deprecated': False},
79
83
  'brian-gladman-2-clause': {'id': 'Brian-Gladman-2-Clause', 'deprecated': False},
80
84
  'brian-gladman-3-clause': {'id': 'Brian-Gladman-3-Clause', 'deprecated': False},
@@ -85,6 +89,7 @@ LICENSES: dict[str, SPDXLicense] = {
85
89
  'bsd-2-clause-freebsd': {'id': 'BSD-2-Clause-FreeBSD', 'deprecated': True},
86
90
  'bsd-2-clause-netbsd': {'id': 'BSD-2-Clause-NetBSD', 'deprecated': True},
87
91
  'bsd-2-clause-patent': {'id': 'BSD-2-Clause-Patent', 'deprecated': False},
92
+ 'bsd-2-clause-pkgconf-disclaimer': {'id': 'BSD-2-Clause-pkgconf-disclaimer', 'deprecated': False},
88
93
  'bsd-2-clause-views': {'id': 'BSD-2-Clause-Views', 'deprecated': False},
89
94
  'bsd-3-clause': {'id': 'BSD-3-Clause', 'deprecated': False},
90
95
  'bsd-3-clause-acpica': {'id': 'BSD-3-Clause-acpica', 'deprecated': False},
@@ -176,6 +181,8 @@ LICENSES: dict[str, SPDXLicense] = {
176
181
  'cc-by-sa-3.0-igo': {'id': 'CC-BY-SA-3.0-IGO', 'deprecated': False},
177
182
  'cc-by-sa-4.0': {'id': 'CC-BY-SA-4.0', 'deprecated': False},
178
183
  'cc-pddc': {'id': 'CC-PDDC', 'deprecated': False},
184
+ 'cc-pdm-1.0': {'id': 'CC-PDM-1.0', 'deprecated': False},
185
+ 'cc-sa-1.0': {'id': 'CC-SA-1.0', 'deprecated': False},
179
186
  'cc0-1.0': {'id': 'CC0-1.0', 'deprecated': False},
180
187
  'cddl-1.0': {'id': 'CDDL-1.0', 'deprecated': False},
181
188
  'cddl-1.1': {'id': 'CDDL-1.1', 'deprecated': False},
@@ -215,6 +222,7 @@ LICENSES: dict[str, SPDXLicense] = {
215
222
  'cpol-1.02': {'id': 'CPOL-1.02', 'deprecated': False},
216
223
  'cronyx': {'id': 'Cronyx', 'deprecated': False},
217
224
  'crossword': {'id': 'Crossword', 'deprecated': False},
225
+ 'cryptoswift': {'id': 'CryptoSwift', 'deprecated': False},
218
226
  'crystalstacker': {'id': 'CrystalStacker', 'deprecated': False},
219
227
  'cua-opl-1.0': {'id': 'CUA-OPL-1.0', 'deprecated': False},
220
228
  'cube': {'id': 'Cube', 'deprecated': False},
@@ -226,7 +234,9 @@ LICENSES: dict[str, SPDXLicense] = {
226
234
  'dl-de-by-2.0': {'id': 'DL-DE-BY-2.0', 'deprecated': False},
227
235
  'dl-de-zero-2.0': {'id': 'DL-DE-ZERO-2.0', 'deprecated': False},
228
236
  'doc': {'id': 'DOC', 'deprecated': False},
237
+ 'docbook-dtd': {'id': 'DocBook-DTD', 'deprecated': False},
229
238
  'docbook-schema': {'id': 'DocBook-Schema', 'deprecated': False},
239
+ 'docbook-stylesheet': {'id': 'DocBook-Stylesheet', 'deprecated': False},
230
240
  'docbook-xml': {'id': 'DocBook-XML', 'deprecated': False},
231
241
  'dotseqn': {'id': 'Dotseqn', 'deprecated': False},
232
242
  'drl-1.0': {'id': 'DRL-1.0', 'deprecated': False},
@@ -263,12 +273,17 @@ LICENSES: dict[str, SPDXLicense] = {
263
273
  'fsfap-no-warranty-disclaimer': {'id': 'FSFAP-no-warranty-disclaimer', 'deprecated': False},
264
274
  'fsful': {'id': 'FSFUL', 'deprecated': False},
265
275
  'fsfullr': {'id': 'FSFULLR', 'deprecated': False},
276
+ 'fsfullrsd': {'id': 'FSFULLRSD', 'deprecated': False},
266
277
  'fsfullrwd': {'id': 'FSFULLRWD', 'deprecated': False},
278
+ 'fsl-1.1-alv2': {'id': 'FSL-1.1-ALv2', 'deprecated': False},
279
+ 'fsl-1.1-mit': {'id': 'FSL-1.1-MIT', 'deprecated': False},
267
280
  'ftl': {'id': 'FTL', 'deprecated': False},
268
281
  'furuseth': {'id': 'Furuseth', 'deprecated': False},
269
282
  'fwlw': {'id': 'fwlw', 'deprecated': False},
283
+ 'game-programming-gems': {'id': 'Game-Programming-Gems', 'deprecated': False},
270
284
  'gcr-docs': {'id': 'GCR-docs', 'deprecated': False},
271
285
  'gd': {'id': 'GD', 'deprecated': False},
286
+ 'generic-xts': {'id': 'generic-xts', 'deprecated': False},
272
287
  'gfdl-1.1': {'id': 'GFDL-1.1', 'deprecated': True},
273
288
  'gfdl-1.1-invariants-only': {'id': 'GFDL-1.1-invariants-only', 'deprecated': False},
274
289
  'gfdl-1.1-invariants-or-later': {'id': 'GFDL-1.1-invariants-or-later', 'deprecated': False},
@@ -320,6 +335,7 @@ LICENSES: dict[str, SPDXLicense] = {
320
335
  'gtkbook': {'id': 'gtkbook', 'deprecated': False},
321
336
  'gutmann': {'id': 'Gutmann', 'deprecated': False},
322
337
  'haskellreport': {'id': 'HaskellReport', 'deprecated': False},
338
+ 'hdf5': {'id': 'HDF5', 'deprecated': False},
323
339
  'hdparm': {'id': 'hdparm', 'deprecated': False},
324
340
  'hidapi': {'id': 'HIDAPI', 'deprecated': False},
325
341
  'hippocratic-2.1': {'id': 'Hippocratic-2.1', 'deprecated': False},
@@ -360,6 +376,7 @@ LICENSES: dict[str, SPDXLicense] = {
360
376
  'imlib2': {'id': 'Imlib2', 'deprecated': False},
361
377
  'info-zip': {'id': 'Info-ZIP', 'deprecated': False},
362
378
  'inner-net-2.0': {'id': 'Inner-Net-2.0', 'deprecated': False},
379
+ 'innosetup': {'id': 'InnoSetup', 'deprecated': False},
363
380
  'intel': {'id': 'Intel', 'deprecated': False},
364
381
  'intel-acpi': {'id': 'Intel-ACPI', 'deprecated': False},
365
382
  'interbase-1.0': {'id': 'Interbase-1.0', 'deprecated': False},
@@ -369,6 +386,7 @@ LICENSES: dict[str, SPDXLicense] = {
369
386
  'isc-veillard': {'id': 'ISC-Veillard', 'deprecated': False},
370
387
  'jam': {'id': 'Jam', 'deprecated': False},
371
388
  'jasper-2.0': {'id': 'JasPer-2.0', 'deprecated': False},
389
+ 'jove': {'id': 'jove', 'deprecated': False},
372
390
  'jpl-image': {'id': 'JPL-image', 'deprecated': False},
373
391
  'jpnic': {'id': 'JPNIC', 'deprecated': False},
374
392
  'json': {'id': 'JSON', 'deprecated': False},
@@ -394,6 +412,7 @@ LICENSES: dict[str, SPDXLicense] = {
394
412
  'lgpl-3.0-or-later': {'id': 'LGPL-3.0-or-later', 'deprecated': False},
395
413
  'lgpllr': {'id': 'LGPLLR', 'deprecated': False},
396
414
  'libpng': {'id': 'Libpng', 'deprecated': False},
415
+ 'libpng-1.6.35': {'id': 'libpng-1.6.35', 'deprecated': False},
397
416
  'libpng-2.0': {'id': 'libpng-2.0', 'deprecated': False},
398
417
  'libselinux-1.0': {'id': 'libselinux-1.0', 'deprecated': False},
399
418
  'libtiff': {'id': 'libtiff', 'deprecated': False},
@@ -424,14 +443,17 @@ LICENSES: dict[str, SPDXLicense] = {
424
443
  'magaz': {'id': 'magaz', 'deprecated': False},
425
444
  'mailprio': {'id': 'mailprio', 'deprecated': False},
426
445
  'makeindex': {'id': 'MakeIndex', 'deprecated': False},
446
+ 'man2html': {'id': 'man2html', 'deprecated': False},
427
447
  'martin-birgmeier': {'id': 'Martin-Birgmeier', 'deprecated': False},
428
448
  'mcphee-slideshow': {'id': 'McPhee-slideshow', 'deprecated': False},
429
449
  'metamail': {'id': 'metamail', 'deprecated': False},
430
450
  'minpack': {'id': 'Minpack', 'deprecated': False},
451
+ 'mips': {'id': 'MIPS', 'deprecated': False},
431
452
  'miros': {'id': 'MirOS', 'deprecated': False},
432
453
  'mit': {'id': 'MIT', 'deprecated': False},
433
454
  'mit-0': {'id': 'MIT-0', 'deprecated': False},
434
455
  'mit-advertising': {'id': 'MIT-advertising', 'deprecated': False},
456
+ 'mit-click': {'id': 'MIT-Click', 'deprecated': False},
435
457
  'mit-cmu': {'id': 'MIT-CMU', 'deprecated': False},
436
458
  'mit-enna': {'id': 'MIT-enna', 'deprecated': False},
437
459
  'mit-feh': {'id': 'MIT-feh', 'deprecated': False},
@@ -472,6 +494,7 @@ LICENSES: dict[str, SPDXLicense] = {
472
494
  'netcdf': {'id': 'NetCDF', 'deprecated': False},
473
495
  'newsletr': {'id': 'Newsletr', 'deprecated': False},
474
496
  'ngpl': {'id': 'NGPL', 'deprecated': False},
497
+ 'ngrep': {'id': 'ngrep', 'deprecated': False},
475
498
  'nicta-1.0': {'id': 'NICTA-1.0', 'deprecated': False},
476
499
  'nist-pd': {'id': 'NIST-PD', 'deprecated': False},
477
500
  'nist-pd-fallback': {'id': 'NIST-PD-fallback', 'deprecated': False},
@@ -486,6 +509,7 @@ LICENSES: dict[str, SPDXLicense] = {
486
509
  'npl-1.1': {'id': 'NPL-1.1', 'deprecated': False},
487
510
  'nposl-3.0': {'id': 'NPOSL-3.0', 'deprecated': False},
488
511
  'nrl': {'id': 'NRL', 'deprecated': False},
512
+ 'ntia-pd': {'id': 'NTIA-PD', 'deprecated': False},
489
513
  'ntp': {'id': 'NTP', 'deprecated': False},
490
514
  'ntp-0': {'id': 'NTP-0', 'deprecated': False},
491
515
  'nunit': {'id': 'Nunit', 'deprecated': True},
@@ -580,6 +604,7 @@ LICENSES: dict[str, SPDXLicense] = {
580
604
  'schemereport': {'id': 'SchemeReport', 'deprecated': False},
581
605
  'sendmail': {'id': 'Sendmail', 'deprecated': False},
582
606
  'sendmail-8.23': {'id': 'Sendmail-8.23', 'deprecated': False},
607
+ 'sendmail-open-source-1.1': {'id': 'Sendmail-Open-Source-1.1', 'deprecated': False},
583
608
  'sgi-b-1.0': {'id': 'SGI-B-1.0', 'deprecated': False},
584
609
  'sgi-b-1.1': {'id': 'SGI-B-1.1', 'deprecated': False},
585
610
  'sgi-b-2.0': {'id': 'SGI-B-2.0', 'deprecated': False},
@@ -592,10 +617,12 @@ LICENSES: dict[str, SPDXLicense] = {
592
617
  'sissl-1.2': {'id': 'SISSL-1.2', 'deprecated': False},
593
618
  'sl': {'id': 'SL', 'deprecated': False},
594
619
  'sleepycat': {'id': 'Sleepycat', 'deprecated': False},
620
+ 'smail-gpl': {'id': 'SMAIL-GPL', 'deprecated': False},
595
621
  'smlnj': {'id': 'SMLNJ', 'deprecated': False},
596
622
  'smppl': {'id': 'SMPPL', 'deprecated': False},
597
623
  'snia': {'id': 'SNIA', 'deprecated': False},
598
624
  'snprintf': {'id': 'snprintf', 'deprecated': False},
625
+ 'sofa': {'id': 'SOFA', 'deprecated': False},
599
626
  'softsurfer': {'id': 'softSurfer', 'deprecated': False},
600
627
  'soundex': {'id': 'Soundex', 'deprecated': False},
601
628
  'spencer-86': {'id': 'Spencer-86', 'deprecated': False},
@@ -609,6 +636,7 @@ LICENSES: dict[str, SPDXLicense] = {
609
636
  'sspl-1.0': {'id': 'SSPL-1.0', 'deprecated': False},
610
637
  'standardml-nj': {'id': 'StandardML-NJ', 'deprecated': True},
611
638
  'sugarcrm-1.1.3': {'id': 'SugarCRM-1.1.3', 'deprecated': False},
639
+ 'sul-1.0': {'id': 'SUL-1.0', 'deprecated': False},
612
640
  'sun-ppp': {'id': 'Sun-PPP', 'deprecated': False},
613
641
  'sun-ppp-2000': {'id': 'Sun-PPP-2000', 'deprecated': False},
614
642
  'sunpro': {'id': 'SunPro', 'deprecated': False},
@@ -620,12 +648,14 @@ LICENSES: dict[str, SPDXLicense] = {
620
648
  'tcp-wrappers': {'id': 'TCP-wrappers', 'deprecated': False},
621
649
  'termreadkey': {'id': 'TermReadKey', 'deprecated': False},
622
650
  'tgppl-1.0': {'id': 'TGPPL-1.0', 'deprecated': False},
651
+ 'thirdeye': {'id': 'ThirdEye', 'deprecated': False},
623
652
  'threeparttable': {'id': 'threeparttable', 'deprecated': False},
624
653
  'tmate': {'id': 'TMate', 'deprecated': False},
625
654
  'torque-1.1': {'id': 'TORQUE-1.1', 'deprecated': False},
626
655
  'tosl': {'id': 'TOSL', 'deprecated': False},
627
656
  'tpdl': {'id': 'TPDL', 'deprecated': False},
628
657
  'tpl-1.0': {'id': 'TPL-1.0', 'deprecated': False},
658
+ 'trustedqsl': {'id': 'TrustedQSL', 'deprecated': False},
629
659
  'ttwl': {'id': 'TTWL', 'deprecated': False},
630
660
  'ttyp0': {'id': 'TTYP0', 'deprecated': False},
631
661
  'tu-berlin-1.0': {'id': 'TU-Berlin-1.0', 'deprecated': False},
@@ -641,6 +671,8 @@ LICENSES: dict[str, SPDXLicense] = {
641
671
  'unicode-tou': {'id': 'Unicode-TOU', 'deprecated': False},
642
672
  'unixcrypt': {'id': 'UnixCrypt', 'deprecated': False},
643
673
  'unlicense': {'id': 'Unlicense', 'deprecated': False},
674
+ 'unlicense-libtelnet': {'id': 'Unlicense-libtelnet', 'deprecated': False},
675
+ 'unlicense-libwhirlpool': {'id': 'Unlicense-libwhirlpool', 'deprecated': False},
644
676
  'upl-1.0': {'id': 'UPL-1.0', 'deprecated': False},
645
677
  'urt-rle': {'id': 'URT-RLE', 'deprecated': False},
646
678
  'vim': {'id': 'Vim', 'deprecated': False},
@@ -654,6 +686,7 @@ LICENSES: dict[str, SPDXLicense] = {
654
686
  'widget-workshop': {'id': 'Widget-Workshop', 'deprecated': False},
655
687
  'wsuipa': {'id': 'Wsuipa', 'deprecated': False},
656
688
  'wtfpl': {'id': 'WTFPL', 'deprecated': False},
689
+ 'wwl': {'id': 'wwl', 'deprecated': False},
657
690
  'wxwindows': {'id': 'wxWindows', 'deprecated': True},
658
691
  'x11': {'id': 'X11', 'deprecated': False},
659
692
  'x11-distribute-modifications-variant': {'id': 'X11-distribute-modifications-variant', 'deprecated': False},
@@ -695,9 +728,11 @@ EXCEPTIONS: dict[str, SPDXException] = {
695
728
  'bison-exception-1.24': {'id': 'Bison-exception-1.24', 'deprecated': False},
696
729
  'bison-exception-2.2': {'id': 'Bison-exception-2.2', 'deprecated': False},
697
730
  'bootloader-exception': {'id': 'Bootloader-exception', 'deprecated': False},
731
+ 'cgal-linking-exception': {'id': 'CGAL-linking-exception', 'deprecated': False},
698
732
  'classpath-exception-2.0': {'id': 'Classpath-exception-2.0', 'deprecated': False},
699
733
  'clisp-exception-2.0': {'id': 'CLISP-exception-2.0', 'deprecated': False},
700
734
  'cryptsetup-openssl-exception': {'id': 'cryptsetup-OpenSSL-exception', 'deprecated': False},
735
+ 'digia-qt-lgpl-exception-1.1': {'id': 'Digia-Qt-LGPL-exception-1.1', 'deprecated': False},
701
736
  'digirule-foss-exception': {'id': 'DigiRule-FOSS-exception', 'deprecated': False},
702
737
  'ecos-exception-2.0': {'id': 'eCos-exception-2.0', 'deprecated': False},
703
738
  'erlang-otp-linking-exception': {'id': 'erlang-otp-linking-exception', 'deprecated': False},
@@ -714,13 +749,16 @@ EXCEPTIONS: dict[str, SPDXException] = {
714
749
  'gnome-examples-exception': {'id': 'GNOME-examples-exception', 'deprecated': False},
715
750
  'gnu-compiler-exception': {'id': 'GNU-compiler-exception', 'deprecated': False},
716
751
  'gnu-javamail-exception': {'id': 'gnu-javamail-exception', 'deprecated': False},
752
+ 'gpl-3.0-389-ds-base-exception': {'id': 'GPL-3.0-389-ds-base-exception', 'deprecated': False},
717
753
  'gpl-3.0-interface-exception': {'id': 'GPL-3.0-interface-exception', 'deprecated': False},
718
754
  'gpl-3.0-linking-exception': {'id': 'GPL-3.0-linking-exception', 'deprecated': False},
719
755
  'gpl-3.0-linking-source-exception': {'id': 'GPL-3.0-linking-source-exception', 'deprecated': False},
720
756
  'gpl-cc-1.0': {'id': 'GPL-CC-1.0', 'deprecated': False},
721
757
  'gstreamer-exception-2005': {'id': 'GStreamer-exception-2005', 'deprecated': False},
722
758
  'gstreamer-exception-2008': {'id': 'GStreamer-exception-2008', 'deprecated': False},
759
+ 'harbour-exception': {'id': 'harbour-exception', 'deprecated': False},
723
760
  'i2p-gpl-java-exception': {'id': 'i2p-gpl-java-exception', 'deprecated': False},
761
+ 'independent-modules-exception': {'id': 'Independent-modules-exception', 'deprecated': False},
724
762
  'kicad-libraries-exception': {'id': 'KiCad-libraries-exception', 'deprecated': False},
725
763
  'lgpl-3.0-linking-exception': {'id': 'LGPL-3.0-linking-exception', 'deprecated': False},
726
764
  'libpri-openh323-exception': {'id': 'libpri-OpenH323-exception', 'deprecated': False},
@@ -730,12 +768,14 @@ EXCEPTIONS: dict[str, SPDXException] = {
730
768
  'llvm-exception': {'id': 'LLVM-exception', 'deprecated': False},
731
769
  'lzma-exception': {'id': 'LZMA-exception', 'deprecated': False},
732
770
  'mif-exception': {'id': 'mif-exception', 'deprecated': False},
771
+ 'mxml-exception': {'id': 'mxml-exception', 'deprecated': False},
733
772
  'nokia-qt-exception-1.1': {'id': 'Nokia-Qt-exception-1.1', 'deprecated': True},
734
773
  'ocaml-lgpl-linking-exception': {'id': 'OCaml-LGPL-linking-exception', 'deprecated': False},
735
774
  'occt-exception-1.0': {'id': 'OCCT-exception-1.0', 'deprecated': False},
736
775
  'openjdk-assembly-exception-1.0': {'id': 'OpenJDK-assembly-exception-1.0', 'deprecated': False},
737
776
  'openvpn-openssl-exception': {'id': 'openvpn-openssl-exception', 'deprecated': False},
738
777
  'pcre2-exception': {'id': 'PCRE2-exception', 'deprecated': False},
778
+ 'polyparse-exception': {'id': 'polyparse-exception', 'deprecated': False},
739
779
  'ps-or-pdf-font-exception-20170817': {'id': 'PS-or-PDF-font-exception-20170817', 'deprecated': False},
740
780
  'qpl-1.0-inria-2004-exception': {'id': 'QPL-1.0-INRIA-2004-exception', 'deprecated': False},
741
781
  'qt-gpl-exception-1.0': {'id': 'Qt-GPL-exception-1.0', 'deprecated': False},
@@ -8,7 +8,7 @@ import operator
8
8
  import os
9
9
  import platform
10
10
  import sys
11
- from typing import AbstractSet, Any, Callable, Literal, TypedDict, Union, cast
11
+ from typing import AbstractSet, Callable, Literal, Mapping, TypedDict, Union, cast
12
12
 
13
13
  from ._parser import MarkerAtom, MarkerList, Op, Value, Variable
14
14
  from ._parser import parse_marker as _parse_marker
@@ -17,6 +17,7 @@ from .specifiers import InvalidSpecifier, Specifier
17
17
  from .utils import canonicalize_name
18
18
 
19
19
  __all__ = [
20
+ "Environment",
20
21
  "EvaluateContext",
21
22
  "InvalidMarker",
22
23
  "Marker",
@@ -28,6 +29,12 @@ __all__ = [
28
29
  Operator = Callable[[str, Union[str, AbstractSet[str]]], bool]
29
30
  EvaluateContext = Literal["metadata", "lock_file", "requirement"]
30
31
  MARKERS_ALLOWING_SET = {"extras", "dependency_groups"}
32
+ MARKERS_REQUIRING_VERSION = {
33
+ "implementation_version",
34
+ "platform_release",
35
+ "python_full_version",
36
+ "python_version",
37
+ }
31
38
 
32
39
 
33
40
  class InvalidMarker(ValueError):
@@ -121,20 +128,28 @@ class Environment(TypedDict):
121
128
  """
122
129
 
123
130
 
124
- def _normalize_extra_values(results: Any) -> Any:
131
+ def _normalize_extras(
132
+ result: MarkerList | MarkerAtom | str,
133
+ ) -> MarkerList | MarkerAtom | str:
134
+ if not isinstance(result, tuple):
135
+ return result
136
+
137
+ lhs, op, rhs = result
138
+ if isinstance(lhs, Variable) and lhs.value == "extra":
139
+ normalized_extra = canonicalize_name(rhs.value)
140
+ rhs = Value(normalized_extra)
141
+ elif isinstance(rhs, Variable) and rhs.value == "extra":
142
+ normalized_extra = canonicalize_name(lhs.value)
143
+ lhs = Value(normalized_extra)
144
+ return lhs, op, rhs
145
+
146
+
147
+ def _normalize_extra_values(results: MarkerList) -> MarkerList:
125
148
  """
126
149
  Normalize extra values.
127
150
  """
128
- if isinstance(results[0], tuple):
129
- lhs, op, rhs = results[0]
130
- if isinstance(lhs, Variable) and lhs.value == "extra":
131
- normalized_extra = canonicalize_name(rhs.value)
132
- rhs = Value(normalized_extra)
133
- elif isinstance(rhs, Variable) and rhs.value == "extra":
134
- normalized_extra = canonicalize_name(lhs.value)
135
- lhs = Value(normalized_extra)
136
- results[0] = lhs, op, rhs
137
- return results
151
+
152
+ return [_normalize_extras(r) for r in results]
138
153
 
139
154
 
140
155
  def _format_marker(
@@ -168,25 +183,26 @@ def _format_marker(
168
183
  _operators: dict[str, Operator] = {
169
184
  "in": lambda lhs, rhs: lhs in rhs,
170
185
  "not in": lambda lhs, rhs: lhs not in rhs,
171
- "<": operator.lt,
172
- "<=": operator.le,
186
+ "<": lambda _lhs, _rhs: False,
187
+ "<=": operator.eq,
173
188
  "==": operator.eq,
174
189
  "!=": operator.ne,
175
- ">=": operator.ge,
176
- ">": operator.gt,
190
+ ">=": operator.eq,
191
+ ">": lambda _lhs, _rhs: False,
177
192
  }
178
193
 
179
194
 
180
- def _eval_op(lhs: str, op: Op, rhs: str | AbstractSet[str]) -> bool:
181
- if isinstance(rhs, str):
195
+ def _eval_op(lhs: str, op: Op, rhs: str | AbstractSet[str], *, key: str) -> bool:
196
+ op_str = op.serialize()
197
+ if key in MARKERS_REQUIRING_VERSION:
182
198
  try:
183
- spec = Specifier("".join([op.serialize(), rhs]))
199
+ spec = Specifier(f"{op_str}{rhs}")
184
200
  except InvalidSpecifier:
185
201
  pass
186
202
  else:
187
203
  return spec.contains(lhs, prereleases=True)
188
204
 
189
- oper: Operator | None = _operators.get(op.serialize())
205
+ oper: Operator | None = _operators.get(op_str)
190
206
  if oper is None:
191
207
  raise UndefinedComparison(f"Undefined {op!r} on {lhs!r} and {rhs!r}.")
192
208
 
@@ -196,13 +212,14 @@ def _eval_op(lhs: str, op: Op, rhs: str | AbstractSet[str]) -> bool:
196
212
  def _normalize(
197
213
  lhs: str, rhs: str | AbstractSet[str], key: str
198
214
  ) -> tuple[str, str | AbstractSet[str]]:
199
- # PEP 685 Comparison of extra names for optional distribution dependencies
215
+ # PEP 685 - Comparison of extra names for optional distribution dependencies
200
216
  # https://peps.python.org/pep-0685/
201
217
  # > When comparing extra names, tools MUST normalize the names being
202
218
  # > compared using the semantics outlined in PEP 503 for names
203
219
  if key == "extra":
204
220
  assert isinstance(rhs, str), "extra value must be a string"
205
- return (canonicalize_name(lhs), canonicalize_name(rhs))
221
+ # Both sides are normalized at this point already
222
+ return (lhs, rhs)
206
223
  if key in MARKERS_ALLOWING_SET:
207
224
  if isinstance(rhs, str): # pragma: no cover
208
225
  return (canonicalize_name(lhs), canonicalize_name(rhs))
@@ -219,8 +236,6 @@ def _evaluate_markers(
219
236
  groups: list[list[bool]] = [[]]
220
237
 
221
238
  for marker in markers:
222
- assert isinstance(marker, (list, tuple, str))
223
-
224
239
  if isinstance(marker, list):
225
240
  groups[-1].append(_evaluate_markers(marker, environment))
226
241
  elif isinstance(marker, tuple):
@@ -234,13 +249,16 @@ def _evaluate_markers(
234
249
  lhs_value = lhs.value
235
250
  environment_key = rhs.value
236
251
  rhs_value = environment[environment_key]
252
+
237
253
  assert isinstance(lhs_value, str), "lhs must be a string"
238
254
  lhs_value, rhs_value = _normalize(lhs_value, rhs_value, key=environment_key)
239
- groups[-1].append(_eval_op(lhs_value, op, rhs_value))
240
- else:
241
- assert marker in ["and", "or"]
242
- if marker == "or":
243
- groups.append([])
255
+ groups[-1].append(_eval_op(lhs_value, op, rhs_value, key=environment_key))
256
+ elif marker == "or":
257
+ groups.append([])
258
+ elif marker == "and":
259
+ pass
260
+ else: # pragma: nocover
261
+ raise TypeError(f"Unexpected marker {marker!r}")
244
262
 
245
263
  return any(all(item) for item in groups)
246
264
 
@@ -276,6 +294,11 @@ class Marker:
276
294
  # Note: We create a Marker object without calling this constructor in
277
295
  # packaging.requirements.Requirement. If any additional logic is
278
296
  # added here, make sure to mirror/adapt Requirement.
297
+
298
+ # If this fails and throws an error, the repr still expects _markers to
299
+ # be defined.
300
+ self._markers: MarkerList = []
301
+
279
302
  try:
280
303
  self._markers = _normalize_extra_values(_parse_marker(marker))
281
304
  # The attribute `_markers` can be described in terms of a recursive type:
@@ -301,12 +324,12 @@ class Marker:
301
324
  return _format_marker(self._markers)
302
325
 
303
326
  def __repr__(self) -> str:
304
- return f"<Marker('{self}')>"
327
+ return f"<{self.__class__.__name__}('{self}')>"
305
328
 
306
329
  def __hash__(self) -> int:
307
- return hash((self.__class__.__name__, str(self)))
330
+ return hash(str(self))
308
331
 
309
- def __eq__(self, other: Any) -> bool:
332
+ def __eq__(self, other: object) -> bool:
310
333
  if not isinstance(other, Marker):
311
334
  return NotImplemented
312
335
 
@@ -314,7 +337,7 @@ class Marker:
314
337
 
315
338
  def evaluate(
316
339
  self,
317
- environment: dict[str, str] | None = None,
340
+ environment: Mapping[str, str | AbstractSet[str]] | None = None,
318
341
  context: EvaluateContext = "metadata",
319
342
  ) -> bool:
320
343
  """Evaluate a marker.
@@ -337,12 +360,15 @@ class Marker:
337
360
  )
338
361
  elif context == "metadata":
339
362
  current_environment["extra"] = ""
363
+
340
364
  if environment is not None:
341
365
  current_environment.update(environment)
342
- # The API used to allow setting extra to None. We need to handle this
343
- # case for backwards compatibility.
344
- if "extra" in current_environment and current_environment["extra"] is None:
345
- current_environment["extra"] = ""
366
+ if "extra" in current_environment:
367
+ # The API used to allow setting extra to None. We need to handle
368
+ # this case for backwards compatibility. Also skip running
369
+ # normalize name if extra is empty.
370
+ extra = cast("str | None", current_environment["extra"])
371
+ current_environment["extra"] = canonicalize_name(extra) if extra else ""
346
372
 
347
373
  return _evaluate_markers(
348
374
  self._markers, _repair_python_full_version(current_environment)
@@ -356,7 +382,7 @@ def _repair_python_full_version(
356
382
  Work around platform.python_version() returning something that is not PEP 440
357
383
  compliant for non-tagged Python builds.
358
384
  """
359
- python_full_version = cast(str, env["python_full_version"])
385
+ python_full_version = cast("str", env["python_full_version"])
360
386
  if python_full_version.endswith("+"):
361
387
  env["python_full_version"] = f"{python_full_version}local"
362
388
  return env