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
|
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>distutils-r1 — standard Python build systems — Gentoo Python Guide documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/alabaster.css" />
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
<script src="_static/jquery.js"></script>
<script src="_static/underscore.js"></script>
<script src="_static/doctools.js"></script>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="next" title="distutils-r1 legacy concepts" href="distutils-legacy.html" />
<link rel="prev" title="python-r1 — multi-impl packages" href="multi.html" />
<link rel="stylesheet" href="_static/custom.css" type="text/css" />
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
</head><body>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="distutils-r1-standard-python-build-systems">
<h1>distutils-r1 — standard Python build systems<a class="headerlink" href="#distutils-r1-standard-python-build-systems" title="Permalink to this headline">¶</a></h1>
<p>The <code class="docutils literal notranslate"><span class="pre">distutils-r1</span></code> eclass is used to facilitate build systems using
<code class="docutils literal notranslate"><span class="pre">setup.py</span></code> (distutils and its derivatives, notably setuptools)
or <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code> (flit, poetry). It is built on top
of <code class="docutils literal notranslate"><span class="pre">python-r1</span></code> and <code class="docutils literal notranslate"><span class="pre">python-single-r1</span></code>, and therefore supports
efficiently building multi-impl and single-impl packages.</p>
<p>Eclass reference: <a class="reference external" href="https://devmanual.gentoo.org/eclass-reference/distutils-r1.eclass/index.html">distutils-r1.eclass(5)</a></p>
<section id="the-pep-517-and-legacy-modes">
<h2>The PEP 517 and legacy modes<a class="headerlink" href="#the-pep-517-and-legacy-modes" title="Permalink to this headline">¶</a></h2>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>The PEP 517 mode is still experimental and it is not guaranteed
to handle all packages correctly. When using it, please verify
that all necessary files are installed correctly. The hooks provided
by <code class="docutils literal notranslate"><span class="pre">app-portage/iwdevtools</span></code> can be helpful in checking for
regressions when migrating existing packages.</p>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">distutils-r1</span></code> eclass has currently two modes of operation:
the PEP 517 mode and the legacy mode. The former mode should be
preferred for new ebuilds; the latter is provided for backwards
compatibility and packages that are not PEP 517-ready.</p>
<p>The PEP 517 mode uses backends as defined by <a class="reference external" href="https://www.python.org/dev/peps/pep-0517/">PEP 517</a> to build
packages. It supports a greater number of Python build systems
at the cost of flexibility and performance. In the eclass
implementation, the PEP 517 backend is used to build a wheel (i.e. a zip
archive) with the package and then an installer tool is used to install
the wheel into a staging directory. The complete process is done
in compile phase, and the install phase merely moves the files into
the image directory.</p>
<p>The legacy mode invokes the <code class="docutils literal notranslate"><span class="pre">setup.py</span></code> script directly. The build
command is invoked to populate the build directory in the compile phase,
then the install command is used in the install phase. Normally, this
mode works only for packages using backwards-compatible distutils
derivatives. Additionally, it supports flit and poetry through
pyproject2setuppy hack. This mode relies on deprecated features.</p>
<p>The PEP 517 mode is enabled via declaring the <code class="docutils literal notranslate"><span class="pre">DISTUTILS_USE_PEP517</span></code>
variable. Otherwise, the legacy mode is used.</p>
</section>
<section id="basic-use-pep-517-mode">
<h2>Basic use (PEP 517 mode)<a class="headerlink" href="#basic-use-pep-517-mode" title="Permalink to this headline">¶</a></h2>
<p>By default, <code class="docutils literal notranslate"><span class="pre">distutils-r1</span></code> sets appropriate metadata variables
and exports a full set of phase functions necessary to install packages
using Python build systems.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">DISTUTILS_USE_PEP517</span></code> variable is used to enable the modern
PEP 517 mode and declare the build system used. The eclass
automatically generates a build-time dependency on the packages needed
for the build system.</p>
<p>The simplest case of ebuild is:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span> <span class="c1"># Copyright 1999-2022 Gentoo Authors</span>
<span class="c1"># Distributed under the terms of the GNU General Public License v2</span>
<span class="nv">EAPI</span><span class="o">=</span><span class="m">8</span>
<span class="hll"> <span class="nv">DISTUTILS_USE_PEP517</span><span class="o">=</span>setuptools
</span><span class="hll"> <span class="nv">PYTHON_COMPAT</span><span class="o">=(</span> python3_<span class="o">{</span><span class="m">8</span>..10<span class="o">}</span> pypy3 <span class="o">)</span>
</span><span class="hll"> inherit distutils-r1
</span>
<span class="nv">DESCRIPTION</span><span class="o">=</span><span class="s2">"Makes working with XML feel like you are working with JSON"</span>
<span class="nv">HOMEPAGE</span><span class="o">=</span><span class="s2">"https://github.com/martinblech/xmltodict/ https://pypi.org/project/xmltodict/"</span>
<span class="nv">SRC_URI</span><span class="o">=</span><span class="s2">"mirror://pypi/</span><span class="si">${</span><span class="nv">PN</span><span class="p">:</span><span class="nv">0</span><span class="p">:</span><span class="nv">1</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">PN</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">P</span><span class="si">}</span><span class="s2">.tar.gz"</span>
<span class="nv">LICENSE</span><span class="o">=</span><span class="s2">"MIT"</span>
<span class="nv">SLOT</span><span class="o">=</span><span class="s2">"0"</span>
<span class="nv">KEYWORDS</span><span class="o">=</span><span class="s2">"~amd64 ~arm ~arm64 ~x86"</span>
</pre></div>
</div>
</section>
<section id="dependencies">
<h2>Dependencies<a class="headerlink" href="#dependencies" title="Permalink to this headline">¶</a></h2>
<p>Dependencies on Python packages are declared using the same method
as the underlying eclass — that is, <code class="docutils literal notranslate"><span class="pre">python-r1</span></code>
or <code class="docutils literal notranslate"><span class="pre">python-single-r1</span></code>.</p>
<p>In packages using <code class="docutils literal notranslate"><span class="pre">dev-python/setuptools</span></code>, dependencies are often
specified in <code class="docutils literal notranslate"><span class="pre">setup.py</span></code> or <code class="docutils literal notranslate"><span class="pre">setup.cfg</span></code> file.
The <code class="docutils literal notranslate"><span class="pre">install_requires</span></code> key specifies runtime dependencies,
<code class="docutils literal notranslate"><span class="pre">setup_requires</span></code> pure build-time dependencies, <code class="docutils literal notranslate"><span class="pre">extras_require</span></code>
optional dependencies. Test dependencies are sometimes specified
as one of the ‘extras’, and sometimes as <code class="docutils literal notranslate"><span class="pre">tests_require</span></code>.</p>
<p>Setuptools strictly enforces <code class="docutils literal notranslate"><span class="pre">setup_requires</span></code> at build time,
and <code class="docutils literal notranslate"><span class="pre">tests_require</span></code> when running <code class="docutils literal notranslate"><span class="pre">setup.py</span> <span class="pre">test</span></code>. Runtime
dependencies are enforced only when starting installed programs
via entry points.</p>
<p>In other cases, dependencies are listed in additional files named
e.g. <code class="docutils literal notranslate"><span class="pre">requirements.txt</span></code>. They could be also found in test runner
setup (<code class="docutils literal notranslate"><span class="pre">tox.ini</span></code>) or CI setup files (<code class="docutils literal notranslate"><span class="pre">.travis.yml</span></code>). Finally, you
can grep source code for <code class="docutils literal notranslate"><span class="pre">import</span></code> statements.</p>
<p>In general, you should take special care when listing dependencies
of Python packages. Upstreams sometimes specify indirect dependencies,
often list packages that are not strictly relevant to Gentoo runs
but used on CI/CD setup, unnecessarily restrict version requirements.</p>
<p>Most of the time, runtime dependencies do not need to be present
at build time. However, they do need to be copied there if the Python
modules needing them are imported at build time. Often this is the case
when running tests, hence the following logic is common in Python
ebuilds:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="nv">RDEPEND</span><span class="o">=</span><span class="s2">"..."</span>
<span class="nv">BDEPEND</span><span class="o">=</span><span class="s2">"test? ( </span><span class="si">${</span><span class="nv">RDEPEND</span><span class="si">}</span><span class="s2"> )"</span>
</pre></div>
</div>
<p>There are two different approaches used for optional runtime
dependencies. Some packages are installing them conditionally to USE
flags (this is generally acceptable as long as package builds quickly),
others list them in <code class="docutils literal notranslate"><span class="pre">pkg_postinst()</span></code> messages. It is recommended
that optional test dependencies are used unconditionally (to ensure
the widest test coverage, and avoid unpredictable test failures on users
who have more dependencies installed).</p>
</section>
<section id="python-single-r1-variant">
<span id="index-0"></span><h2>python-single-r1 variant<a class="headerlink" href="#python-single-r1-variant" title="Permalink to this headline">¶</a></h2>
<p>Normally, <code class="docutils literal notranslate"><span class="pre">distutils-r1</span></code> uses <code class="docutils literal notranslate"><span class="pre">python-r1</span></code> to build multi-impl
packages, and this is the recommended mode. However, in some cases
you will need to use <code class="docutils literal notranslate"><span class="pre">python-single-r1</span></code> instead, especially if you
need to depend on other packages using that eclass.</p>
<p>The single-impl mode can be enabled by setting <code class="docutils literal notranslate"><span class="pre">DISTUTILS_SINGLE_IMPL</span></code>
variable before inheriting the eclass. The eclass aims to provide
maximum compatibility between these two modes, so most of the existing
code will work with either. However, the functions specific to
the underlying eclass are not compatible — e.g. the dependencies need
to be rewritten.</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span> <span class="c1"># Copyright 1999-2022 Gentoo Authors</span>
<span class="c1"># Distributed under the terms of the GNU General Public License v2</span>
<span class="nv">EAPI</span><span class="o">=</span><span class="m">7</span>
<span class="nv">PYTHON_COMPAT</span><span class="o">=(</span> python3_<span class="o">{</span><span class="m">8</span>..10<span class="o">}</span> <span class="o">)</span>
<span class="nv">PYTHON_REQ_USE</span><span class="o">=</span><span class="s2">"readline"</span>
<span class="nv">DISTUTILS_USE_PEP517</span><span class="o">=</span>setuptools
<span class="hll"> <span class="nv">DISTUTILS_SINGLE_IMPL</span><span class="o">=</span><span class="m">1</span>
</span>
inherit distutils-r1
<span class="nv">DESCRIPTION</span><span class="o">=</span><span class="s2">"Pythonic layer on top of the ROOT framework's PyROOT bindings"</span>
<span class="nv">HOMEPAGE</span><span class="o">=</span><span class="s2">"http://rootpy.org"</span>
<span class="nv">SRC_URI</span><span class="o">=</span><span class="s2">"mirror://pypi/</span><span class="si">${</span><span class="nv">PN</span><span class="p">:</span><span class="nv">0</span><span class="p">:</span><span class="nv">1</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">PN</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">P</span><span class="si">}</span><span class="s2">.tar.gz"</span>
<span class="nv">LICENSE</span><span class="o">=</span><span class="s2">"BSD"</span>
<span class="nv">SLOT</span><span class="o">=</span><span class="s2">"0"</span>
<span class="nv">KEYWORDS</span><span class="o">=</span><span class="s2">"~amd64 ~x86 ~amd64-linux ~x86-linux"</span>
<span class="nv">RDEPEND</span><span class="o">=</span><span class="s2">"</span>
<span class="s2"> sci-physics/root:=[</span><span class="si">${</span><span class="nv">PYTHON_SINGLE_USEDEP</span><span class="si">}</span><span class="s2">]</span>
<span class="s2"> dev-python/root_numpy[</span><span class="si">${</span><span class="nv">PYTHON_SINGLE_USEDEP</span><span class="si">}</span><span class="s2">]</span>
<span class="s2"> </span><span class="k">$(</span>python_gen_cond_dep <span class="s1">'</span>
<span class="s1"> dev-python/matplotlib[${PYTHON_USEDEP}]</span>
<span class="s1"> dev-python/pytables[${PYTHON_USEDEP}]</span>
<span class="s1"> dev-python/termcolor[${PYTHON_USEDEP}]</span>
<span class="s1"> '</span><span class="k">)</span><span class="s2">"</span>
<span class="nv">DEPEND</span><span class="o">=</span><span class="s2">"</span>
<span class="s2"> sci-physics/root[</span><span class="si">${</span><span class="nv">PYTHON_SINGLE_USEDEP</span><span class="si">}</span><span class="s2">]"</span>
</pre></div>
</div>
</section>
<section id="pep-517-build-systems">
<span id="index-1"></span><h2>PEP 517 build systems<a class="headerlink" href="#pep-517-build-systems" title="Permalink to this headline">¶</a></h2>
<p>The majority of examples in this guide assume using setuptools build
system. However, PEP 517 mode provides support for other build systems.</p>
<p>In order to determine the correct build system used, read
the <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code> file. An example file could start with:</p>
<div class="highlight-toml notranslate"><div class="highlight"><pre><span></span><span class="k">[build-system]</span><span class="w"></span>
<span class="n">requires</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="s">"flit_core >=3.6.0,<4"</span><span class="p">]</span><span class="w"></span>
<span class="n">build-backend</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"flit_core.buildapi"</span><span class="w"></span>
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">requires</span></code> key indicates the packages required in order to run
the build system, while <code class="docutils literal notranslate"><span class="pre">build-backend</span></code> indicates the module
(and optionally the class) providing the build system backend.
The eclass maintains a mapping of backend paths to the respective
<code class="docutils literal notranslate"><span class="pre">DISTUTILS_USE_PEP517</span></code> and automatically suggests the correct value.</p>
<p>The following table summarizes supported backends.</p>
<table class="docutils align-default">
<colgroup>
<col style="width: 25%" />
<col style="width: 31%" />
<col style="width: 44%" />
</colgroup>
<thead>
<tr class="row-odd"><th class="head"><p>USE_PEP517 value</p></th>
<th class="head"><p>Provider package</p></th>
<th class="head"><p>build-backend</p></th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td><p>flit</p></td>
<td><p>dev-python/flit_core</p></td>
<td><p>flit_core.buildapi</p></td>
</tr>
<tr class="row-odd"><td><p>pdm</p></td>
<td><p>dev-python/pdm-pep517</p></td>
<td><p>pdm.pep517.api</p></td>
</tr>
<tr class="row-even"><td><p>poetry</p></td>
<td><p>dev-python/poetry-core</p></td>
<td><p>poetry.core.masonry.api</p></td>
</tr>
<tr class="row-odd"><td><p>setuptools</p></td>
<td><p>dev-python/setuptools</p></td>
<td><p>setuptools.build_meta
setuptools.__legacy__.build_meta</p></td>
</tr>
<tr class="row-even"><td><p>standalone</p></td>
<td><p>(none)</p></td>
<td><p>(various)</p></td>
</tr>
</tbody>
</table>
<p>The special value <code class="docutils literal notranslate"><span class="pre">standalone</span></code> is reserved for bootstrapping build
systems. It indicates that the package itself provides its own build
backend.</p>
<p>Legacy packages that provide <code class="docutils literal notranslate"><span class="pre">setup.py</span></code> but no <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code>
(or do not define a backend inside it) should be installed via
the <code class="docutils literal notranslate"><span class="pre">setuptools</span></code> backend (this applies to pure distutils packages
as well). The eclass automatically uses the legacy setuptools backend
for them.</p>
</section>
<section id="deprecated-pep-517-backends">
<h2>Deprecated PEP 517 backends<a class="headerlink" href="#deprecated-pep-517-backends" title="Permalink to this headline">¶</a></h2>
<section id="flit-buildapi">
<h3>flit.buildapi<a class="headerlink" href="#flit-buildapi" title="Permalink to this headline">¶</a></h3>
<p>Some packages are still found using the historical flit build backend.
Their <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code> files contain a section similar
to the following:</p>
<div class="highlight-toml notranslate"><div class="highlight"><pre><span></span><span class="k">[build-system]</span><span class="w"></span>
<span class="n">requires</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="s">"flit"</span><span class="p">]</span><span class="w"></span>
<span class="n">build-backend</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"flit.buildapi"</span><span class="w"></span>
</pre></div>
</div>
<p>This backend requires installing the complete flit package manager.
Instead, the package should be fixed upstream to use flit_core
per <a class="reference external" href="https://flit.readthedocs.io/en/latest/pyproject_toml.html#build-system-section">flit build system section documentation</a> instead:</p>
<div class="highlight-toml notranslate"><div class="highlight"><pre><span></span><span class="k">[build-system]</span><span class="w"></span>
<span class="n">requires</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="s">"flit_core"</span><span class="p">]</span><span class="w"></span>
<span class="n">build-backend</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"flit_core.buildapi"</span><span class="w"></span>
</pre></div>
</div>
<p>flit_core produces identical artifacts to flit. At the same time, it
reduces the build-time dependency footprint and therefore makes isolated
PEP 517 builds faster.</p>
</section>
<section id="poetry-masonry-api">
<h3>poetry.masonry.api<a class="headerlink" href="#poetry-masonry-api" title="Permalink to this headline">¶</a></h3>
<p>A similar problem applies to the packages using poetry. The respective
<code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code> files contain:</p>
<div class="highlight-toml notranslate"><div class="highlight"><pre><span></span><span class="k">[build-system]</span><span class="w"></span>
<span class="n">requires</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="s">"poetry>=0.12"</span><span class="p">]</span><span class="w"></span>
<span class="n">build-backend</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"poetry.masonry.api"</span><span class="w"></span>
</pre></div>
</div>
<p>Instead, the lightweight poetry-core module should be used per <a class="reference external" href="https://python-poetry.org/docs/pyproject/#poetry-and-pep-517">poetry
PEP-517 documentation</a>:</p>
<div class="highlight-toml notranslate"><div class="highlight"><pre><span></span><span class="k">[build-system]</span><span class="w"></span>
<span class="n">requires</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="s">"poetry_core>=1.0.0"</span><span class="p">]</span><span class="w"></span>
<span class="n">build-backend</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"poetry.core.masonry.api"</span><span class="w"></span>
</pre></div>
</div>
<p>poetry-core produces identical artifacts to poetry. It has smaller
dependency footprint and makes isolated builds much faster.</p>
</section>
</section>
<section id="setuptools-scm-and-snapshots">
<span id="index-2"></span><h2>setuptools_scm and snapshots<a class="headerlink" href="#setuptools-scm-and-snapshots" title="Permalink to this headline">¶</a></h2>
<p><a class="reference external" href="https://pypi.org/project/setuptools-scm/">setuptools_scm</a> is a package providing additional features for running
inside a VCS checkout, in particular the ability to determine version
from VCS tags. However, this works correctly only when the package
is built from VCS checkout or an <code class="docutils literal notranslate"><span class="pre">sdist</span></code> archive containing
pregenerated metadata. It does not work when building from a GitHub
snapshot:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>Traceback <span class="o">(</span>most recent call last<span class="o">)</span>:
File <span class="s2">"/tmp/executing-0.5.2/setup.py"</span>, line <span class="m">4</span>, <span class="k">in</span> <module>
setup<span class="o">()</span>
File <span class="s2">"/usr/lib/python3.9/site-packages/setuptools/__init__.py"</span>, line <span class="m">143</span>, <span class="k">in</span> setup
_install_setup_requires<span class="o">(</span>attrs<span class="o">)</span>
File <span class="s2">"/usr/lib/python3.9/site-packages/setuptools/__init__.py"</span>, line <span class="m">131</span>, <span class="k">in</span> _install_setup_requires
<span class="nv">dist</span> <span class="o">=</span> distutils.core.Distribution<span class="o">(</span>dict<span class="o">(</span>
File <span class="s2">"/usr/lib/python3.9/site-packages/setuptools/dist.py"</span>, line <span class="m">425</span>, <span class="k">in</span> __init__
_Distribution.__init__<span class="o">(</span>self, <span class="o">{</span>
File <span class="s2">"/usr/lib/python3.9/distutils/dist.py"</span>, line <span class="m">292</span>, <span class="k">in</span> __init__
self.finalize_options<span class="o">()</span>
File <span class="s2">"/usr/lib/python3.9/site-packages/setuptools/dist.py"</span>, line <span class="m">717</span>, <span class="k">in</span> finalize_options
ep<span class="o">(</span>self<span class="o">)</span>
File <span class="s2">"/usr/lib/python3.9/site-packages/setuptools_scm/integration.py"</span>, line <span class="m">48</span>, <span class="k">in</span> infer_version
dist.metadata.version <span class="o">=</span> _get_version<span class="o">(</span>config<span class="o">)</span>
File <span class="s2">"/usr/lib/python3.9/site-packages/setuptools_scm/__init__.py"</span>, line <span class="m">148</span>, <span class="k">in</span> _get_version
<span class="nv">parsed_version</span> <span class="o">=</span> _do_parse<span class="o">(</span>config<span class="o">)</span>
File <span class="s2">"/usr/lib/python3.9/site-packages/setuptools_scm/__init__.py"</span>, line <span class="m">110</span>, <span class="k">in</span> _do_parse
raise LookupError<span class="o">(</span>
LookupError: setuptools-scm was unable to detect version <span class="k">for</span> <span class="s1">'/tmp/executing-0.5.2'</span>.
Make sure you<span class="s1">'re either building from a fully intact git repository or PyPI tarballs. Most other sources (such as GitHub'</span>s tarballs, a git checkout without the .git folder<span class="o">)</span> don<span class="s1">'t contain the necessary metadata and will not work.</span>
<span class="s1">For example, if you'</span>re using pip, instead of https://github.com/user/proj/archive/master.zip use git+https://github.com/user/proj.git#egg<span class="o">=</span>proj
</pre></div>
</div>
<p>This problem can be resolved by providing the correct version externally
via <code class="docutils literal notranslate"><span class="pre">SETUPTOOLS_SCM_PRETEND_VERSION</span></code>:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="nb">export</span> <span class="nv">SETUPTOOLS_SCM_PRETEND_VERSION</span><span class="o">=</span><span class="si">${</span><span class="nv">PV</span><span class="si">}</span>
</pre></div>
</div>
</section>
<section id="parallel-build-race-conditions">
<h2>Parallel build race conditions<a class="headerlink" href="#parallel-build-race-conditions" title="Permalink to this headline">¶</a></h2>
<p>The distutils build system has a major unresolved bug regarding race
conditions. If the same source file is used to build multiple Python
extensions, the build can start multiple simultaneous compiler processes
using the same output file. As a result, there is a race between
the compilers writing output file and link editors reading it. This
generally does not cause immediate build failures but results in broken
extensions causing cryptic issues in reverse dependencies.</p>
<p>For example, a miscompilation of <code class="docutils literal notranslate"><span class="pre">dev-python/pandas</span></code> have recently
caused breakage in <code class="docutils literal notranslate"><span class="pre">dev-python/dask</span></code>:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>/usr/lib/python3.8/site-packages/pandas/__init__.py:29: <span class="k">in</span> <module>
from pandas._libs import hashtable as _hashtable, lib as _lib, tslib as _tslib
/usr/lib/python3.8/site-packages/pandas/_libs/__init__.py:13: <span class="k">in</span> <module>
from pandas._libs.interval import Interval
pandas/_libs/interval.pyx:1: <span class="k">in</span> init pandas._libs.interval
???
pandas/_libs/hashtable.pyx:1: <span class="k">in</span> init pandas._libs.hashtable
???
pandas/_libs/missing.pyx:1: <span class="k">in</span> init pandas._libs.missing
???
/usr/lib/python3.8/site-packages/pandas/_libs/tslibs/__init__.py:30: <span class="k">in</span> <module>
from .conversion import OutOfBoundsTimedelta, localize_pydatetime
E ImportError: /usr/lib/python3.8/site-packages/pandas/_libs/tslibs/conversion.cpython-38-x86_64-linux-gnu.so: undefined symbol: pandas_datetime_to_datetimestruct
</pre></div>
</div>
<p>The easiest way to workaround the problem in ebuild is to append <code class="docutils literal notranslate"><span class="pre">-j1</span></code>
in <a class="reference internal" href="#python-compile">python_compile</a> sub-phase.</p>
<p>The common way of working around the problem upstream is to create
additional .c files that <code class="docutils literal notranslate"><span class="pre">#include</span></code> the original file, and use unique
source files for every extension.</p>
</section>
<section id="sub-phase-functions">
<h2>Sub-phase functions<a class="headerlink" href="#sub-phase-functions" title="Permalink to this headline">¶</a></h2>
<p>Ebuilds define phase functions in order to conveniently override parts
of the build process. <code class="docutils literal notranslate"><span class="pre">distutils-r1</span></code> extends this concept
by introducing <em>sub-phases</em>. All <code class="docutils literal notranslate"><span class="pre">src_*</span></code> phases in ebuild are split
into two sub-phases: <code class="docutils literal notranslate"><span class="pre">python_*</span></code> sub-phases that are run in a loop
for all enabled interpreters, and <code class="docutils literal notranslate"><span class="pre">python_*_all</span></code> sub-phases that
comprise the common code to be run only once.</p>
<p>Sub-phase functions behave similarly to phase functions. They are run
if defined by the ebuild. If they’re not, the default implementation
is run (if any). The ebuild overrides can call the default
as <code class="docutils literal notranslate"><span class="pre">distutils-r1_<sub-phase></span></code>, the same way it can call eclass’ phase
function defaults.</p>
<p>There are 10 sub-phases corresponding to 5 phase functions. They are
run in the following order:</p>
<ol class="arabic simple">
<li><p><code class="docutils literal notranslate"><span class="pre">python_prepare_all</span></code> (for <code class="docutils literal notranslate"><span class="pre">src_prepare</span></code>, has default)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">python_prepare</span></code> (for each impl.)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">python_configure</span></code> (for <code class="docutils literal notranslate"><span class="pre">src_configure</span></code>, foreach impl.)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">python_configure_all</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">python_compile</span></code> (for <code class="docutils literal notranslate"><span class="pre">src_compile</span></code>, for each impl., has default)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">python_compile_all</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">python_test</span></code> (for <code class="docutils literal notranslate"><span class="pre">src_test</span></code>, for each impl.)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">python_test_all</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">python_install</span></code> (for <code class="docutils literal notranslate"><span class="pre">src_install</span></code>, for each impl., has default)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">python_install_all</span></code> (has default)</p></li>
</ol>
<p>Note that normally all phases are run in the source directory, while
defining <code class="docutils literal notranslate"><span class="pre">${BUILD_DIR}</span></code> to a dedicated build directory for each
implementation. However, if in-source builds are enabled, all phases
are run in these build directories.</p>
<span class="target" id="index-3"></span><section id="python-prepare">
<span id="index-4"></span><h3>python_prepare<a class="headerlink" href="#python-prepare" title="Permalink to this headline">¶</a></h3>
<p><code class="docutils literal notranslate"><span class="pre">python_prepare_all</span></code> is responsible for applying changes
to the package sources that are common to all Python implementations.
The default implementation performs the tasks of <code class="docutils literal notranslate"><span class="pre">default_src_prepare</span></code>
(applying patches), as well as eclass-specific tasks: removing
<code class="docutils literal notranslate"><span class="pre">ez_setup</span></code> (method of bootstrapping setuptools used in old packages)
and handling <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code>. In the end, the function copies
sources to build dirs if in-source build is requested.</p>
<p>If additional changes need to be done to the package, either this
sub-phase or <code class="docutils literal notranslate"><span class="pre">src_prepare</span></code> in general can be replaced. However,
you should always call the original implementation from your override.
For example, you could use it to strip extraneous dependencies or broken
tests:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>python_prepare_all<span class="o">()</span> <span class="o">{</span>
<span class="c1"># FIXME</span>
rm tests/test_pytest_plugin.py <span class="o">||</span> die
sed -i -e <span class="s1">'s:test_testcase_no_app:_&:'</span> tests/test_test_utils.py <span class="o">||</span> die
<span class="c1"># remove pointless dep on pytest-cov</span>
sed -i -e <span class="s1">'/addopts/s/--cov=aiohttp//'</span> pytest.ini <span class="o">||</span> die
distutils-r1_python_prepare_all
<span class="o">}</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">python_prepare</span></code> is responsible for applying changes specific to one
interpreter. It has no default implementation. When defined, in-source
builds are enabled implicitly as sources need to be duplicated to apply
implementation-specific changes.</p>
<p>In the following example, it is used to remove a CLI script whose
dependencies only support Python 3.8 and 3.9 at the moment. Naturally,
since this modification needs to be done on a subset of all Python
interpreters, the eclass needs to keep a separate copy of the sources
for every one of them. This is why <code class="docutils literal notranslate"><span class="pre">python_prepare</span></code> automatically
enables in-source builds.</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>python_prepare<span class="o">()</span> <span class="o">{</span>
<span class="k">if</span> ! use cli <span class="o">||</span> ! has <span class="s2">"</span><span class="si">${</span><span class="nv">EPYTHON</span><span class="si">}</span><span class="s2">"</span> python3.<span class="o">{</span><span class="m">7</span>..9<span class="o">}</span><span class="p">;</span> <span class="k">then</span>
sed -i -e <span class="s1">'/console_scripts/d'</span> setup.py <span class="o">||</span> die
<span class="k">fi</span>
<span class="o">}</span>
</pre></div>
</div>
<span class="target" id="index-5"></span></section>
<section id="python-configure">
<span id="index-6"></span><h3>python_configure<a class="headerlink" href="#python-configure" title="Permalink to this headline">¶</a></h3>
<p><code class="docutils literal notranslate"><span class="pre">python_configure</span></code> and <code class="docutils literal notranslate"><span class="pre">python_configure_all</span></code> have no default
functionality. The former is convenient for running additional
configuration steps if needed by the package, the latter for defining
global environment variables.</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>python_configure<span class="o">()</span> <span class="o">{</span>
esetup.py configure <span class="k">$(</span>usex mpi --mpi <span class="s1">''</span><span class="k">)</span>
<span class="o">}</span>
</pre></div>
</div>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>python_configure_all<span class="o">()</span> <span class="o">{</span>
<span class="nv">DISTUTILS_ARGS</span><span class="o">=(</span>
--resourcepath<span class="o">=</span>/usr/share
--no-compress-manpages
<span class="o">)</span>
<span class="o">}</span>
</pre></div>
</div>
<span class="target" id="index-7"></span></section>
<section id="python-compile">
<span id="index-8"></span><h3>python_compile<a class="headerlink" href="#python-compile" title="Permalink to this headline">¶</a></h3>
<p><code class="docutils literal notranslate"><span class="pre">python_compile</span></code> normally builds the package. It is sometimes used
to pass additional arguments to the build step. For example, it can
be used to disable parallel extension builds in packages that are broken
with it:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>python_compile<span class="o">()</span> <span class="o">{</span>
distutils-r1_python_compile -j1
<span class="o">}</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">python_compile_all</span></code>
has no default implementation. It is convenient for performing
additional common build steps, in particular for building
the documentation (see <code class="docutils literal notranslate"><span class="pre">distutils_enable_sphinx</span></code>).</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>python_compile_all<span class="o">()</span> <span class="o">{</span>
use doc <span class="o">&&</span> emake -C docs html
<span class="o">}</span>
</pre></div>
</div>
<span class="target" id="index-9"></span></section>
<section id="python-test">
<span id="index-10"></span><h3>python_test<a class="headerlink" href="#python-test" title="Permalink to this headline">¶</a></h3>
<p><code class="docutils literal notranslate"><span class="pre">python_test</span></code> is responsible for running tests. It has no default
implementation but you are strongly encouraged to provide one (either
directly or via <code class="docutils literal notranslate"><span class="pre">distutils_enable_tests</span></code>). <code class="docutils literal notranslate"><span class="pre">python_test_all</span></code>
can be used to run additional testing code that is not specific
to Python.</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>python_test<span class="o">()</span> <span class="o">{</span>
<span class="s2">"</span><span class="si">${</span><span class="nv">EPYTHON</span><span class="si">}</span><span class="s2">"</span> TestBitVector/Test.py <span class="o">||</span> die <span class="s2">"Tests fail with </span><span class="si">${</span><span class="nv">EPYTHON</span><span class="si">}</span><span class="s2">"</span>
<span class="o">}</span>
</pre></div>
</div>
<span class="target" id="index-11"></span></section>
<section id="python-install">
<span id="index-12"></span><h3>python_install<a class="headerlink" href="#python-install" title="Permalink to this headline">¶</a></h3>
<p><code class="docutils literal notranslate"><span class="pre">python_install</span></code> installs the package’s Python part. It is usually
redefined in order to pass additional <code class="docutils literal notranslate"><span class="pre">setup.py</span></code> arguments
or to install additional Python modules.</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>python_install<span class="o">()</span> <span class="o">{</span>
distutils-r1_python_install
<span class="c1"># ensure data files for tests are getting installed too</span>
python_moduleinto collada/tests/
python_domodule collada/tests/data
<span class="o">}</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">python_install_all</span></code> installs documentation via <code class="docutils literal notranslate"><span class="pre">einstalldocs</span></code>.
It is usually defined by ebuilds to install additional common files
such as bash completions or examples.</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>python_install_all<span class="o">()</span> <span class="o">{</span>
<span class="k">if</span> use examples<span class="p">;</span> <span class="k">then</span>
docinto examples
dodoc -r Sample_Code/.
docompress -x /usr/share/doc/<span class="si">${</span><span class="nv">PF</span><span class="si">}</span>/examples
<span class="k">fi</span>
distutils-r1_python_install_all
<span class="o">}</span>
</pre></div>
</div>
</section>
</section>
<section id="passing-arguments-to-setup-py-commands">
<h2>Passing arguments to setup.py commands<a class="headerlink" href="#passing-arguments-to-setup-py-commands" title="Permalink to this headline">¶</a></h2>
<p>The PEP 517 mode does not support passing additional commands arguments
via <code class="docutils literal notranslate"><span class="pre">DISTUTILS_ARGS</span></code> anymore. Instead, the additional parameters
can be passed using the <code class="docutils literal notranslate"><span class="pre">setup.cfg</span></code> file.</p>
<p>For example, Pillow provides for configuring available backends via
additional <code class="docutils literal notranslate"><span class="pre">build_ext</span></code> command flags:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>setup.py build_ext --enable-tiff --disable-webp ...
</pre></div>
</div>
<p>The respective options can be setup via the configuration file, where
sections represent the commands and individual keys — options. Note
that dashes need to be replaced by underscores, and flag-style options
take boolean arguments. In this case, the ebuild can use:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>src_configure<span class="o">()</span> <span class="o">{</span>
cat >> setup.cfg <span class="s"><<-EOF</span>
<span class="s"> [build_ext]</span>
<span class="s"> disable_tiff = $(usex !tiff True False)</span>
<span class="s"> enable_tiff = $(usex tiff True False)</span>
<span class="s"> disable_webp = $(usex !webp True False)</span>
<span class="s"> enable_webp = $(usex webp True False)</span>
<span class="s"> #...</span>
<span class="s"> EOF</span>
<span class="o">}</span>
</pre></div>
</div>
<p>Note that this method works only for arguments to specific commands.
Some packages use hacks to support global options, e.g. via manipulating
<code class="docutils literal notranslate"><span class="pre">sys.argv</span></code> directly. This is no longer possible with PEP 517 builds
and the packages need to be fixed not to rely on it. The possible
alternatives include using environment variables or custom commands.</p>
</section>
<section id="calling-custom-setup-py-commands">
<span id="index-13"></span><h2>Calling custom setup.py commands<a class="headerlink" href="#calling-custom-setup-py-commands" title="Permalink to this headline">¶</a></h2>
<p>When working on packages using setuptools or modified distutils, you
sometimes need to manually invoke <code class="docutils literal notranslate"><span class="pre">setup.py</span></code>. The eclass provides
a <code class="docutils literal notranslate"><span class="pre">esetup.py</span></code> helper that wraps it with additional checks, error
handling and ensures that the override configuration file is created
beforehand (much like <code class="docutils literal notranslate"><span class="pre">econf</span></code> or <code class="docutils literal notranslate"><span class="pre">emake</span></code>).</p>
<p><code class="docutils literal notranslate"><span class="pre">esetup.py</span></code> passes all its paremeters to <code class="docutils literal notranslate"><span class="pre">./setup.py</span></code>.</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>python_test<span class="o">()</span> <span class="o">{</span>
esetup.py check
<span class="o">}</span>
</pre></div>
</div>
</section>
<section id="preventing-test-directory-from-being-installed">
<h2>Preventing test directory from being installed<a class="headerlink" href="#preventing-test-directory-from-being-installed" title="Permalink to this headline">¶</a></h2>
<p>Many packages using the setuptools build system utilize the convenient
<code class="docutils literal notranslate"><span class="pre">find_packages()</span></code> method to locate the Python sources. In some cases,
this method also wrongly grabs top-level test directories or other files
that were not intended to be installed.</p>
<p>The eclass attempts to detect and report the most common mistakes:</p>
<div class="highlight-console notranslate"><div class="highlight"><pre><span></span><span class="go">* Package installs 'tests' package which is forbidden and likely a bug in the build system.</span>
</pre></div>
</div>
<p>The correct fix for this problem is to add an <code class="docutils literal notranslate"><span class="pre">exclude</span></code> parameter
to the <code class="docutils literal notranslate"><span class="pre">find_packages()</span></code> call in <code class="docutils literal notranslate"><span class="pre">setup.py</span></code>, e.g.:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">setup</span><span class="p">(</span>
<span class="n">packages</span><span class="o">=</span><span class="n">find_packages</span><span class="p">(</span><span class="n">exclude</span><span class="o">=</span><span class="p">[</span><span class="s2">"tests"</span><span class="p">,</span> <span class="s2">"tests.*"</span><span class="p">]))</span>
</pre></div>
</div>
<p>Note that if the top-level <code class="docutils literal notranslate"><span class="pre">tests</span></code> package has any subpackages, both
<code class="docutils literal notranslate"><span class="pre">tests</span></code> and <code class="docutils literal notranslate"><span class="pre">tests.*</span></code> need to be listed.</p>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>In order to test your fix properly, you need to remove the previous
build directory. Otherwise, the install command will install all
files found there, including the files that are now excluded.</p>
</div>
<p>As an intermediate solution it is possible to strip the extra
directories in the install phase:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>python_install<span class="o">()</span> <span class="o">{</span>
rm -r <span class="s2">"</span><span class="si">${</span><span class="nv">BUILD_DIR</span><span class="si">}</span><span class="s2">"</span>/lib/tests <span class="o">||</span> die
distutils-r1_python_install
<span class="o">}</span>
</pre></div>
</div>
</section>
<section id="enabling-tests">
<span id="index-14"></span><h2>Enabling tests<a class="headerlink" href="#enabling-tests" title="Permalink to this headline">¶</a></h2>
<p>Since Python performs only minimal build-time (or more precisely,
import-time) checking of correctness, it is important to run tests
of Python packages in order to catch any problems early. This is
especially important for permitting others to verify support for new
Python implementations.</p>
<p>Many Python packages use one of the standard test runners, and work fine
with the default ways of calling them. Note that upstreams sometimes
specify a test runner that’s not strictly necessary — e.g. specify
<code class="docutils literal notranslate"><span class="pre">dev-python/pytest</span></code> as a dependency while the tests do not use it
anywhere and work just fine with built-in modules. The best way
to determine the test runner to use is to grep the test sources.</p>
<section id="using-distutils-enable-tests">
<h3>Using distutils_enable_tests<a class="headerlink" href="#using-distutils-enable-tests" title="Permalink to this headline">¶</a></h3>
<p>The simplest way of enabling tests is to call <code class="docutils literal notranslate"><span class="pre">distutils_enable_tests</span></code>
in global scope, passing the test runner name as the first argument.
This function takes care of declaring test phase, setting appropriate
dependencies and <code class="docutils literal notranslate"><span class="pre">test</span></code> USE flag if necessary. If called after
setting <code class="docutils literal notranslate"><span class="pre">RDEPEND</span></code>, it also copies it to test dependencies.</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span> <span class="c1"># Copyright 1999-2020 Gentoo Authors</span>
<span class="c1"># Distributed under the terms of the GNU General Public License v2</span>
<span class="nv">EAPI</span><span class="o">=</span><span class="m">7</span>
<span class="nv">PYTHON_COMPAT</span><span class="o">=(</span> python2_7 python3_<span class="o">{</span><span class="m">6</span>,7,8<span class="o">}</span> pypy3 <span class="o">)</span>
inherit distutils-r1
<span class="nv">DESCRIPTION</span><span class="o">=</span><span class="s2">"An easy whitelist-based HTML-sanitizing tool"</span>
<span class="nv">HOMEPAGE</span><span class="o">=</span><span class="s2">"https://github.com/mozilla/bleach https://pypi.org/project/bleach/"</span>
<span class="nv">SRC_URI</span><span class="o">=</span><span class="s2">"mirror://pypi/</span><span class="si">${</span><span class="nv">PN</span><span class="p">:</span><span class="nv">0</span><span class="p">:</span><span class="nv">1</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">PN</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">P</span><span class="si">}</span><span class="s2">.tar.gz"</span>
<span class="nv">LICENSE</span><span class="o">=</span><span class="s2">"Apache-2.0"</span>
<span class="nv">SLOT</span><span class="o">=</span><span class="s2">"0"</span>
<span class="nv">KEYWORDS</span><span class="o">=</span><span class="s2">"~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sparc ~x86"</span>
<span class="nv">RDEPEND</span><span class="o">=</span><span class="s2">"</span>
<span class="s2"> dev-python/six[</span><span class="si">${</span><span class="nv">PYTHON_USEDEP</span><span class="si">}</span><span class="s2">]</span>
<span class="s2"> dev-python/webencodings[</span><span class="si">${</span><span class="nv">PYTHON_USEDEP</span><span class="si">}</span><span class="s2">]</span>
<span class="s2"> "</span>
<span class="hll"> distutils_enable_tests pytest
</span></pre></div>
</div>
<p>The valid values include:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">nose</span></code> for <code class="docutils literal notranslate"><span class="pre">dev-python/nose</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">pytest</span></code> for <code class="docutils literal notranslate"><span class="pre">dev-python/pytest</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">setup.py</span></code> to call <code class="docutils literal notranslate"><span class="pre">setup.py</span> <span class="pre">test</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">unittest</span></code> to use built-in unittest discovery</p></li>
</ul>
</section>
<section id="adding-more-test-dependencies">
<h3>Adding more test dependencies<a class="headerlink" href="#adding-more-test-dependencies" title="Permalink to this headline">¶</a></h3>
<p>Additional test dependencies can be specified in <code class="docutils literal notranslate"><span class="pre">test?</span></code> conditional.
The flag normally does not need to be explicitly declared,
as <code class="docutils literal notranslate"><span class="pre">distutils_enable_tests</span></code> does that in the majority of cases.</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span> <span class="c1"># Copyright 1999-2020 Gentoo Authors</span>
<span class="c1"># Distributed under the terms of the GNU General Public License v2</span>
<span class="nv">EAPI</span><span class="o">=</span><span class="m">6</span>
<span class="nv">PYTHON_COMPAT</span><span class="o">=(</span> python2_7 python3_<span class="o">{</span><span class="m">6</span>,7,8<span class="o">}</span> pypy3 <span class="o">)</span>
inherit distutils-r1
<span class="nv">DESCRIPTION</span><span class="o">=</span><span class="s2">"Universal encoding detector"</span>
<span class="nv">HOMEPAGE</span><span class="o">=</span><span class="s2">"https://github.com/chardet/chardet https://pypi.org/project/chardet/"</span>
<span class="nv">SRC_URI</span><span class="o">=</span><span class="s2">"https://github.com/chardet/chardet/archive/</span><span class="si">${</span><span class="nv">PV</span><span class="si">}</span><span class="s2">.tar.gz -> </span><span class="si">${</span><span class="nv">P</span><span class="si">}</span><span class="s2">.tar.gz"</span>
<span class="nv">LICENSE</span><span class="o">=</span><span class="s2">"LGPL-2.1"</span>
<span class="nv">SLOT</span><span class="o">=</span><span class="s2">"0"</span>
<span class="nv">KEYWORDS</span><span class="o">=</span><span class="s2">"~alpha amd64 arm arm64 hppa ia64 ~m68k ~mips ppc ppc64 s390 ~sh sparc x86 ~x64-cygwin ~amd64-linux ~x86-linux ~x64-macos ~x86-macos ~x64-solaris"</span>
<span class="nv">DEPEND</span><span class="o">=</span><span class="s2">"</span>
<span class="hll"><span class="s2"> test? ( dev-python/hypothesis[</span><span class="si">${</span><span class="nv">PYTHON_USEDEP</span><span class="si">}</span><span class="s2">] )</span>
</span><span class="s2"> "</span>
<span class="hll"> distutils_enable_tests pytest
</span></pre></div>
</div>
<p>Note that <code class="docutils literal notranslate"><span class="pre">distutils_enable_tests</span></code> modifies variables directly
in the ebuild environment. This means that if you wish to change their
values, you need to append to them, i.e. the bottom part of that ebuild
can be rewritten as:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span> distutils_enable_tests pytest
<span class="hll"> <span class="nv">DEPEND</span><span class="o">+=</span><span class="s2">"</span>
</span><span class="s2"> test? ( dev-python/hypothesis[</span><span class="si">${</span><span class="nv">PYTHON_USEDEP</span><span class="si">}</span><span class="s2">] )</span>
<span class="s2"> "</span>
</pre></div>
</div>
</section>
<section id="installing-the-package-before-running-tests">
<h3>Installing the package before running tests<a class="headerlink" href="#installing-the-package-before-running-tests" title="Permalink to this headline">¶</a></h3>
<p>In PEP 517 mode, the eclass automatically exposes a venv-style install
tree to the test phase. No explicit action in necessary.</p>
<p>In the legacy mode, <code class="docutils literal notranslate"><span class="pre">distutils_enable_tests</span></code> has an optional
<code class="docutils literal notranslate"><span class="pre">--install</span></code> option that can be used to force performing an install
to a temporary directory. More information can be found in the legacy
section.</p>
</section>
<section id="undesirable-test-dependencies">
<h3>Undesirable test dependencies<a class="headerlink" href="#undesirable-test-dependencies" title="Permalink to this headline">¶</a></h3>
<p>There is a number of packages that are frequently listed as test
dependencies upstream but have little to no value for Gentoo users.
It is recommended to skip those test dependencies whenever possible.
If tests fail to run without them, it is often preferable to strip
the dependencies and/or configuration values enforcing them.</p>
<p><em>Coverage testing</em> establishes how much of the package’s code is covered
by the test suite. While this is useful statistic upstream, it has
no value for Gentoo users who just want to install the package. This
is often represented by dependencies on <code class="docutils literal notranslate"><span class="pre">dev-python/coverage</span></code>,
<code class="docutils literal notranslate"><span class="pre">dev-python/pytest-cov</span></code>. In the latter case, you usually need
to strip <code class="docutils literal notranslate"><span class="pre">--cov</span></code> parameter from <code class="docutils literal notranslate"><span class="pre">pytest.ini</span></code>.</p>
<p><em>PEP-8 testing</em> enforces standard coding style across Python programs.
Issues found by it are relevant to upstream but entirely irrelevant
to Gentoo users. If the package uses <code class="docutils literal notranslate"><span class="pre">dev-python/pep8</span></code>,
<code class="docutils literal notranslate"><span class="pre">dev-python/pycodestyle</span></code>, <code class="docutils literal notranslate"><span class="pre">dev-python/flake8</span></code>, strip that
dependency.</p>
<p><code class="docutils literal notranslate"><span class="pre">dev-python/pytest-runner</span></code> is a thin wrapper to run pytest
from <code class="docutils literal notranslate"><span class="pre">setup.py</span></code>. Do not use it, just call pytest directly.</p>
<p><code class="docutils literal notranslate"><span class="pre">dev-python/tox</span></code> is a convenient wrapper to run tests for multiple
Python versions, in a virtualenv. The eclass already provides the logic
for the former, and an environment close enough to the latter. Do not
use tox in ebuilds.</p>
</section>
<section id="customizing-the-test-phase">
<h3>Customizing the test phase<a class="headerlink" href="#customizing-the-test-phase" title="Permalink to this headline">¶</a></h3>
<p>If additional pre-/post-test phase actions need to be performed,
they can be easily injected via overriding <code class="docutils literal notranslate"><span class="pre">src_test()</span></code> and making
it call <code class="docutils literal notranslate"><span class="pre">distutils-r1_src_test</span></code>:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span> <span class="c1"># Copyright 1999-2020 Gentoo Authors</span>
<span class="c1"># Distributed under the terms of the GNU General Public License v2</span>
<span class="nv">EAPI</span><span class="o">=</span><span class="m">7</span>
<span class="nv">PYTHON_COMPAT</span><span class="o">=(</span> python3_<span class="o">{</span><span class="m">6</span>,7,8<span class="o">}</span> <span class="o">)</span>
inherit distutils-r1 virtualx
<span class="nv">DESCRIPTION</span><span class="o">=</span><span class="s2">"Extra features for standard library's cmd module"</span>
<span class="nv">HOMEPAGE</span><span class="o">=</span><span class="s2">"https://github.com/python-cmd2/cmd2"</span>
<span class="nv">SRC_URI</span><span class="o">=</span><span class="s2">"mirror://pypi/</span><span class="si">${</span><span class="nv">PN</span><span class="p">:</span><span class="nv">0</span><span class="p">:</span><span class="nv">1</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">PN</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">P</span><span class="si">}</span><span class="s2">.tar.gz"</span>
<span class="nv">LICENSE</span><span class="o">=</span><span class="s2">"MIT"</span>
<span class="nv">SLOT</span><span class="o">=</span><span class="s2">"0"</span>
<span class="nv">KEYWORDS</span><span class="o">=</span><span class="s2">"~amd64 ~arm ~arm64 ~ppc64 ~x86 ~amd64-linux ~x86-linux"</span>
<span class="nv">RDEPEND</span><span class="o">=</span><span class="s2">"</span>
<span class="s2"> dev-python/attrs[</span><span class="si">${</span><span class="nv">PYTHON_USEDEP</span><span class="si">}</span><span class="s2">]</span>
<span class="s2"> >=dev-python/colorama-0.3.7[</span><span class="si">${</span><span class="nv">PYTHON_USEDEP</span><span class="si">}</span><span class="s2">]</span>
<span class="s2"> >=dev-python/pyperclip-1.6[</span><span class="si">${</span><span class="nv">PYTHON_USEDEP</span><span class="si">}</span><span class="s2">]</span>
<span class="s2"> dev-python/six[</span><span class="si">${</span><span class="nv">PYTHON_USEDEP</span><span class="si">}</span><span class="s2">]</span>
<span class="s2"> dev-python/wcwidth[</span><span class="si">${</span><span class="nv">PYTHON_USEDEP</span><span class="si">}</span><span class="s2">]</span>
<span class="s2"> "</span>
<span class="nv">BDEPEND</span><span class="o">=</span><span class="s2">"</span>
<span class="s2"> dev-python/setuptools_scm[</span><span class="si">${</span><span class="nv">PYTHON_USEDEP</span><span class="si">}</span><span class="s2">]</span>
<span class="s2"> "</span>
distutils_enable_tests pytest
<span class="hll"> src_test<span class="o">()</span> <span class="o">{</span>
</span><span class="hll"> <span class="c1"># tests rely on very specific text wrapping...</span>
</span><span class="hll"> <span class="nb">local</span> -x <span class="nv">COLUMNS</span><span class="o">=</span><span class="m">80</span>
</span><span class="hll"> distutils-r1_src_test
</span><span class="hll"> <span class="o">}</span>
</span></pre></div>
</div>
<p>If the actual test command needs to be customized, or a non-standard
test tool needs to be used, you can define a <code class="docutils literal notranslate"><span class="pre">python_test()</span></code> sub-phase
function. This function is called for every enabled Python target
by the default <code class="docutils literal notranslate"><span class="pre">src_test</span></code> implementation. This can either be combined
with <code class="docutils literal notranslate"><span class="pre">distutils_enable_tests</span></code> call, or used instead of it. In fact,
the former function simply defines a <code class="docutils literal notranslate"><span class="pre">python_test()</span></code> function as part
of its logic.</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span> <span class="c1"># Copyright 1999-2020 Gentoo Authors</span>
<span class="c1"># Distributed under the terms of the GNU General Public License v2</span>
<span class="nv">EAPI</span><span class="o">=</span><span class="m">7</span>
<span class="nv">PYTHON_COMPAT</span><span class="o">=(</span> python<span class="o">{</span>2_7,3_6,3_7,3_8<span class="o">}</span> pypy3 <span class="o">)</span>
inherit distutils-r1
<span class="nv">DESCRIPTION</span><span class="o">=</span><span class="s2">"Bash tab completion for argparse"</span>
<span class="nv">HOMEPAGE</span><span class="o">=</span><span class="s2">"https://pypi.org/project/argcomplete/"</span>
<span class="nv">SRC_URI</span><span class="o">=</span><span class="s2">"mirror://pypi/</span><span class="si">${</span><span class="nv">PN</span><span class="p">:</span><span class="nv">0</span><span class="p">:</span><span class="nv">1</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">PN</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">P</span><span class="si">}</span><span class="s2">.tar.gz"</span>
<span class="nv">LICENSE</span><span class="o">=</span><span class="s2">"Apache-2.0"</span>
<span class="nv">SLOT</span><span class="o">=</span><span class="s2">"0"</span>
<span class="nv">KEYWORDS</span><span class="o">=</span><span class="s2">"~amd64 ~arm ~arm64 ~hppa ~x86 ~amd64-linux ~x86-linux ~x64-macos"</span>
<span class="hll"> <span class="nv">IUSE</span><span class="o">=</span><span class="s2">"test"</span>
</span><span class="hll"> <span class="nv">RESTRICT</span><span class="o">=</span><span class="s2">"!test? ( test )"</span>
</span>
<span class="nv">RDEPEND</span><span class="o">=</span><span class="s2">"</span>
<span class="s2"> </span><span class="k">$(</span>python_gen_cond_dep <span class="s1">'</span>
<span class="s1"> <dev-python/importlib_metadata-2[${PYTHON_USEDEP}]</span>
<span class="s1"> '</span> -2 python3_<span class="o">{</span><span class="m">5</span>,6,7<span class="o">}</span> pypy3<span class="k">)</span><span class="s2">"</span>
<span class="c1"># pip is called as an external tool</span>
<span class="nv">BDEPEND</span><span class="o">=</span><span class="s2">"</span>
<span class="s2"> dev-python/setuptools[</span><span class="si">${</span><span class="nv">PYTHON_USEDEP</span><span class="si">}</span><span class="s2">]</span>
<span class="hll"><span class="s2"> test? (</span>
</span><span class="hll"><span class="s2"> app-shells/fish</span>
</span><span class="hll"><span class="s2"> app-shells/tcsh</span>
</span><span class="hll"><span class="s2"> dev-python/pexpect[</span><span class="si">${</span><span class="nv">PYTHON_USEDEP</span><span class="si">}</span><span class="s2">]</span>
</span><span class="hll"><span class="s2"> dev-python/pip</span>
</span><span class="hll"><span class="s2"> )"</span>
</span>
<span class="hll"> python_test<span class="o">()</span> <span class="o">{</span>
</span><span class="hll"> <span class="s2">"</span><span class="si">${</span><span class="nv">EPYTHON</span><span class="si">}</span><span class="s2">"</span> test/test.py -v <span class="o">||</span> die
</span><span class="hll"> <span class="o">}</span>
</span></pre></div>
</div>
<p>Note that <code class="docutils literal notranslate"><span class="pre">python_test</span></code> is called by <code class="docutils literal notranslate"><span class="pre">distutils-r1_src_test</span></code>,
so you must make sure to call it if you override <code class="docutils literal notranslate"><span class="pre">src_test</span></code>.</p>
</section>
<section id="customizing-the-test-phase-for-pytest">
<span id="index-15"></span><h3>Customizing the test phase for pytest<a class="headerlink" href="#customizing-the-test-phase-for-pytest" title="Permalink to this headline">¶</a></h3>
<p>For the relatively frequent case of pytest-based packages needing
additional customization, a <code class="docutils literal notranslate"><span class="pre">epytest</span></code> helper is provided. The helper
runs <code class="docutils literal notranslate"><span class="pre">pytest</span></code> with a standard set of options and automatic handling
of test failures.</p>
<p>For example, if upstream uses <code class="docutils literal notranslate"><span class="pre">network</span></code> marker to disable
network-based tests, you can override the test phase in the following
way:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>distutils_enable_tests pytest
python_test<span class="o">()</span> <span class="o">{</span>
epytest -m <span class="s1">'not network'</span>
<span class="o">}</span>
</pre></div>
</div>
</section>
</section>
<section id="building-documentation-via-sphinx">
<span id="index-16"></span><h2>Building documentation via Sphinx<a class="headerlink" href="#building-documentation-via-sphinx" title="Permalink to this headline">¶</a></h2>
<p><code class="docutils literal notranslate"><span class="pre">dev-python/sphinx</span></code> is commonly used to document Python packages.
It comes with a number of plugins and themes that make it convenient
to write and combine large text documents (such as this Guide!),
as well as automatically document Python code.</p>
<p>Depending on the exact package, building documentation may range
from being trivial to very hard. Packages that do not use autodoc
(documenting of Python code) do not need to USE-depend on Sphinx at all.
Packages that do that need to use a supported Python implementation
for Sphinx, and packages that use plugins need to guarantee the same
implementation across all plugins. To cover all those use cases easily,
the <code class="docutils literal notranslate"><span class="pre">distutils_enable_sphinx</span></code> function is provided.</p>
<section id="basic-documentation-with-autodoc">
<h3>Basic documentation with autodoc<a class="headerlink" href="#basic-documentation-with-autodoc" title="Permalink to this headline">¶</a></h3>
<p>The most common case is a package that uses Sphinx along with autodoc.
It can be recognized by <code class="docutils literal notranslate"><span class="pre">conf.py</span></code> listing <code class="docutils literal notranslate"><span class="pre">sphinx.ext.autodoc</span></code>
in the extension list. In order to support building documentation,
call <code class="docutils literal notranslate"><span class="pre">distutils_enable_sphinx</span></code> and pass the path to the directory
containing Sphinx documentation:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span> <span class="c1"># Copyright 1999-2020 Gentoo Authors</span>
<span class="c1"># Distributed under the terms of the GNU General Public License v2</span>
<span class="nv">EAPI</span><span class="o">=</span><span class="m">7</span>
<span class="nv">PYTHON_COMPAT</span><span class="o">=(</span> python3_<span class="o">{</span><span class="m">6</span>,7,8<span class="o">}</span> <span class="o">)</span>
<span class="nv">DISTUTILS_USE_SETUPTOOLS</span><span class="o">=</span>rdepend
inherit distutils-r1
<span class="nv">DESCRIPTION</span><span class="o">=</span><span class="s2">"Colored stream handler for the logging module"</span>
<span class="nv">HOMEPAGE</span><span class="o">=</span><span class="s2">"</span>
<span class="s2"> https://pypi.org/project/coloredlogs/</span>
<span class="s2"> https://github.com/xolox/python-coloredlogs</span>
<span class="s2"> https://coloredlogs.readthedocs.io/en/latest/"</span>
<span class="nv">SRC_URI</span><span class="o">=</span><span class="s2">"mirror://pypi/</span><span class="si">${</span><span class="nv">PN</span><span class="p">:</span><span class="nv">0</span><span class="p">:</span><span class="nv">1</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">PN</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">P</span><span class="si">}</span><span class="s2">.tar.gz"</span>
<span class="nv">LICENSE</span><span class="o">=</span><span class="s2">"MIT"</span>
<span class="nv">SLOT</span><span class="o">=</span><span class="s2">"0"</span>
<span class="nv">KEYWORDS</span><span class="o">=</span><span class="s2">"~amd64 ~x86 ~amd64-linux ~x86-linux"</span>
<span class="nv">RDEPEND</span><span class="o">=</span><span class="s2">"dev-python/humanfriendly[</span><span class="si">${</span><span class="nv">PYTHON_USEDEP</span><span class="si">}</span><span class="s2">]"</span>
<span class="hll"> distutils_enable_sphinx docs
</span></pre></div>
</div>
<p>This call takes care of it all: it adds <code class="docutils literal notranslate"><span class="pre">doc</span></code> USE flag to control
building documentation, appropriate dependencies via the expert any-r1
API making it sufficient for Sphinx to be installed with only one
of the supported implementations, and appropriate <code class="docutils literal notranslate"><span class="pre">python_compile_all</span></code>
implementation to build and install HTML documentation.</p>
</section>
<section id="additional-sphinx-extensions">
<h3>Additional Sphinx extensions<a class="headerlink" href="#additional-sphinx-extensions" title="Permalink to this headline">¶</a></h3>
<p>It is not uncommon for packages to require additional third-party
extensions to Sphinx. Those include themes. In order to specify
dependencies on the additional packages, pass them as extra arguments
to <code class="docutils literal notranslate"><span class="pre">distutils_enable_sphinx</span></code>.</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span> <span class="c1"># Copyright 1999-2020 Gentoo Authors</span>
<span class="c1"># Distributed under the terms of the GNU General Public License v2</span>
<span class="nv">EAPI</span><span class="o">=</span><span class="m">7</span>
<span class="nv">PYTHON_COMPAT</span><span class="o">=(</span> pypy3 python3_<span class="o">{</span><span class="m">6</span>,7,8<span class="o">}</span> <span class="o">)</span>
inherit distutils-r1
<span class="nv">DESCRIPTION</span><span class="o">=</span><span class="s2">"Correctly inflect words and numbers"</span>
<span class="nv">HOMEPAGE</span><span class="o">=</span><span class="s2">"https://github.com/jazzband/inflect"</span>
<span class="nv">SRC_URI</span><span class="o">=</span><span class="s2">"mirror://pypi/</span><span class="si">${</span><span class="nv">PN</span><span class="p">:</span><span class="nv">0</span><span class="p">:</span><span class="nv">1</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">PN</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">P</span><span class="si">}</span><span class="s2">.tar.gz"</span>
<span class="nv">LICENSE</span><span class="o">=</span><span class="s2">"MIT"</span>
<span class="nv">SLOT</span><span class="o">=</span><span class="s2">"0"</span>
<span class="nv">KEYWORDS</span><span class="o">=</span><span class="s2">"~amd64 ~arm64 ~ia64 ~ppc ~ppc64 ~x86"</span>
<span class="hll"> distutils_enable_sphinx docs <span class="se">\</span>
</span><span class="hll"> <span class="s1">'>=dev-python/jaraco-packaging-3.2'</span> <span class="se">\</span>
</span><span class="hll"> <span class="s1">'>=dev-python/rst-linker-1.9'</span> <span class="se">\</span>
</span><span class="hll"> dev-python/alabaster
</span></pre></div>
</div>
<p>In this case, the function uses the any-r1 API to request one
of the supported implementations to be enabled on <em>all</em> of those
packages. However, it does not have to be the one in <code class="docutils literal notranslate"><span class="pre">PYTHON_TARGETS</span></code>
for this package.</p>
</section>
<section id="sphinx-without-autodoc-or-extensions">
<h3>Sphinx without autodoc or extensions<a class="headerlink" href="#sphinx-without-autodoc-or-extensions" title="Permalink to this headline">¶</a></h3>
<p>Finally, there are packages that use Sphinx purely to build
documentation from text files, without inspecting Python code.
For those packages, the any-r1 API can be omitted entirely and plain
dependency on <code class="docutils literal notranslate"><span class="pre">dev-python/sphinx</span></code> is sufficient. In this case,
the <code class="docutils literal notranslate"><span class="pre">--no-autodoc</span></code> option can be specified instead of additional
packages.</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span> <span class="c1"># Copyright 1999-2020 Gentoo Authors</span>
<span class="c1"># Distributed under the terms of the GNU General Public License v2</span>
<span class="nv">EAPI</span><span class="o">=</span><span class="m">7</span>
<span class="nv">PYTHON_COMPAT</span><span class="o">=(</span> python2_7 python3_<span class="o">{</span><span class="m">6</span>,7,8<span class="o">}</span> <span class="o">)</span>
inherit distutils-r1
<span class="nv">DESCRIPTION</span><span class="o">=</span><span class="s2">"Python Serial Port extension"</span>
<span class="nv">HOMEPAGE</span><span class="o">=</span><span class="s2">"https://github.com/pyserial/pyserial https://pypi.org/project/pyserial/"</span>
<span class="nv">SRC_URI</span><span class="o">=</span><span class="s2">"mirror://pypi/</span><span class="si">${</span><span class="nv">PN</span><span class="p">:</span><span class="nv">0</span><span class="p">:</span><span class="nv">1</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">PN</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">P</span><span class="si">}</span><span class="s2">.tar.gz"</span>
<span class="nv">LICENSE</span><span class="o">=</span><span class="s2">"PSF-2"</span>
<span class="nv">SLOT</span><span class="o">=</span><span class="s2">"0"</span>
<span class="nv">KEYWORDS</span><span class="o">=</span><span class="s2">"~alpha amd64 ~arm arm64 ~hppa ~ia64 ~m68k ~mips ~ppc ~ppc64 ~s390 ~sh ~sparc ~x86"</span>
<span class="hll"> distutils_enable_sphinx documentation --no-autodoc
</span></pre></div>
</div>
<p>Note that this is valid only if no third-party extensions are used.
If additional packages need to be installed, the previous variant
must be used instead.</p>
<p>The eclass tries to automatically determine whether <code class="docutils literal notranslate"><span class="pre">--no-autodoc</span></code>
should be used, and issue a warning if it’s missing or incorrect.</p>
</section>
</section>
</section>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<div class="sphinxsidebarwrapper">
<h1 class="logo"><a href="index.html">Gentoo Python Guide</a></h1>
<h3>Navigation</h3>
<p class="caption" role="heading"><span class="caption-text">Contents:</span></p>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="preface.html">Preface</a></li>
<li class="toctree-l1"><a class="reference internal" href="interpreter.html">Python interpreters</a></li>
<li class="toctree-l1"><a class="reference internal" href="eclass.html">Choosing between Python eclasses</a></li>
<li class="toctree-l1"><a class="reference internal" href="basic.html">Common basics</a></li>
<li class="toctree-l1"><a class="reference internal" href="any.html">python-any-r1 — build-time dependency</a></li>
<li class="toctree-l1"><a class="reference internal" href="single.html">python-single-r1 — single-impl packages</a></li>
<li class="toctree-l1"><a class="reference internal" href="multi.html">python-r1 — multi-impl packages</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="#">distutils-r1 — standard Python build systems</a><ul>
<li class="toctree-l2"><a class="reference internal" href="#the-pep-517-and-legacy-modes">The PEP 517 and legacy modes</a></li>
<li class="toctree-l2"><a class="reference internal" href="#basic-use-pep-517-mode">Basic use (PEP 517 mode)</a></li>
<li class="toctree-l2"><a class="reference internal" href="#dependencies">Dependencies</a></li>
<li class="toctree-l2"><a class="reference internal" href="#python-single-r1-variant">python-single-r1 variant</a></li>
<li class="toctree-l2"><a class="reference internal" href="#pep-517-build-systems">PEP 517 build systems</a></li>
<li class="toctree-l2"><a class="reference internal" href="#deprecated-pep-517-backends">Deprecated PEP 517 backends</a></li>
<li class="toctree-l2"><a class="reference internal" href="#setuptools-scm-and-snapshots">setuptools_scm and snapshots</a></li>
<li class="toctree-l2"><a class="reference internal" href="#parallel-build-race-conditions">Parallel build race conditions</a></li>
<li class="toctree-l2"><a class="reference internal" href="#sub-phase-functions">Sub-phase functions</a></li>
<li class="toctree-l2"><a class="reference internal" href="#passing-arguments-to-setup-py-commands">Passing arguments to setup.py commands</a></li>
<li class="toctree-l2"><a class="reference internal" href="#calling-custom-setup-py-commands">Calling custom setup.py commands</a></li>
<li class="toctree-l2"><a class="reference internal" href="#preventing-test-directory-from-being-installed">Preventing test directory from being installed</a></li>
<li class="toctree-l2"><a class="reference internal" href="#enabling-tests">Enabling tests</a></li>
<li class="toctree-l2"><a class="reference internal" href="#building-documentation-via-sphinx">Building documentation via Sphinx</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="distutils-legacy.html">distutils-r1 legacy concepts</a></li>
<li class="toctree-l1"><a class="reference internal" href="helper.html">Common helper functions</a></li>
<li class="toctree-l1"><a class="reference internal" href="depend.html">Advanced dependencies</a></li>
<li class="toctree-l1"><a class="reference internal" href="test.html">Resolving test suite problems</a></li>
<li class="toctree-l1"><a class="reference internal" href="pytest.html">pytest recipes</a></li>
<li class="toctree-l1"><a class="reference internal" href="concept.html">Advanced concepts</a></li>
<li class="toctree-l1"><a class="reference internal" href="expert-multi.html">Expert python-r1 usage</a></li>
<li class="toctree-l1"><a class="reference internal" href="buildsys.html">Integration with build systems written in Python</a></li>
<li class="toctree-l1"><a class="reference internal" href="porting.html">Porting tips</a></li>
<li class="toctree-l1"><a class="reference internal" href="migration.html">Migration guides</a></li>
<li class="toctree-l1"><a class="reference internal" href="package-maintenance.html">Python package maintenance</a></li>
<li class="toctree-l1"><a class="reference internal" href="interpreter-maintenance.html">Maintenance of Python implementations</a></li>
</ul>
<div class="relations">
<h3>Related Topics</h3>
<ul>
<li><a href="index.html">Documentation overview</a><ul>
<li>Previous: <a href="multi.html" title="previous chapter">python-r1 — multi-impl packages</a></li>
<li>Next: <a href="distutils-legacy.html" title="next chapter">distutils-r1 legacy concepts</a></li>
</ul></li>
</ul>
</div>
<div id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
</div>
</div>
<script>$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="footer">
©2020, Michał Górny, license: CC BY 4.0.
|
Powered by <a href="http://sphinx-doc.org/">Sphinx 4.4.0</a>
& <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
|
<a href="_sources/distutils.rst.txt"
rel="nofollow">Page source</a>
</div>
</body>
</html>
|