1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
|
- = Python Packaging Guidelines
- :last-reviewed: 2024-04-03
- ////
- Additional style notes:
- - Normative points are at the beginnings of sections
- and include highlighted keywords like **MUST** or **SHOULD**.
- So, if a reader only wants the rules,
- they can skip remainders of sections
- (discussion, examples, clarifications, ...)
- without missing context.
- - Some sections have additional IDs
- (see https://docs.asciidoctor.org/asciidoc/latest/sections/custom-ids/ )
- to avoid breaking links to removed/renamed sections.
- - In text, macros appear as Literal Monospace with a leading percent sign.
- Use curly braces for value-like macros, but not command-like macros
- (for example: `%{version}` but `%autosetup` or `%check`).
- - The first mention of a macro generally links to the documentation.
- The link includes some non-monospace text, e.g. "the `+%{version}+` macro".
- (In the current Fedora docs style, links aren't visible in monospace text).
- - The documentation for a macro has the macro's name as ID.
- ////
- This version of Python Packaging Guidelines
- is in effect since 2021
- and represents a major rewrite and paradigm shift.
- Not all packages are updated to reflect this.
- Older guidelines are still being kept up to date,
- and existing packages *MAY* use them instead of this document:
- * xref:Python_201x.adoc[“201x-era” Python packaging guidelines]
- (Packages using these usually use the
- <<py3_install,`+%py3_install+`>>
- or <<py3_install_wheel,`+%py3_install_wheel+` macro>>
- or call `+setup.py install+`.)
- * xref:Python_Appendix.adoc#_python_2_packages[Python 2 appendix]
- Note that Python 2 packages require a FESCo exception.
- ////
- NOTE: A summary of changes from the older guidelines
- is available at https://hackmd.io/@python-maint/rJmQQc4DP
- ////
- NOTE: These guidelines only support current Fedora releases.
- For older releases (such as in EPEL 8),
- consult the xref:Python_201x.adoc[201x-era guidelines].
- The two <<Distro-wide guidelines>> below
- apply to all software in Fedora that uses Python at build- or run-time.
- The rest of the Guidelines apply to packages that ship code
- that can be imported with Python’s `+import+` statement.
- Specifically, that is all packages
- that install files under `+/usr/lib*/python*/+`.
- Except for the two “Distro-wide guidelines”,
- these Guidelines do not apply to simple one-file scripts or utilities,
- especially if these are included with software
- not written in Python.
- However, if an application (e.g. CLI tool, script or GUI app)
- needs a more complex Python library,
- the library *SHOULD* be packaged as an importable library
- under these guidelines.
- A major goal for Python packaging in Fedora is to
- _harmonize with the wider Python ecosystem_,
- that is,
- the https://pypa.io[Python Packaging Authority] (PyPA) standards
- and the https://pypi.org/[Python Package Index] (PyPI).
- Packagers *SHOULD* be prepared to get involved with upstream projects
- to establish best practices as outlined here.
- We wish to improve both Fedora and the wider Python ecosystem.
- NOTE: Some build tools (like CMake or autotools)
- may not work with the latest PyPA standards yet.
- (For example, they might generate `+.egg-info+` directories
- rather than `+.dist-info+`.)
- While this document's normative points (MUST/SHOULD) are tool-agnostic,
- many of the practical tips and helper macros will not be applicable.
- If this affects you, consider contacting the
- https://lists.fedoraproject.org/archives/list/python-devel@lists.fedoraproject.org/[Python SIG]
- for guidance
- and/or following the xref:Python_201x.adoc[older guidelines]
- for the time being.
- NOTE: Fedora’s Python SIG not only develops these guidelines,
- but it’s also involved in PyPA standards and Python packaging best practices.
- Check out https://fedoraproject.org/wiki/SIGs/Python[the wiki] or
- https://lists.fedoraproject.org/archives/list/python-devel@lists.fedoraproject.org/[mailing list]
- if you need help or wish to help out.
- == Distro-wide guidelines
- === BuildRequire python3-devel
- *Every* package that uses Python (at runtime and/or build time)
- and/or installs Python modules
- *MUST* explicitly BuildRequire `+python3-devel+`,
- even if Python is not actually invoked during build time.
- Such package *MUST* include `+BuildRequires: python3-devel+` in its `+.spec+` file
- or use <<pyproject_buildrequires,the `+%pyproject_buildrequires+` macro>>
- in the `+%generate_buildrequires+` section.
- If the package uses an alternate Python interpreter instead of `+python3+`
- (e.g. `+pypy+`, `+jython+`, `+python2.7+`),
- it *MAY* instead require the corresponding `+*-devel+` package.
- The `+*-devel+` package brings in relevant RPM macros.
- It may also enable automated or manual checks: for example,
- Python maintainers use this requirement to list packages
- that use Python in some way
- and might be affected by planned changes.
- === Mandatory macros
- The following macros *MUST* be used where applicable.
- The expansions in parentheses are provided only as reference/examples.
- The macros are defined for you in all supported Fedora and EPEL
- versions.
- // Keep the list synced with "Macro Reference" below
- * `+%{python3}+` (`+/usr/bin/python3+`):
- The Python interpreter.
- For example, this macro should be
- used for invoking Python from a `+spec+` file script,
- passed to `+configure+` scripts to select a Python executable,
- or used as `+%{python3} -m pip+` to run a Python-based tool.
- +
- If the packaged software invokes Python at _run time_
- (as opposed to running Python to build/test it),
- it might be necessary to pass flags to `+%{python3}+`
- to isolate it from user-installed packages.
- See <<Shebangs>> for details.
- +
- * `+%{python3_version}+` (e.g. `+3.9+`, `+3.10+`):
- Version of the Python interpreter.
- +
- * `+%{python3_version_nodots}+` (e.g. `+39+`, `+310+`):
- Version of the Python interpreter without the dot.
- * `+%{python3_sitelib}+` (e.g. `+/usr/lib/python3.9/site-packages+`):
- Where pure-Python modules are installed.
- +
- * `+%{python3_sitearch}+` (e.g. `+/usr/lib64/python3.9/site-packages+`):
- Where Python extension modules (native code, e.g. compiled from C) are
- installed.
- The rest of this document uses these macros,
- along with `+%{_bindir}+` (`+/usr/bin/+`),
- instead of the raw path names.
- === Python implementation support[[_multiple_python_runtimes]]
- Fedora primarily targets _CPython_,
- the reference implementation of the Python language.
- We generally use “Python” to mean CPython.
- Alternate implementations like `+pypy+` are available,
- but currently lack comprehensive tooling and guidelines for packaging.
- When targetting these, there are no hard rules
- (except the general Fedora packaging guidelines).
- But please try to abide by the _spirit_ of these guidelines.
- When in doubt, consider consulting the Python SIG.
- === Python version support
- Fedora packages *MUST NOT* depend on other versions
- of the CPython interpreter
- than the current `+python3+`.
- In Fedora, Python libraries are packaged for a single version of Python,
- called `+python3+`.
- For example, in Fedora 32, `+python3+` is Python 3.8.
- In the past, there were multiple Python stacks,
- e.g. `+python3.7+` and `+python2.7+`,
- installable together on the same machine.
- That is also the case in some projects that build _on top_ of Fedora,
- like RHEL, EPEL and CentOS.
- Fedora might re-introduce parallell-installable stacks in the future
- (for example if a switch to a new Python version needs a transition period,
- or if enough interested maintainers somehow appear).
- Fedora does include alternate interpreter versions,
- e.g. `+python2.7+` or `+python3.5+`,
- but these are meant only for developers that need to test upstream code.
- Bug and security fixes for these interpreters only cover this use case.
- Packages such as `+pip+` or `+tox+`,
- which enable setting up isolated environments
- and installing third-party packages into them,
- *MAY*, as an exception to the rule above, use these interpreters
- as long as this is coordinated with the maintainers
- of the relevant Python interpreter.
- == Naming
- Python packages have several different names,
- which should be kept in sync but will sometimes differ
- for historical or practical reasons.
- They are:
- * the Fedora _source package name_ (or _component name_, `+%{name}+`),
- * the Fedora _built RPM name_,
- * the _project name_ used on https://pypi.org/[PyPI]
- or by https://pip.pypa.io[pip], and
- * the _importable module name_ used in Python
- (a single package may have multiple importable modules).
- Some examples (both good and worse):
- [cols=",,,",options="header",]
- |===
- |Fedora component |Built RPM |Project name |Importable module
- |`+python-requests+` |`+python3-requests+` |`+requests+` |`+requests+`
- |`+python-django+` |`+python3-django+` |`+Django+` |`+django+`
- |`+PyYAML+` |`+python3-pyyaml+` |`+pyyaml+` |`+yaml+`
- |`+python-ldap+` |`+python3-ldap+` |`+python-ldap+` |`+ldap+`, `+ldif+`, etc.
- |`+python-pillow+` |`+python3-pillow+` |`+pillow+` |`+PIL+`
- |`+python-jupyter-client+` |`+python3-jupyter-client+` |`+jupyter-client+` |`+jupyter_client+`
- |===
- Elsewhere in this text,
- the metavariables `+SRPMNAME+`, `+RPMNAME+`, `+PROJECTNAME+`, `+MODNAME+`
- refer to these names, respectively.
- === Canonical project name
- Most of these names are case-sensitive machine-friendly identifiers,
- but the _project name_ has human-friendly semantics:
- it is case-insensitive
- and treats some sets of characters (like `+._-+`) specially.
- For automated use,
- it needs to be normalized to a canonical format
- used by Python tools and services such as setuptools, pip and PyPI.
- For example, the canonical name of the `+Django+` project
- is `+django+` (in lowercase).
- This normalization is defined in
- https://www.python.org/dev/peps/pep-0503/#normalized-names[PEP 503],
- and <<py_dist_name,the `+%{py_dist_name}+` macro>> implements it
- for Fedora packaging.
- The canonical name is obtained by switching the project name to lower case
- and converting all runs of non-alphanumeric characters to single “-” characters.
- Example: “The $$$ Tree” becomes “the-tree”.
- Elsewhere in this text,
- the metavariable `+DISTNAME+` refers to the canonical form of the project name.
- Note that in some places, the original,
- non-normalized project name must be used.
- For example,
- the <<pypi_source,`+%pypi_source+` macro>> and the `+%autosetup+` macro
- need `+Django+`, not `+django+`.
- === Name limitations
- The character `pass:[+]` in names of built (i.e. non-SRPM) packages
- that include `+.dist-info+` or `+.egg-info+` directories
- is reserved for <<Extras>> and *MUST NOT* be used for any other purpose.
- As an exception, `pass:[+]` characters *MAY* appear at the _end_ of such names.
- The `pass:[+]` character triggers
- the automatic dependency generator for extras.
- Replace any `pass:[+]` signs in the upstream name with `+-+`.
- Omit `pass:[+]` signs on the beginning of the name.
- Consider adding `Provides` for the original name with `pass:[+]` characters
- to make the package easier to find for users.
- === Library naming
- A built (i.e. non-SRPM) package for a _Python library_
- *MUST* be named with the prefix `+python3-+`.
- A source package containing primarily a _Python library_
- *MUST* be named with the prefix `+python-+`.
- The Fedora package’s name *SHOULD* contain
- the <<Canonical project name>>.
- If possible, the project name *SHOULD* be the same
- as the name of the main importable module,
- in lowercase,
- with underscores (`+_+`) replaced by dashes (`+-+`).
- If the importable module name and the project name do not match,
- users frequently end up confused.
- In this case, packagers *SHOULD* ensure that upstream is aware of the problem
- and (especially for new packages where renaming is feasible)
- strive to get the package renamed.
- The Python SIG is available for assistance.
- A _Python library_ is a package meant to be imported in Python,
- such as with `+import requests+`.
- Tools like _Ansible_ or _IDLE_, whose code is importable
- but not primarily meant to be imported from other software,
- are not considered libraries in this sense.
- So, this section does not apply for them.
- (See the
- xref:index#_libraries_and_applications[general Libraries and Applications guidelines]
- for general guidance.)
- The Fedora component (source package) name for a library
- should be formed by taking the _canonical project name_
- and prepending `+python-+` if it does not already start with `+python-+`.
- This may leads to conflicts
- (e.g. between https://pypi.org/project/bugzilla/[bugzilla]
- and https://pypi.org/project/python-bugzilla/[python-bugzilla]).
- In that case, ensure upstream is aware of the potentially confusing naming
- and apply best judgment.
- === Application naming
- Packages that primarily provide applications, services
- or any kind of executables *SHOULD* be named
- according to the general xref:Naming.adoc[Fedora naming guidelines]
- (e.g. `+ansible+`).
- Consider adding a virtual provide according to <<Library naming>> above
- (e.g. `+python3-PROJECTNAME+`),
- if it would help users find the package.
- == Files to include
- === Source files and bytecode cache[[_byte_compiling]]
- Packages *MUST* include the source file (`+*.py+`)
- *AND* the bytecode cache (`+*.pyc+`) for each pure-Python importable module.
- The source files *MUST* be included in the same package as the bytecode cache.
- Scripts that are not importable
- (typically ones in `+%{_bindir}+` or `+%{_libexecdir}+`)
- *SHOULD NOT* be byte-compiled.
- The cache files are found in a `+__pycache__+` directory
- and have an interpreter-dependent suffix like `+.cpython-39.pyc+`.
- The cache is not necessary to run the software,
- but if it is not found, Python will try to create it when a module is imported.
- If this succeeds, the file is not tracked by RPM
- and it will linger on the system after uninstallation.
- If it does not succeed, users can get spurious SELinux AVC denials in the logs.
- Normally, byte compilation (generating the cache files)
- is done for you by the `+brp-python-bytecompile+`
- xref:index.adoc#_brp_buildroot_policy_scripts[BRP script],
- which runs automatically
- after the `+%install+` section of the spec file has been processed.
- It byte-compiles any `+.py+` files that it finds
- in `+%{python3_sitelib}+` or `+%{python3_sitearch}+`.
- You must include these files of your package
- (i.e. in the `+%files+` section).
- If the code is in a subdirectory (importable package),
- include the entire directory:
- [source,spec]
- ----
- %files
- %{python3_sitelib}/foo/
- ----
- Adding the trailing slash is best practice for directories.
- However, this cannot be used for top-level modules (those directly in
- e.g. `+%{python3_sitelib}+`), because both `+%{python3_sitelib}+` and
- `+%{python3_sitelib}/__pycache__/+` are owned by Python itself. Here, the
- `+%pycached+` macro can help. It expands to the given `+*.py+` source file
- and its corresponding cache file(s). For example:
- [source,spec]
- ----
- %files
- %pycached %{python3_sitelib}/foo.py
- ----
- expands roughly to:
- [source,spec]
- ----
- %files
- %{python3_sitelib}/foo.py
- %{python3_sitelib}/__pycache__/foo.cpython-3X{,.opt-?}.pyc
- ----
- ==== Manual byte compilation[[manual-bytecompilation]]
- If you need to bytecompile stuff
- outside of `+%{python3_sitelib}+`/`+%{python3_sitearch}+`,
- use the <<py_byte_compile,`+%py_byte_compile+` macro>>.
- For example,
- if your software adds `+%{_datadir}/mypackage+` to Python’s import path
- and imports package `+foo+` from there, you will need to compile `+foo+` with:
- [source,spec]
- ----
- %py_byte_compile %{python3} %{buildroot}%{_datadir}/mypackage/foo/
- ----
- === Dist-info metadata
- Each Python package *MUST* include _Package Distribution Metadata_
- conforming to https://packaging.python.org/specifications/[PyPA specifications]
- (specifically,
- https://packaging.python.org/specifications/recording-installed-packages/[Recording installed projects]).
- The metadata *SHOULD* be included
- in the same subpackage as the main importable module,
- if there is one.
- This applies to libraries (e.g. `+python-requests+`)
- as well as tools (e.g. `+ansible+`).
- When software is split into several subpackages,
- it is OK to only ship metadata in one built RPM.
- In this case, consider working with upstream
- to also split the upstream project.
- The metadata takes the form of a `+.dist-info+` directory
- installed in `+%{python3_sitelib}+` or `+%{python3_sitearch}+`,
- and contains information that tools like
- https://docs.python.org/3/library/importlib.metadata.html[`+importlib.metadata+`]
- use to introspect installed libraries.
- For example, a project named `+MyLib+` with importable package `+mylib+`
- could be packaged with:
- [source,spec]
- ----
- %files -p python3-mylib
- %{python3_sitelib}/mylib/
- %{python3_sitelib}/MyLib-%{version}.dist-info/
- %doc README.md
- %license LICENSE.txt
- ----
- Note that some older tools instead put metadata in an `+.egg-info+` directory,
- or even a single file.
- This won’t happen if you use the `+%pyproject_wheel+` macro.
- If your package uses a build system
- that generates an `+.egg-info+` directory or file,
- please contact Python SIG.
- As an exception,
- the Python standard library *MAY* ship without this metadata.
- === Explicit lists
- Packages *MUST NOT* own shared directories owned by Python itself,
- such as the top-level `+__pycache__+` directories
- (`+%{python3_sitelib}/__pycache__+`, `+%{python3_sitearch}/__pycache__+`).
- Similarly to the xref:index#_explicit_lists[general rule],
- packagers *SHOULD NOT* simply glob everything under a shared directory.
- In addition to the xref:index#_explicit_lists[general list],
- the following *SHOULD NOT* be used in `+%files+`:
- * `+%{python3_sitelib}/*+`
- * `+%{python3_sitearch}/*+`
- * `+%{python_sitelib}/*+`
- * `+%{python_sitearch}/*+`
- * `+%pyproject_save_files '*'+`
- * `+%pyproject_save_files +auto+`
- This rule serves as a check against common mistakes
- which are otherwise hard to detect.
- It does limit some possibilities for automation.
- The most common mistakes this rule prevents are:
- * installing a test suite system-wide as an importable module named `+test+`,
- which would then conflict with other such packages, and
- * upstream adding new unexpected importable modules –
- you should always check such changes for
- https://docs.fedoraproject.org/en-US/packaging-guidelines/Conflicts/#_common_conflicting_files_cases_and_solutions[conflicts],
- and keep the list of such files explicit and auditable.
- == PyPI parity
- Every Python package in Fedora *SHOULD* also be available
- on https://pypi.org[the Python Package Index] (PyPI).
- The command `+pip install PROJECTNAME+` *MUST*
- install the same package (possibly in a different version),
- install nothing,
- or fail with a reasonable error message.
- If this is not the case,
- the packager *SHOULD* contact upstream about this.
- The goal is to get the project name registered or blocked on PyPI,
- or to otherwise ensure the rule is followed.
- If your package is not or cannot be published on PyPI, you can:
- * Ask upstream to publish it
- * If you wish: publish it to PyPI yourself and maintain it
- * Ask mailto:python-devel@lists.fedoraproject.org[Python SIG]
- to _block_ the name on PyPI for you
- * Email mailto:admin@pypi.org[PyPI admins] to block the name for you,
- giving the project name and explaining the situation
- (for example: the package cannot currently be installed via `+pip+`).
- You can ask questions and discuss the process at the
- https://discuss.python.org/t/block-names/4045[Python Discourse].
- NOTE: Project names that were in Fedora but not on PyPI
- when these guidelines were proposed are _blocked_ from being uploaded to PyPI.
- This prevents potential trolls from taking them,
- but it also blocks legitimate owners.
- If your package is affected, contact the Python SIG or
- https://github.com/pypa/pypi-support/issues/new?labels=PEP+541&template=pep541-request.md&title=PEP+541+Request%3A+PROJECT_NAME[file a PyPA issue]
- and mention `+@encukou+`.
- If your package’s project name conflicts with a different package on PyPI,
- change the project name.
- As painful as it is,
- we need to use a single global namespace across the Python ecosystem.
- Software that is not written specifically for Fedora already expects
- that project names use the PyPI namespace:
- for example, if a third-party library identifies a dependency by name,
- we don’t want that dependency satisfied by an unrelated Fedora package.
- As always,
- xref:index.adoc#_general_exception_policy[specific exceptions]
- can be granted by the Packaging Committee.
- == Provides and requirements[[_provides]]
- === Provides for importable modules[[_the_py_provides_macro]]
- For any module intended to be used in Python 3 with `+import MODNAME+`,
- the package that includes it *SHOULD* provide `+python3-MODNAME+`,
- with underscores (`+_+`) replaced by dashes (`+-+`).
- This is of course always the case if the package is named `+python3-MODNAME+`.
- If the subpackage has some other name,
- then add `+%py_provides python3-MODNAME+` explicitly.
- See the following section to learn about `+%py_provides+`.
- [#Automatic-unversioned-provides]
- === Automatic python- and python3.X- provides
- For any `+FOO+`,
- a package that provides `+python3-FOO+` *SHOULD* use `+%py_provides+`
- or an automatic generator
- to also provide `+python-FOO+`
- and `+python3.X-FOO+`, where `+X+` is the minor version of the interpreter.
- The provide *SHOULD NOT* be added manually:
- if a generator or macro is not used,
- do not add the `+python-FOO+` / `+python3.X-FOO+` provides at all.
- This is done automatically for package names by a generator.
- If absolutely necessary, the generator can be disabled
- by undefining <<__pythonname_provides,the `+%__pythonname_provides+` macro>>.
- For provides that aren’t package names,
- or (for technical reasons) for packages without files,
- the generator will not work.
- For these cases, the following invocation will provide `+python3-FOO+`,
- `+python-FOO+` and `+python3.X-FOO+`:
- [source,spec]
- ----
- %py_provides python3-FOO
- ----
- Using the generator or macro is important, because the specific form of
- the provide may change in the future.
- [#Machine-readable-provides]
- === Machine-readable provides[[_automatic_provides_with_a_standardized_name]]
- Every Python package *MUST* provide `+python3dist(DISTNAME)+`
- *and* `+python3.Xdist(DISTNAME)+`,
- where `+X+` is the minor version of the interpreter
- and `+DISTNAME+` is the <<Canonical project name>>
- corresponding to the <<Dist-info metadata>>.
- For example, `+python3-django+` would provide
- `+python3dist(django)+` and `+python3.9dist(django)+`.
- This is generated automatically from the dist-info metadata.
- The provide *SHOULD NOT* be added manually:
- if the generator fails to add it, the metadata *MUST* be fixed.
- These _Provides_ are used for automatically generated _Requires_.
- If absolutely necessary,
- the automatic generator can be disabled by undefining the
- <<__pythondist_provides,`+%{?__pythondist_provides}+` macro>>.
- Consider discussing your use case with the Python SIG if you need to do this.
- === Dependencies
- As mentioned above,
- each Python package *MUST* explicitly BuildRequire `+python3-devel+`.
- Packages *MUST NOT* have dependencies (either build-time or runtime)
- with the unversioned prefix `+python-+`
- if the corresponding `+python3-+` dependency can be used instead.
- Packages *SHOULD NOT* have explicit dependencies
- (either build-time or runtime)
- with a minor-version prefix such as `+python3.8-+` or `+python3.8dist(+`.
- Such dependencies *SHOULD* instead be automatically generated
- or a macro should be used to get the version.
- Packages *SHOULD NOT* have an explicit runtime dependency on `+python3+`.
- Instead of depending on `+python3+`,
- packages have an automatic dependency on `+python(abi) = 3.X+`
- when they install files to `+%{python3_sitelib}+` or `+%{python3_sitearch}+`,
- or they have an automatic dependency on `+/usr/bin/python3+`
- if they have executable Python scripts,
- or they have an automatic dependency on `+libpython3.X.so.1.0()+`
- if they embed Python.
- These rules help ensure a smooth upgrade path
- when `+python3+` is updated in new versions of Fedora.
- [#Automatically-generated-dependencies]
- === Automatically generated dependencies[[_requires_and_buildrequires_with_standardized_names]]
- Packages *MUST* use the automatic Python run-time dependency generator.
- Packages *SHOULD* use the opt-in build-dependency generator if possible.
- The packager *MUST* inspect the generated requires for correctness.
- All dependencies *MUST* be resolvable within the targeted Fedora version.
- Any necessary changes *MUST* be done by patches
- or modifying the source (e.g. with `+sed+`),
- rather than disabling the generator.
- The resulting change *SHOULD* be offered to upstream.
- As an exception, xref:AutoProvidesAndRequiresFiltering.adoc[filtering]
- *MAY* be used for temporary workarounds
- and xref:index.adoc#bootstrapping[bootstrapping].
- Dependencies covered by the generators *SHOULD NOT*
- be repeated in the `+.spec+` file.
- (For example, if the generator finds a `+requests+` dependency,
- then `+Requires: python3-requests+` is redundant.)
- The automatically generated requirements
- are in the form `+python3.Xdist(DISTNAME)+`,
- potentially augmented with version requirements or combined together
- with https://rpm-software-management.github.io/rpm/manual/boolean_dependencies.html[rich dependencies].
- Any `+.0+` suffixes are removed from version numbers
- to match the behavior of Python tools.
- (https://www.python.org/dev/peps/pep-0440/[PEP 440] specifies
- that `+X.Y+` and `+X.Y.0+` are treated as equal.)
- Note that the generators only cover Python packages.
- Other dependencies, often C libraries like `+openssl-devel+`,
- must be specified in the `+.spec+` file manually.
- Where the requirements are specified in the source
- depends on each project’s build system and preferences.
- Common locations are `+pyproject.toml+`, `+setup.py+`, `+setup.cfg+`,
- `+config.toml+`.
- ==== Run-time dependency generator
- The automatic runtime dependency generator uses package metadata
- (as recorded in installed `+*.dist-info+` directories)
- to determine what the package depends on.
- In an emergency, you can opt-out from running the requires generator by
- <<python_disable_dependency_generator, adding `+%{?python_disable_dependency_generator}+`>>
- to the package (usually, just before the main package’s `+%description+`).
- ==== Build-time dependency generator
- The opt-in (but strongly recommended) build-time dependency generator
- gathers information from
- https://www.python.org/dev/peps/pep-0517/#source-trees[`+pyproject.toml+` build-system information]
- (with fallback to `+setuptools+`) plus a standardized
- https://www.python.org/dev/peps/pep-0517/#get-requires-for-build-wheel[build-system hook]
- to gather further requirements.
- See <<pyproject_buildrequires,the `+%pyproject_buildrequires+` macro>>
- for more details.
- Note that without the `+-R+` flag, the generator will include run-time
- requirements in BuildRequires. This is useful for running tests and for
- checking that the dependencies are available in Fedora.
- === Test dependencies
- See the <<Tests>> section.
- [#Extras]
- === Extras[[_python_extras]]
- Python extras are a way for Python projects
- to declare that extra dependencies are required for additional functionality.
- For example,
- `+requests+` has several standard dependencies (e.g. `+urllib3+`).
- But it also declares an _extra_ named `+requests[security]+`,
- which lists additional dependencies (e.g. `+cryptography+`).
- Unlike RPM subpackages, extras can only specify additional dependencies,
- not additional files.
- The main package will work if the optional dependency is not installed,
- but it might have limited functionality.
- Python tools treat extras as virtual packages.
- For example, if a user runs `+pip install 'requests[security]'+`,
- or installs a project that depends on `+requests[security]+`,
- both `+requests+` and `+cryptography+` will be installed.
- In Fedora, extras are usually provided by packages with no files.
- Instead of square brackets,
- Fedora package names conventionally use the `pass:[+]` character
- (which is valid in RPM package names,
- but not in Python canonical project names nor in extras identifiers).
- ==== Handling extras
- Python packages *SHOULD* have Provides
- for all extras the upstream project specifies, except:
- * those that are not useful for other packages
- (for example build/development requirements,
- commonly named `+dev+`, `+doc+` or `+test+`), and
- * those that have requirements that are not packaged in Fedora.
- A package that provides a Python extra
- *MUST* provide `+python3dist(DISTNAME[EXTRA])+`
- *and* `+python3.Xdist(DISTNAME[EXTRA])+`,
- where `+X+` is the minor version of the interpreter,
- `+DISTNAME+` is the <<Canonical project name>>,
- and `+EXTRA+` is the name of a single extra.
- For example, `+python3.9dist(requests[security])+`.
- These requirements *SHOULD* be generated
- using the automatic dependency generator.
- A package that provides a Python extra
- *MUST* require the extra’s main package with exact NEVR.
- A subpackage that primarily provides one Python extra *SHOULD* be named
- by appending `pass:[+]` and the extra name to the main package name.
- For example, `+python3-requests+security+`.
- The most straightforward way to provide an extra
- is with a dedicated subpackage containing no files (a “metapackage”).
- This case can be automated with
- the <<pyproject_extras_subpkg,`+%pyproject_extras_subpkg+` macro>>
- or the <<python_extras_subpkg,`+%python_extras_subpkg+` macro>>.
- This is not the only way:
- when some extra is always useful in a distro,
- it can be provided by the main package;
- when several extras are related,
- they may be provided by a single subpackage.
- However, having one dedicated subpackage per extra
- allows you to use the automatic dependency generator
- to ensure that the extras’ requirements will stay in sync with upstream.
- If you create a dedicated subpackage
- and want it to be always/usually installed,
- you can _Require_/_Recommend_/_Suggest_ it from the main package.
- The dependency generator for extras activates if the following holds:
- * The package name must end with `++EXTRA+`
- (where `+EXTRA+` is the extra name).
- * The package must contain the `+.dist-info+` directory, usually as `+%ghost+`.
- ===== Example and convenience macros
- The extra subpackage for `+setuptools_scm[toml]+` can be specified
- using the `+%pyproject_extras_subpkg+` convenience macro as follows.
- The macro takes the main package name and name(s) of the extra(s):
- [source,spec]
- ----
- %pyproject_extras_subpkg -n python3-setuptools_scm toml
- ----
- If not using `+%pyproject_install+`,
- you will instead need to use `+%python_extras_subpkg+`
- and pass a path to the `+dist-info+` directory:
- [source,spec]
- ----
- %python_extras_subpkg -n python3-setuptools_scm -i %{python3_sitelib}/*.dist-info toml
- ----
- For this case,
- the extras dependency generator will read upstream metadata
- from the `+.dist-info+` directory.
- If it finds that the extra requires on `+toml+`,
- it will generate `+Requires: python3.Xdist(toml)+`
- and `+Provides: python3dist(setuptools-scm[toml])+`
- (and the corresponding `+python3.Xdist+` provide).
- If you need additional features
- that the `+*_extras_subpkg+` macros do not cover,
- you will need to write the subpackage sections manually.
- Such features can be, for example:
- * Obsoleting/providing other names (e.g. obsoleted extras packages)
- * Manual strong or weak dependencies on other
- (possibly non-Python) packages
- As an example of what you need to write in these cases,
- both of the `+*_extras_subpkg+` macro invocations above
- expand to the following:
- [source,spec]
- ----
- %package -n python3-setuptools_scm+toml
- Summary: Metapackage for python3-setuptools_scm: toml extra
- Requires: python3-setuptools_scm = %{?epoch:%{epoch}:}%{version}-%{release}
- %description -n python3-setuptools_scm+toml
- This is a metapackage bringing in toml extra requires for python3-setuptools_scm.
- It contains no code, just makes sure the dependencies are installed.
- %files -n python3-setuptools_scm+toml
- %ghost %{python3_sitelib}/*.dist-info
- ----
- Note that the dependency generator
- does not add a dependency on the main package
- (the `+Requires: python3-setuptools_scm = ...+` above).
- If you are not using the `+%python_extras_subpkg+` macro,
- you need to add it manually.
- ==== Removing extras
- If an existing extra is removed from an upstream project,
- the Fedora maintainer *SHOULD* try to convince upstream to re-introduce it
- (with an empty list of dependencies).
- If that fails, the extra *SHOULD* be Obsoleted
- from either the main package or another extras subpackage.
- Note that removing extras is discouraged in
- https://setuptools.readthedocs.io/en/latest/userguide/dependency_management.html#optional-dependencies[setuptools documentation]
- (see the _Tip_ box near the end of the _Optional dependencies_ section).
- ==== Automatic Requires for extras
- The automatic <<Run-time dependency generator>>
- will generate Requires on `+python3.Xdist(DISTNAME[EXTRA])+`
- from upstream `+Requires-Dist+` metadata.
- If the required package does not yet provide metadata for the extra,
- contact the Fedora maintainer to add it.
- In an emergency, you can define
- the <<_python_no_extras_requires,`+%_python_no_extras_requires+` macro>>
- to avoid automatically generating _all_ extras requirements.
- == Interpreter invocation
- === Shebangs
- Shebang lines to invoke Python *MUST* use `+%{python3}+` as the interpreter.
- Shebang lines to invoke Python *SHOULD* be `+#!%{python3} -%{py3_shebang_flags}+`
- and they *MAY* include extra flags.
- If (some of) the default flags from
- <<py3_shebang_flags,the `+%{py3_shebang_flags}+` macro>> are not desirable,
- packages *SHOULD* explicitly redefine the macro to remove them by undefining
- the relevant `+%{_py3_shebang_...}+` macro.
- Using `+#!%{python3}+` (`+#!/usr/bin/python3+`)
- rather than e.g. `+#!/usr/bin/env python+`
- ensures that the system-wide Python interpreter is used to run the code,
- even if the user modifies `+$PATH+` (e.g. by activating a virtual environment).
- By default, `+-%{py3_shebang_flags}+` expands to `+-sP+`
- (or just `+-s+` on Python version lower than 3.11 and Fedora Linux older than 37).
- The `+-s+` flag,
- stored in <<_py3_shebang_s,the `+%{_py3_shebang_s}+` macro>>,
- means _don’t add user site directory to `+sys.path+`._
- That ensures the user’s Python packages
- (e.g. installed by `+pip install --user+`,
- or just placed in the current directory)
- don’t interfere with the RPM installed software.
- Sometimes, such content is desirable, such as with plugins.
- The `+-P+` flag,
- stored in <<_py3_shebang_P,the `+%{_py3_shebang_P}+` macro>>,
- means _don’t add the script's directory to `+sys.path+`._
- Sometimes, adding the script's directory to `+sys.path+` is desirable,
- such as with executable Python scripts installed in a custom directory,
- importing each other.
- Removing the undesired flag(s) from <<py3_shebang_flags,the `+%{py3_shebang_flags}+` macro>>
- rather than not using the macro at all,
- ensures that existing or future automation won’t add the flag.
- [source,spec]
- ----
- # Remove -s from Python shebang - ensure that extensions installed with pip
- # to user locations are seen and properly loaded
- %undefine _py3_shebang_s
- ----
- [source,spec]
- ----
- # Don't add -P to Python shebangs
- # The executable Python scripts in /usr/share/opt-viewer/ import each other
- %undefine _py3_shebang_P
- ----
- The <<pyproject_install,`+%pyproject_install+` macro>>
- automatically changes all Python shebangs
- in `+%{buildroot}%{_bindir}/*+` to use `+%{python3}+`
- and add contents of the <<py3_shebang_flags,`+%{py3_shebang_flags}+` macro>>
- to the existing flags.
- If you’re not using that macro
- or you need to change a shebang in a different directory,
- you can use <<py3_shebang_fix,the `+%py3_shebang_fix+` macro>> as follows:
- [source,spec]
- ----
- %py3_shebang_fix SCRIPTNAME …
- ----
- === Invokable Python modules
- Every executable `+TOOL+`
- for which the current version of Python matters
- *SHOULD* also be invokable by `+python3 -m TOOL+`.
- If the software doesn’t provide this functionality,
- packagers *SHOULD* ask the upstream to add it.
- This applies to tools that
- modify the current Python environment (like installing or querying packages),
- use Python for configuration,
- or use Python to run plugins.
- It does not apply to tools like GIMP or Bash
- which support plugins in multiple languages
- and/or have other means to specify the interpreter.
- For example, `+pip+` can be invoked as `+python3 -m pip+`.
- This allows users to accurately specify
- the Python version used to run the software.
- This convention works across different environments
- that might not always set `+$PATH+` or install scripts consistently.
- == Using Cython[[_packages_using_cython]]
- Tightening the
- xref:what-can-be-packaged.adoc#pregenerated-code[general Fedora policy],
- packages *MUST NOT* use files pre-generated by Cython.
- These *MUST* be deleted in `+%prep+` and regenerated during the build.
- As an exception, these sources *MAY* be used temporarily to prevent
- build time circular dependencies by following the
- xref:index.adoc#bootstrapping[bootstrapping guidelines].
- Generated files (the ones that must be deleted)
- have a generic `+.c+` or `+.cpp+` extension.
- Cython source files (which should stay)
- usually have the `+.pyx+` or `+.pxd+` extension.
- Cython is a popular tool for writing extension modules for Python.
- If compiles a Python-like language to C, which is then fed to the C compiler.
- Historically, Cython was hard to use upstream as a build-time dependency.
- Many projects include pre-generated C files in source
- distributions to avoid users from needing to install the tool.
- Cython uses CPython’s fast-changing internal API for performance reasons.
- For a new release of Python,
- Cython generally needs to be updated and the C files regenerated.
- In Fedora, this is frequently needed
- before upstreams release re-generated sources
- (e.g. for Alpha versins of Python).
- Since we do not have a problem with build-time dependencies,
- we always want to run the Cython step.
- For example, `+PyYAML+` removes a generated C file with:
- [source,spec]
- ----
- rm -rf ext/_yaml.c
- ----
- For another example, in `+python-lxml+` all C files are generated with Cython,
- which allows removing them with:
- [source,spec]
- ----
- # Remove pregenerated Cython C sources
- find -type f -name '*.c' -print -delete
- ----
- Some upstreams mix generated and hand-written C files.
- In such cases a grep like this one from `+scipy+` helps
- (but might not be entirely future proof):
- [source,spec]
- ----
- # Remove pregenerated Cython C sources
- rm $(grep -rl '/\* Generated by Cython')
- ----
- == Tests
- === Running tests
- If a test suite exists upstream,
- it *SHOULD* be run in the `+%check+` section.
- If that is not possible with reasonable effort,
- at least a basic smoke test (such as importing the packaged module)
- *MUST* be run in `+%check+`.
- You *MAY* exclude specific failing tests.
- You *MUST NOT* disable the entire testsuite
- or ignore its result to solve a build failure.
- As an exception,
- you *MAY* disable tests with an appropriate `+%if+` conditional
- (e.g. https://rpm-software-management.github.io/rpm/manual/conditionalbuilds.html[bcond])
- when xref:index.adoc#bootstrapping[bootstrapping].
- Most errors in Python happen at run-time,
- so tests are extremely important to root out issues,
- especially when mass rebuilds are required.
- Common reasons for skipping tests in `+%check+` include requiring
- network access,
- dependencies not packaged in Fedora,
- and/or specialized hardware or resources.
- In these cases,
- you can use <<pyproject_check_import,the `+%pyproject_check_import+`>>
- or <<py3_check_import,the `+%py3_check_import+` macro>>
- to test that installed modules are importable.
- ==== Tox
- A popular testing tool, and one which is well integrated in Fedora,
- is `+tox+`.
- Upstream, it is commonly used to test against multiple Python versions.
- In a Fedora package, BuildRequire test dependencies via `+%pyproject_buildrequires -t+` or `+-e+`
- (see _Test dependencies_ below)
- and run `+tox+` with:
- [source,spec]
- ----
- %tox
- ----
- This sets up the environment
- (`+$PATH+`, `+$PYTHONPATH+`, `+$TOX_TESTENV_PASSENV+`)
- and instructs `+tox+` to use the current environment rather than create new ones.
- For more options, see <<Build macros>>.
- ==== pytest
- When upstream doesn’t use `+tox+`,
- the tests need to be run directly
- depending on upstream choice of a test runner.
- A popular runner is `+pytest+`, which can be invoked using `+%pytest+`.
- Use positional arguments to specify the test directory.
- See `+python3 -m pytest --help+` for how to select tests.
- For example, if network-related tests are marked “network”,
- you might use `+-m+` to deselect them:
- [source,spec]
- ----
- %pytest -m "not network"
- ----
- The `+%pytest+` macro sets several environment variables
- appropriate for `+%check+`:
- * Locations in the buildroot are added to `+$PATH+` and `+$PYTHONPATH+`.
- * `+$PYTHONDONTWRITEBYTECODE+` is set to avoid
- writing pytest-specific cache files to buildroot
- * `+$PYTEST_XDIST_AUTO_NUM_WORKERS+` is set to `+%{_smp_build_ncpus}+`
- * If unset, `+$CFLAGS+` and `+$LDFLAGS+` are set to match the build flags
- ==== Other test runners
- If upstream doesn’t use `+tox+` or `+pytest+`,
- other test runners can be invoked with <<py3_test_envvars,the `+%{py3_test_envvars}+`>> macro,
- available since Fedora Linux 38.
- This macro sets several environment variables similarly to `+%pytest+`,
- but requires the actual test runner to be invoked after the macro, for example:
- [source,spec]
- ----
- %{py3_test_envvars} %{python3} -m unittest
- ----
- Or:
- [source,spec]
- ----
- %{py3_test_envvars} %{python3} tests/run_tests.py
- ----
- === Test dependencies
- One part of the Python packaging ecosystem that is still not standardized
- is specifying test dependencies (and development dependencies in general).
- A good, common way for upstreams to specify test dependencies
- is using an <<Extras,extra>> like `+[test]+`, `+[testing]+` or `+[dev]+`.
- In this case, upstream’s instructions to install test dependencies
- might look like `+$ pip install -e.[test]+`.
- Projects using `+tox+` usually specify test dependencies
- in a `+tox+`-specific format:
- a https://tox.readthedocs.io/en/latest/config.html#conf-requires[requires]
- key in the configuration.
- These two forms are handled by
- the <<pyproject_buildrequires,`+%pyproject_buildrequires+` macro>>.
- If upstream does not use either form,
- list test dependencies as manual _BuildRequires_ in the `+spec+` file,
- for example:
- [source,spec]
- ----
- # Test dependencies:
- BuildRequires: python3dist(pytest)
- ----
- If you need to do this,
- consider asking upstream to add a `+[test]+` extra.
- === Linters
- In `+%check+`, packages *SHOULD NOT* run “linters”:
- code style checkers,
- test coverage checkers
- and other tools that check code quality rather than functionality.
- Tools like `+black+`, `+pylint+`, `+flake8+`, or `+mypy+`
- are often “opinionated” and their “opinions” change frequently enough
- that they are nuisance in Fedora,
- where the linter is not pinned to an exact version.
- Furthermore, some of these tools take a long time
- to adapt to new Python versions,
- preventing early testing with Alpha and Beta releases of Python.
- And they are just not needed: wrongly formatted code is not important enough
- for the Fedora packager to bug the upstream about it.
- Making such an issue break a package build is entirely unreasonable.
- Linters _do_ make sense in upstream CI. But not in Fedora.
- If a linter is used, disable it and remove the dependency on it.
- If that is not easy, talk to upstream about making it easy
- (for example with a configuration option or a separate `+tox+` environment).
- For packages that contain such linters, use them at runtime or extend them,
- you will usually need to run the linter in `+%check+`.
- Run it to test functionality, not code quality of the packaged software.
- == Source files from PyPI
- Packages *MAY* use sources from PyPI.
- However, packages *SHOULD NOT* use an archive that omits test suites,
- licenses and/or documentation present in other source archives.
- For example, as of this writing `+pip+` provides a
- https://pypi.org/project/pip/#files[source tarball (“sdist”)]
- which omits the relatively large `+tests+` and `+docs+` directories
- present in https://github.com/pypa/pip[the source on GitHub].
- In this case, the tarball from GitHub should be used.
- (See the xref:SourceURL#_git_tags[Git tags] section
- of Fedora SourceURL guidelines.)
- When using sources from PyPI,
- you can use the <<pypi_source,the `+%pypi_source+` macro>>
- to generate the proper URL.
- [[_version_warning]]
- WARNING: Some Python packages use metadata from `git`
- (or a similar version control system)
- to construct their version string,
- for example via https://pypi.org/project/setuptools-scm/[setuptools_scm].
- When publishing a package to PyPI,
- this version metadata is usually stored and included in a file,
- so the version control history is no longer needed to construct it.
- However, when using tarballs from a git forge directly,
- this version information is missing
- and must be manually provided by the packager.
- For example, the `SETUPTOOLS_SCM_PRETEND_VERSION` environment variable can be set
- to the desired value in the `+%generate_buildrequires+` and `+%build+` scripts in the spec file
- for packages that use `setuptools_scm` for this purpose.
- == Example spec file[[_example_python_spec_file]]
- The following is a viable spec file
- for a Python library called `+Pello+`
- that follows packaging best practices.
- Note that the project name `+Pello+` <<Canonical project name,normalizes>>
- to the lowercase `+pello+`.
- The example spec shows where each variant is typically used.
- The project has an <<Extras,extra>> `+color+`,
- which enables colorized output when installed.
- Since the required dependency is quite minimal
- and color improves the user experience,
- the extra is Recommended from the main package.
- [source,spec]
- ----
- Name: python-pello
- Version: 1.0.4
- Release: 1%{?dist}
- Summary: Example Python library
- License: MIT-0
- URL: https://github.com/fedora-python/Pello
- Source: %{url}/archive/v%{version}/Pello-%{version}.tar.gz
- BuildArch: noarch
- BuildRequires: python3-devel
- %global _description %{expand:
- A python module which provides a convenient example.
- This description provides some details.}
- %description %_description
- %package -n python3-pello
- Summary: %{summary}
- Recommends: python3-pello+color
- %description -n python3-pello %_description
- %pyproject_extras_subpkg -n python3-pello color
- %prep
- %autosetup -p1 -n Pello-%{version}
- %generate_buildrequires
- %pyproject_buildrequires -t
- %build
- %pyproject_wheel
- %install
- %pyproject_install
- # Here, "pello" is the name of the importable module.
- %pyproject_save_files -l pello
- %check
- %tox
- # Note that there is no %%files section for
- # the unversioned python module, python-pello.
- # For python3-pello, %%{pyproject_files} handles code files and %%license,
- # but executables and documentation must be listed in the spec file:
- %files -n python3-pello -f %{pyproject_files}
- %doc README.md
- %{_bindir}/pello_greeting
- %changelog
- ----
- == Empty spec file
- The following is an unfinished spec file template to copy, paste and edit.
- [source,spec]
- ----
- Name: python-...
- Version: ...
- Release: 0%{?dist}
- Summary: ...
- License: ...
- URL: https://...
- Source: %{url}/archive/v%{version}/...-%{version}.tar.gz / %{pypi_source ...}
- BuildArch: noarch / BuildRequires: gcc
- BuildRequires: python3-devel
- %global _description %{expand:
- ...}
- %description %_description
- %package -n python3-...
- Summary: %{summary}
- %description -n python3-... %_description
- %prep
- %autosetup -p1 -n ...-%{version}
- %generate_buildrequires
- %pyproject_buildrequires -x... / -t
- %build
- %pyproject_wheel
- %install
- %pyproject_install
- %pyproject_save_files ...
- %check
- %tox / %pytest / %pyproject_check_import ...
- %files -n python3-... -f %{pyproject_files}
- %doc README.*
- %{_bindir}/...
- %changelog
- ----
- == Macro Reference[[_macros]]
- This section documents macros that are available
- to help with Python packaging.
- The expansions in parentheses are provided only as reference/examples.
- See the <<Mandatory macros>> section above for:
- * `+%{python3}+` (`+/usr/bin/python3+`)
- * `+%{python3_version}+` (e.g. `+3.9+`)
- * `+%{python3_version_nodots}+` (e.g. `+39+`)
- * `+%{python3_sitelib}+` (e.g. `+/usr/lib/python3.9/site-packages+`)
- * `+%{python3_sitearch}+` (e.g. `+/usr/lib64/python3.9/site-packages+`)
- === Shebang macros
- [#py3_shebang_flags]
- * `+%{py3_shebang_flags}+` (`+sP+` or `+s+` before Fedora Linux 37)
- +
- Flags for `+%{python3}+` to use in shebangs.
- See <<Shebangs>> for details.
- Includes flags from several `+%{_py3_shebang_...}+` macros listed here.
- [#_py3_shebang_s]
- * `+%{_py3_shebang_s}+` (`+s+`)
- +
- Undefine this macro to drop `+s+` from `+%{py3_shebang_flags}+`.
- [#_py3_shebang_P]
- * `+%{_py3_shebang_P}+` (`+P+`)
- +
- Undefine this macro to drop `+P+` from `+%{py3_shebang_flags}+`.
- Introduced in Fedora Linux 37.
- [#py3_shebang_fix]
- * `+%py3_shebang_fix PATHS+` (`+pathfix.py ... PATHS+`)
- +
- A macro to fix shebangs in specified `+PATHS+`.
- Only shebangs that already have `+python+` in them are changed.
- If a directory is given, all `+.py+` files in it are fixed, recursively.
- (So, if you need to fix shebangs in files not named `+*.py+`,
- you need to list each file separately or use a Shell glob,
- such as `+%{buildroot}%{_libexecdir}/mytool/*+`.)
- Existing flags are preserved and `+%{py3_shebang_flags}+` are added.
- +
- For example,
- `+#! /usr/bin/env python+` will be changed to `+#! /usr/bin/python3 -s+`
- and `+#! /usr/bin/python -u+` will be changed to `+#! /usr/bin/python3 -su+`.
- +
- This macro is called automatically
- by `+%pyproject_install+` on `+%{buildroot}%{_bindir}/*+`.
- === Convenience macros
- [#pypi_source]
- * `+%{pypi_source PROJECTNAME [VERSION [EXT]]}+`
- (e.g. `+https://.../Django-3.0.5.tar.gz+`)
- +
- Evaluates to the appropriate URL for source archive hosted on PyPI.
- Accepts the project name and up to two optional arguments:
- +
- --
- ** The version of the PyPI project.
- Defaults to `+%version+` (the package version) with any `+~+` removed.
- ** The file extension to use. Defaults to `+tar.gz+`.
- --
- +
- In most cases it is not necessary to specify those two arguments.
- +
- For backward compatibility, the first argument is technically optional
- as well, but omitting it is deprecated. (It defaults to `+%srcname+` if
- defined, or to `+%pypi_name+` if defined, or to `+%name+`.)
- [#python3_platform]
- * `+%{python3_platform}+` (e.g. `+linux-x86_64+`)
- +
- The platform name.
- Used in some Python build systems.
- This corresponds to
- https://docs.python.org/3/library/sysconfig.html#sysconfig.get_platform[`+sysconfig.get_platform()+`].
- [#python3_ext_suffix]
- * `+%{python3_ext_suffix}+` (e.g. `+.cpython-39-x86_64-linux-gnu.so+`)
- +
- Filename extension for Python extension modules.
- This corresponds to the `+EXT_SUFFIX+`
- https://docs.python.org/3/library/sysconfig.html[sysconfig] variable.
- [#python3_platform_triplet]
- * `+%{python3_platform_triplet}+` (e.g. `+x86_64-linux-gnu+`)
- +
- A string identifying the architecture/platform.
- This corresponds to the `+MULTIARCH+`
- https://docs.python.org/3/library/sysconfig.html[sysconfig] variable.
- [#python3_cache_tag]
- * `+%{python3_cache_tag}+` (e.g. `+cpython-311+`)
- +
- Part of the bytecode cache filename that identifies the interpreter.
- This corresponds to the
- https://docs.python.org/3/library/sys.html#sys.implementation[`+sys.implementation.cache_tag+`]
- value.
- === Build macros
- The “pyproject macros” are most useful
- for packaging Python projects that use the `+pyproject.toml+` file
- defined in https://www.python.org/dev/peps/pep-0518/[PEP 518]
- and https://www.python.org/dev/peps/pep-0517/[PEP 517],
- which specifies the package’s build dependencies
- (including the build system, such as `+setuptools+`, `+flit+` or `+poetry+`).
- If `+pyproject.toml+` is not found,
- the macros automatically fall backs to using `+setuptools+`
- with configuration in `+setup.cfg+`/`+setup.py+`.
- A full tutorial and discussion for the macros is available in the macros’
- https://src.fedoraproject.org/rpms/pyproject-rpm-macros/[README].
- [#pyproject_buildrequires]
- * `+%pyproject_buildrequires+`
- +
- Generate BuildRequires for the package.
- Used in the `+%generate_buildrequires+` section of the `+spec+` file.
- The macro has these options:
- +
- ** `+-R+`: Don't include run-time requirements (e.g. if the build backend does not support this).
- ** `+-r+`: Include run-time requirements
- (this flag is not needed and exists for backward-compatibility reasons only,
- run-time requirements are included by default).
- ** `+-x EXTRA+`: Include dependencies given by the given <<Extras,extra>>.
- Cannot be used with `+-R+`.
- ** `+-t+`: Include dependencies for the default _tox_ environment.
- Cannot be used with `+-R+`.
- ** `+-e ENV+`: Include dependencies for the given _tox_ environment,
- and save the `+ENV+` name as `+%{toxenv}+`.
- Cannot be used with `+-R+`.
- Multiple comma separated values can be given, for example:
- +
- [source,spec]
- ----
- %pyproject_buildrequires -e %{toxenv}-unit,%{toxenv}-integration
- ----
- [#pyproject_wheel]
- * `+%pyproject_wheel+`
- +
- Build the package.
- Commonly, this is the only macro needed in the `+%build+` section.
- +
- This macro needs BuildRequires generated by `+%pyproject_buildrequires+`.
- [#pyproject_install]
- * `+%pyproject_install+`
- +
- Install the package built by `+%pyproject_wheel+`.
- Calls `+%py3_shebang_fix %{_buildroot}%{_bindir}/*+`.
- +
- This macro needs BuildRequires generated by `+%pyproject_buildrequires+`.
- [#pyproject_save_files]
- * `+%pyproject_save_files MODNAME …+`
- +
- Generate a list of files corresponding to the given importable module(s)
- and save it as `+%{pyproject_files}+`.
- +
- Note that README file is not included.
- The LICENSE file is included when it is specified in the metadata.
- Also, while the macro allows including executable and other files
- (using the `+auto` flag),
- this feature *MUST NOT* be used in Fedora.
- +
- The `+MODNAME+` may be a glob pattern,
- which should be specific to your package.
- To prevent Shell from expanding the globs, put them in `+''+`,
- e.g. `+%pyproject_save_files '*pytest'+`.
- As mentioned in the <<Explicit lists>> section,
- expressions like `+%pyproject_save_files '*'+` are not acceptable.
- +
- The macro has these options:
- +
- ** `+-l+`: Declare that a missing license should terminate the build.
- Packagers are encouraged to use this flag
- when the `%license file` is not manually listed in `%files`
- to avoid accidentally losing the file in a future version.
- ** `+-L+`: Explicitly disable the check for a missing license file.
- When the `%license` file is manually listed in `%files`,
- packagers can use this flag to ensure future compatibility
- in case the `-l` behavior eventually becomes a default.
- [#pyproject_files]
- * `+%{pyproject_files}+`
- +
- Path of the file written by `+%pyproject_save_files+`, to be used as:
- +
- [source,spec]
- ----
- %files -n python3-DISTNAME -f %{pyproject_files}
- ----
- === Test macros
- [#tox]
- * `+%tox+`
- +
- Run tests using `+tox+`.
- +
- This macro needs BuildRequires generated by the `+-t+` or `+-e+` option of
- <<pyproject_buildrequires,the `+%pyproject_buildrequires+` macro>>.
- +
- Different environments may be specified with `+-e+`, for example:
- +
- [source,spec]
- ----
- %check
- %tox %{?with_integration_tests:-e %{toxenv},%{toxenv}-integration}
- ----
- +
- Flags for the `+tox+` command can be specified after `+--+`:
- +
- [source,spec]
- ----
- %tox -- --parallel 0
- ----
- +
- Additional arguments for the test runner may be specified after another `+--+`:
- +
- [source,spec]
- ----
- %tox -- --parallel 0 -- --verbose tests/*
- ----
- [#toxenv]
- * `+%{toxenv}+`
- +
- The _tox_ environment(s) used by the `+%tox+` macro.
- Multiple environments are separated by commas.
- Can be overridden manually or with `+%pyproject_buildrequires -t ENV1,ENV2+`.
- [#default_toxenv]
- * `+%{default_toxenv}+` (e.g. `+py39+`)
- +
- The system-wide default value of `+%{toxenv}+`.
- [#pytest]
- * `+%pytest+`
- +
- Run `+%__pytest+` with environment variables appropriate for tests in `%check`.
- See <<Running tests>> for details.
- [#__pytest]
- * `+%__pytest+` (`+/usr/bin/pytest+`)
- +
- The command that `+%pytest+` uses. May be redefined.
- [#py3_test_envvars]
- * `+%py3_test_envvars+` (`+PATH=... PYTHONPATH=... PYTHONDONTWRITEBYTECODE=1 ...+`)
- +
- The environment variables used by `+%pytest+` and `+%tox+`.
- It may be used to invoke custom test runners in `+%check+`.
- See <<Other test runners>> for details.
- Introduced in Fedora Linux 38.
- [#py3_check_import]
- * `+%py3_check_import+`
- +
- Imports all provided modules.
- If running an upstream test suite is not feasible,
- use this macro in `+%check+` to test that public Python modules are importable.
- +
- Takes these arguments:
- +
- --
- ** `+-f+`: path to file containing qualified module names
- (separated by newlines).
- Optional, can be used multiple times.
- ** `+-e+`: glob to exclude the matching module names.
- Optional, can be used multiple times.
- ** `+-t+`: if set, import only top-level module names
- ** Positional arguments (separated by spaces or commas)
- specify the module name(s) to check.
- --
- +
- The macro sets various environment variables
- such as `+PATH+` and `+PYTHONPATH+`
- to ensure the packaged versions of modules are imported.
- [#pyproject_check_import]
- * `+%pyproject_check_import+`
- +
- Imports all public modules found by
- <<pyproject_save_files,the `+%pyproject_save_files+` macro>> whose names match
- any of the provided `+MODNAME+` globs.
- +
- This macro needs to be used with `+%pyproject_save_files+`
- (use `+%py3_check_import+` in other cases).
- +
- The macro takes `+-e+`/`+-t+` as well as
- positional arguments for `+%py3_check_import+` above.
- === Extras macros
- [#pyproject_extras_subpkg]
- * `+%pyproject_extras_subpkg+`
- +
- Generates a simple subpackage for a Python extra.
- See <<Extras>> for more information.
- +
- This macro needs to be used with `+%pyproject_install+`
- (use `+%python_extras_subpkg+` in other cases).
- +
- Required arguments:
- +
- --
- ** `+-n+`: name of the “base” package (e.g. `+python3-requests+`)
- ** Positional arguments (separated by spaces or commas): the extra name(s).
- Multiple metapackages are generated when multiple names are provided.
- --
- +
- The macro also takes `+-i+`/`+-f+`/`+-F+` arguments
- for `+%python_extras_subpkg+` below,
- but if they are not given, a filelist written by `+%pyproject_install+` is used.
- +
- Similarly, the `+-a+`/`+-A+` flags are passed to `+%python_extras_subpkg+`.
- +
- This macro generates all the subpackage definition sections
- (`+%package+` including the `+Summary+` and `+Requires+` on the base package,
- `+%description+` and, by default, `+%files+`).
- Hence, it cannot be extended with custom _Provides_/_Obsoletes_/_Requires_/etc.
- This macro is designed to fit only the most common uses.
- For more complicated uses, construct the subpackage manually
- as shown in the <<Extras>> section.
- +
- The `+%files+` section is last.
- It can be continued to add files that only make sense with the extra
- and the base package does not fail without them.
- For example, the following macro will
- package the extra `+cli+` for the project `+a-cool-tool+`
- and include an `+a-cool-tool+` command:
- +
- [source,spec]
- ----
- %pyproject_extras_subpkg -n a-cool-tool cli
- %{_bindir}/a-cool-tool
- ----
- +
- Due to technical limitations,
- the macro never generates requirements on the arched
- `+BASE_PACKAGE%{?_isa} = %{?epoch:%{epoch}:}%{version}-%{release}+`.
- It only adds
- `+Requires: BASE_PACKAGE = %{?epoch:%{epoch}:}%{version}-%{release})+`
- because a macro cannot reliably detect if the subpackage is arched or not.
- So far, this has not been a problem in practice.
- [#python_extras_subpkg]
- * `+%python_extras_subpkg+`
- +
- Generates a simple subpackage for a Python extra.
- See <<Extras>> for more information.
- Takes these arguments:
- +
- --
- ** `+-n+`: name of the “base” package (e.g. `+python3-requests+`)
- ** `+-i+`: the `+%files %ghost+` path (glob) to the `+.dist-info+` directory
- ** Positional arguments (separated by spaces or commas)
- specify the extra name(s)
- — multiple metapackages are generated when multiple names are provided.
- ** `+-f+`: Relative path to the filelist for this metapackage
- (which should contain the `+%files %ghost+` path (glob)
- to the the metadata directory).
- Conflicts with `+-i+` and `+-F+`.
- ** `+-F+`: Skip the %files section entirely
- (if the packager wants to construct it manually).
- Conflicts with `+-i+` and `+-f+`.
- ** `+-a+`: Include `+BuildArch: noarch+` in the package definition,
- to be used only when the package is archful,
- but the “base” package passed to `+-n+` is not.
- ** `+-A+`: Explicitly disables `+-a+` (does nothing at the moment).
- --
- +
- As with `+%pyproject_extras_subpkg+`:
- +
- ** This macro generates all the subpackage definition sections,
- with only `+%files+` being customizable.
- For more complicated uses, construct the subpackage manually
- as shown in the <<Extras>> section.
- ** It never generates requirements on the arched
- `+BASE_PACKAGE%{?_isa} = %{?epoch:%{epoch}:}%{version}-%{release}+`.
- === Manual generation
- The following macros are available for cases where
- automatic generation is turned off.
- They can also be useful for handling files in non-standard locations
- where the generators don’t look.
- [#pycached]
- * `+%pycached MODNAME.py+`
- +
- Given a Python file, lists the file and the files with its bytecode
- cache. See _Source files and bytecode cache_ for more information.
- [#py_provides]
- * `+%py_provides python3-MODNAME+`
- +
- Generates `+Provides+` for `+python3-MODNAME+`, `+python3.X-MODNAME+`
- and `+python-MODNAME+`.
- See <<Automatic-unversioned-provides>> for more details.
- [#py_byte_compile]
- * `+%py_byte_compile INTERPRETER PATH+`
- +
- Byte-compile a Python file into a `+__pycache__/*.pyc+`.
- +
- If the `+PATH+` argument is a directory,
- the macro will recursively byte compile all `+*.py+` files in the directory.
- (So, if you need to compile files not named `+*.py+`,
- you need to use the macro on each file separately.)
- +
- The `+INTERPRETER+` determines the compiled file name’s suffix
- and the magic number embedded in the file.
- These muct match the interpreter that will import the file.
- Usually, the `+INTERPRETER+` should be set to `+%{python3}+`.
- If you are compiling for a non-default interpreter,
- use that interpreter instead and add a `+BuildRequires+` line for it.
- [#py_dist_name]
- * `+%{py_dist_name PROJECTNAME}+`
- +
- Given a _project name_ (e.g. `+PyYAML+`) it will convert it
- to the canonical format (e.g. `+pyyaml+`).
- See <<Canonical project name>> for more information.
- [#py3_dist]
- * `+%{py3_dist PROJECTNAME …}+`
- +
- Given one or more _project names_,
- it will convert them to the canonical format
- and evaluate to `+python3dist(DISTNAME)+`,
- which is useful when listing dependencies.
- See <<Machine-readable-provides>> for more information.
- === System Settings
- The following macros can be redefined for special use cases.
- [#__python]
- * `+%{__python}+` (errors by default if not redefined)
- +
- Defining this macro sets the meaning of all “unversioned” Python macros
- such as `+%{python}+` or `+%{python_sitelib}+`.
- Don’t use these macros without redefining `+%{__python}+`.
- [#__python3]
- * `+%{__python3}+` (`+/usr/bin/python3+`)
- +
- The python 3 interpreter.
- Redefining this macro changes all the `+%{python3...}+` macros,
- e.g. `+%{python3}+` or `+%{python3_sitelib}+`.
- [#python3_pkgversion]
- * `+%{python3_pkgversion}+` (`+3+`)
- +
- Distro-wide Python version, i.e. the `+3+` in `+python3+`.
- Projects that build on top of Fedora might define it to e.g. `+3.9+`
- to try allowing multiple Python stacks installable in parallel.
- Packages in Fedora *MAY* use it
- (e.g. in package names: `+python%{python3_pkgversion}-requests+`),
- but *MUST NOT* redefine it.
- === Comparing Python versions
- When comparing Python versions
- (e.g. to ask: is `+%{python3_version}+` greater than 3.8?),
- using naïve `+%if %{python3_version} > 3.8+`
- or `+%if "%{python3_version}" > "3.8"+` is not possible,
- because the comparison is performed alphabetically on strings.
- Hence it is true that `+"3.10" < "3.8"+` (which is not desired).
- It is possible to explicitly compare version literals by using the `+v+` prefix,
- similar to the Python string prefixes:
- [source,spec]
- ----
- %if v"0%{?python3_version}" > v"3.8"
- ...
- %endif
- ----
- [NOTE]
- ====
- As a workaround for compatibility with RPM releases before 4.16 (Fedora 33),
- `+%{python3_version_nodots}+` can be compared as an integers:
- [source,spec]
- ----
- %if %{python3_version_nodots} > 38
- ...
- %endif
- ----
- This will work with Python 3.10 (310 > 39),
- but eventually break with Python 4.0 (40 < 310).
- ====
- === Disabling automation
- The following macros can turn off Python-specific automation.
- Consider contacting the Python SIG if you need to do this.
- [#python_disable_dependency_generator]
- * `+%{?python_disable_dependency_generator}+`
- +
- Disables the automatic dependency generator.
- See <<Automatically-generated-dependencies>> for details.
- [#__pythonname_provides]
- * `+%undefine __pythonname_provides+`
- +
- Disables automatic generation of unversioned/versioned provides for package names,
- e.g. `+python-FOO+` and `+python3.9-FOO+` for `+python3-foo+`.
- See <<Automatic-unversioned-provides>> for more details.
- [#__pythondist_provides]
- * `+%undefine __pythondist_provides+`
- +
- Disables automatic generation of machine-readable Provides,
- e.g. `+python3dist(foo)+`.
- See <<Machine-readable-provides>> for more details.
- [#_python_no_extras_requires]
- * `+%global _python_no_extras_requires 1+`
- +
- If defined, <<Automatic Requires for extras>> will not be generated.
- [#_python_dist_allow_version_zero]
- * `+%global _python_dist_allow_version_zero 1+`
- +
- From Fedora Linux 38 on, it is no longer possible to build a Python package with version 0
- to prevent <<_version_warning,an accidental loss of the actual version information>>.
- If defined, the macro will allow to build such package.
- === Deprecated Macros
- The following macros are deprecated.
- See the xref:Python_201x.adoc[201x-era Python Packaging guidelines]
- for how some of them were used.
- * [[py3_build]] `+%py3_build+`
- * [[py3_build_wheel]] `+%py3_build_wheel+`
- * [[py3_build_egg]] `+%py3_build_egg+`
- * [[py3_install]] `+%py3_install+`
- * [[py3_install_wheel]] `+%py3_install_wheel+`
- * [[py3_install_egg]] `+%py3_install_egg+`
- * [[py3dir]] `+%py3dir+`
- * [[py3_other_build]] `+%py3_other_build+`
- * [[py3_other_install]] `+%py3_other_install+`
- * [[python_provide]] `+%python_provide+`
|