FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
python/Lib/distutils/command/sdist.py at master · pylee/python · GitHub
pylee
/
python
Public
forked from
glix/python
Notifications
You must be signed in to change notification settings
Fork
0
Star
1
Code
Pull requests
0
Actions
Projects
Wiki
Security and quality
0
Insights
Additional navigation options
Code
Pull requests
Actions
Projects
Wiki
Security and quality
Insights
Expand file tree
Breadcrumbs
python
/
Lib
/
distutils
/
command
/
sdist.py
Copy path
More file actions
More file actions
Latest commit
History
History
History
479 lines (393 loc) · 17.9 KB
Breadcrumbs
python
/
Lib
/
distutils
/
command
/
sdist.py
Copy path
File metadata and controls
479 lines (393 loc) · 17.9 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
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
"""distutils.command.sdist
Implements the Distutils 'sdist' command (create a source distribution)."""
__revision__
=
"$Id$"
import
os
,
string
import
sys
from
types
import
*
from
glob
import
glob
from
distutils
.
core
import
Command
from
distutils
import
dir_util
,
dep_util
,
file_util
,
archive_util
from
distutils
.
text_file
import
TextFile
from
distutils
.
errors
import
*
from
distutils
.
filelist
import
FileList
from
distutils
import
log
def
show_formats
():
"""Print all possible values for the 'formats' option (used by
the "--help-formats" command-line option).
"""
from
distutils
.
fancy_getopt
import
FancyGetopt
from
distutils
.
archive_util
import
ARCHIVE_FORMATS
formats
=
[]
for
format
in
ARCHIVE_FORMATS
.
keys
():
formats
.
append
((
"formats="
+
format
,
None
,
ARCHIVE_FORMATS
[
format
][
2
]))
formats
.
sort
()
pretty_printer
=
FancyGetopt
(
formats
)
pretty_printer
.
print_help
(
"List of available source distribution formats:"
)
class
sdist
(
Command
):
description
=
"create a source distribution (tarball, zip file, etc.)"
user_options
=
[
(
'template='
,
't'
,
"name of manifest template file [default: MANIFEST.in]"
),
(
'manifest='
,
'm'
,
"name of manifest file [default: MANIFEST]"
),
(
'use-defaults'
,
None
,
"include the default file set in the manifest "
"[default; disable with --no-defaults]"
),
(
'no-defaults'
,
None
,
"don't include the default file set"
),
(
'prune'
,
None
,
"specifically exclude files/directories that should not be "
"distributed (build tree, RCS/CVS dirs, etc.) "
"[default; disable with --no-prune]"
),
(
'no-prune'
,
None
,
"don't automatically exclude anything"
),
(
'manifest-only'
,
'o'
,
"just regenerate the manifest and then stop "
"(implies --force-manifest)"
),
(
'force-manifest'
,
'f'
,
"forcibly regenerate the manifest and carry on as usual"
),
(
'formats='
,
None
,
"formats for source distribution (comma-separated list)"
),
(
'keep-temp'
,
'k'
,
"keep the distribution tree around after creating "
+
"archive file(s)"
),
(
'dist-dir='
,
'd'
,
"directory to put the source distribution archive(s) in "
"[default: dist]"
),
]
boolean_options
=
[
'use-defaults'
,
'prune'
,
'manifest-only'
,
'force-manifest'
,
'keep-temp'
]
help_options
=
[
(
'help-formats'
,
None
,
"list available distribution formats"
,
show_formats
),
]
negative_opt
=
{
'no-defaults'
:
'use-defaults'
,
'no-prune'
:
'prune'
}
default_format
=
{
'posix'
:
'gztar'
,
'nt'
:
'zip'
}
def
initialize_options
(
self
):
# 'template' and 'manifest' are, respectively, the names of
# the manifest template and manifest file.
self
.
template
=
None
self
.
manifest
=
None
# 'use_defaults': if true, we will include the default file set
# in the manifest
self
.
use_defaults
=
1
self
.
prune
=
1
self
.
manifest_only
=
0
self
.
force_manifest
=
0
self
.
formats
=
None
self
.
keep_temp
=
0
self
.
dist_dir
=
None
self
.
archive_files
=
None
def
finalize_options
(
self
):
if
self
.
manifest
is
None
:
self
.
manifest
=
"MANIFEST"
if
self
.
template
is
None
:
self
.
template
=
"MANIFEST.in"
self
.
ensure_string_list
(
'formats'
)
if
self
.
formats
is
None
:
try
:
self
.
formats
=
[
self
.
default_format
[
os
.
name
]]
except
KeyError
:
raise
DistutilsPlatformError
, \
"don't know how to create source distributions "
+
\
"on platform %s"
%
os
.
name
bad_format
=
archive_util
.
check_archive_formats
(
self
.
formats
)
if
bad_format
:
raise
DistutilsOptionError
, \
"unknown archive format '%s'"
%
bad_format
if
self
.
dist_dir
is
None
:
self
.
dist_dir
=
"dist"
def
run
(
self
):
# 'filelist' contains the list of files that will make up the
# manifest
self
.
filelist
=
FileList
()
# Ensure that all required meta-data is given; warn if not (but
# don't die, it's not *that* serious!)
self
.
check_metadata
()
# Do whatever it takes to get the list of files to process
# (process the manifest template, read an existing manifest,
# whatever). File list is accumulated in 'self.filelist'.
self
.
get_file_list
()
# If user just wanted us to regenerate the manifest, stop now.
if
self
.
manifest_only
:
return
# Otherwise, go ahead and create the source distribution tarball,
# or zipfile, or whatever.
self
.
make_distribution
()
def
check_metadata
(
self
):
"""Ensure that all required elements of meta-data (name, version,
URL, (author and author_email) or (maintainer and
maintainer_email)) are supplied by the Distribution object; warn if
any are missing.
"""
metadata
=
self
.
distribution
.
metadata
missing
=
[]
for
attr
in
(
'name'
,
'version'
,
'url'
):
if
not
(
hasattr
(
metadata
,
attr
)
and
getattr
(
metadata
,
attr
)):
missing
.
append
(
attr
)
if
missing
:
self
.
warn
(
"missing required meta-data: "
+
string
.
join
(
missing
,
", "
))
if
metadata
.
author
:
if
not
metadata
.
author_email
:
self
.
warn
(
"missing meta-data: if 'author' supplied, "
+
"'author_email' must be supplied too"
)
elif
metadata
.
maintainer
:
if
not
metadata
.
maintainer_email
:
self
.
warn
(
"missing meta-data: if 'maintainer' supplied, "
+
"'maintainer_email' must be supplied too"
)
else
:
self
.
warn
(
"missing meta-data: either (author and author_email) "
+
"or (maintainer and maintainer_email) "
+
"must be supplied"
)
# check_metadata ()
def
get_file_list
(
self
):
"""Figure out the list of files to include in the source
distribution, and put it in 'self.filelist'. This might involve
reading the manifest template (and writing the manifest), or just
reading the manifest, or just using the default file set -- it all
depends on the user's options and the state of the filesystem.
"""
# If we have a manifest template, see if it's newer than the
# manifest; if so, we'll regenerate the manifest.
template_exists
=
os
.
path
.
isfile
(
self
.
template
)
if
template_exists
:
template_newer
=
dep_util
.
newer
(
self
.
template
,
self
.
manifest
)
# The contents of the manifest file almost certainly depend on the
# setup script as well as the manifest template -- so if the setup
# script is newer than the manifest, we'll regenerate the manifest
# from the template. (Well, not quite: if we already have a
# manifest, but there's no template -- which will happen if the
# developer elects to generate a manifest some other way -- then we
# can't regenerate the manifest, so we don't.)
self
.
debug_print
(
"checking if %s newer than %s"
%
(
self
.
distribution
.
script_name
,
self
.
manifest
))
setup_newer
=
dep_util
.
newer
(
self
.
distribution
.
script_name
,
self
.
manifest
)
# cases:
# 1) no manifest, template exists: generate manifest
# (covered by 2a: no manifest == template newer)
# 2) manifest & template exist:
# 2a) template or setup script newer than manifest:
# regenerate manifest
# 2b) manifest newer than both:
# do nothing (unless --force or --manifest-only)
# 3) manifest exists, no template:
# do nothing (unless --force or --manifest-only)
# 4) no manifest, no template: generate w/ warning ("defaults only")
manifest_outofdate
=
(
template_exists
and
(
template_newer
or
setup_newer
))
force_regen
=
self
.
force_manifest
or
self
.
manifest_only
manifest_exists
=
os
.
path
.
isfile
(
self
.
manifest
)
neither_exists
=
(
not
template_exists
and
not
manifest_exists
)
# Regenerate the manifest if necessary (or if explicitly told to)
if
manifest_outofdate
or
neither_exists
or
force_regen
:
if
not
template_exists
:
self
.
warn
((
"manifest template '%s' does not exist "
+
"(using default file list)"
)
%
self
.
template
)
self
.
filelist
.
findall
()
if
self
.
use_defaults
:
self
.
add_defaults
()
if
template_exists
:
self
.
read_template
()
if
self
.
prune
:
self
.
prune_file_list
()
self
.
filelist
.
sort
()
self
.
filelist
.
remove_duplicates
()
self
.
write_manifest
()
# Don't regenerate the manifest, just read it in.
else
:
self
.
read_manifest
()
# get_file_list ()
def
add_defaults
(
self
):
"""Add all the default files to self.filelist:
- README or README.txt
- setup.py
- test/test*.py
- all pure Python modules mentioned in setup script
- all C sources listed as part of extensions or C libraries
in the setup script (doesn't catch C headers!)
Warns if (README or README.txt) or setup.py are missing; everything
else is optional.
"""
standards
=
[(
'README'
,
'README.txt'
),
self
.
distribution
.
script_name
]
for
fn
in
standards
:
if
type
(
fn
)
is
TupleType
:
alts
=
fn
got_it
=
0
for
fn
in
alts
:
if
os
.
path
.
exists
(
fn
):
got_it
=
1
self
.
filelist
.
append
(
fn
)
break
if
not
got_it
:
self
.
warn
(
"standard file not found: should have one of "
+
string
.
join
(
alts
,
', '
))
else
:
if
os
.
path
.
exists
(
fn
):
self
.
filelist
.
append
(
fn
)
else
:
self
.
warn
(
"standard file '%s' not found"
%
fn
)
optional
=
[
'test/test*.py'
,
'setup.cfg'
]
for
pattern
in
optional
:
files
=
filter
(
os
.
path
.
isfile
,
glob
(
pattern
))
if
files
:
self
.
filelist
.
extend
(
files
)
if
self
.
distribution
.
has_pure_modules
():
build_py
=
self
.
get_finalized_command
(
'build_py'
)
self
.
filelist
.
extend
(
build_py
.
get_source_files
())
if
self
.
distribution
.
has_ext_modules
():
build_ext
=
self
.
get_finalized_command
(
'build_ext'
)
self
.
filelist
.
extend
(
build_ext
.
get_source_files
())
if
self
.
distribution
.
has_c_libraries
():
build_clib
=
self
.
get_finalized_command
(
'build_clib'
)
self
.
filelist
.
extend
(
build_clib
.
get_source_files
())
if
self
.
distribution
.
has_scripts
():
build_scripts
=
self
.
get_finalized_command
(
'build_scripts'
)
self
.
filelist
.
extend
(
build_scripts
.
get_source_files
())
# add_defaults ()
def
read_template
(
self
):
"""Read and parse manifest template file named by self.template.
(usually "MANIFEST.in") The parsing and processing is done by
'self.filelist', which updates itself accordingly.
"""
log
.
info
(
"reading manifest template '%s'"
,
self
.
template
)
template
=
TextFile
(
self
.
template
,
strip_comments
=
1
,
skip_blanks
=
1
,
join_lines
=
1
,
lstrip_ws
=
1
,
rstrip_ws
=
1
,
collapse_join
=
1
)
while
1
:
line
=
template
.
readline
()
if
line
is
None
:
# end of file
break
try
:
self
.
filelist
.
process_template_line
(
line
)
except
DistutilsTemplateError
,
msg
:
self
.
warn
(
"%s, line %d: %s"
%
(
template
.
filename
,
template
.
current_line
,
msg
))
# read_template ()
def
prune_file_list
(
self
):
"""Prune off branches that might slip into the file list as created
by 'read_template()', but really don't belong there:
* the build tree (typically "build")
* the release tree itself (only an issue if we ran "sdist"
previously with --keep-temp, or it aborted)
* any RCS, CVS, .svn, .hg, .git, .bzr, _darcs directories
"""
build
=
self
.
get_finalized_command
(
'build'
)
base_dir
=
self
.
distribution
.
get_fullname
()
self
.
filelist
.
exclude_pattern
(
None
,
prefix
=
build
.
build_base
)
self
.
filelist
.
exclude_pattern
(
None
,
prefix
=
base_dir
)
# pruning out vcs directories
# both separators are used under win32
if
sys
.
platform
==
'win32'
:
seps
=
r'/|\\'
else
:
seps
=
'/'
vcs_dirs
=
[
'RCS'
,
'CVS'
,
r'\.svn'
,
r'\.hg'
,
r'\.git'
,
r'\.bzr'
,
'_darcs'
]
vcs_ptrn
=
r'(^|%s)(%s)(%s).*'
%
(
seps
,
'|'
.
join
(
vcs_dirs
),
seps
)
self
.
filelist
.
exclude_pattern
(
vcs_ptrn
,
is_regex
=
1
)
def
write_manifest
(
self
):
"""Write the file list in 'self.filelist' (presumably as filled in
by 'add_defaults()' and 'read_template()') to the manifest file
named by 'self.manifest'.
"""
self
.
execute
(
file_util
.
write_file
,
(
self
.
manifest
,
self
.
filelist
.
files
),
"writing manifest file '%s'"
%
self
.
manifest
)
# write_manifest ()
def
read_manifest
(
self
):
"""Read the manifest file (named by 'self.manifest') and use it to
fill in 'self.filelist', the list of files to include in the source
distribution.
"""
log
.
info
(
"reading manifest file '%s'"
,
self
.
manifest
)
manifest
=
open
(
self
.
manifest
)
while
1
:
line
=
manifest
.
readline
()
if
line
==
''
:
# end of file
break
if
line
[
-
1
]
==
'
\n
'
:
line
=
line
[
0
:
-
1
]
self
.
filelist
.
append
(
line
)
manifest
.
close
()
# read_manifest ()
def
make_release_tree
(
self
,
base_dir
,
files
):
"""Create the directory tree that will become the source
distribution archive. All directories implied by the filenames in
'files' are created under 'base_dir', and then we hard link or copy
(if hard linking is unavailable) those files into place.
Essentially, this duplicates the developer's source tree, but in a
directory named after the distribution, containing only the files
to be distributed.
"""
# Create all the directories under 'base_dir' necessary to
# put 'files' there; the 'mkpath()' is just so we don't die
# if the manifest happens to be empty.
self
.
mkpath
(
base_dir
)
dir_util
.
create_tree
(
base_dir
,
files
,
dry_run
=
self
.
dry_run
)
# And walk over the list of files, either making a hard link (if
# os.link exists) to each one that doesn't already exist in its
# corresponding location under 'base_dir', or copying each file
# that's out-of-date in 'base_dir'. (Usually, all files will be
# out-of-date, because by default we blow away 'base_dir' when
# we're done making the distribution archives.)
if
hasattr
(
os
,
'link'
):
# can make hard links on this system
link
=
'hard'
msg
=
"making hard links in %s..."
%
base_dir
else
:
# nope, have to copy
link
=
None
msg
=
"copying files to %s..."
%
base_dir
if
not
files
:
log
.
warn
(
"no files to distribute -- empty manifest?"
)
else
:
log
.
info
(
msg
)
for
file
in
files
:
if
not
os
.
path
.
isfile
(
file
):
log
.
warn
(
"'%s' not a regular file -- skipping"
%
file
)
else
:
dest
=
os
.
path
.
join
(
base_dir
,
file
)
self
.
copy_file
(
file
,
dest
,
link
=
link
)
self
.
distribution
.
metadata
.
write_pkg_info
(
base_dir
)
# make_release_tree ()
def
make_distribution
(
self
):
"""Create the source distribution(s). First, we create the release
tree with 'make_release_tree()'; then, we create all required
archive files (according to 'self.formats') from the release tree.
Finally, we clean up by blowing away the release tree (unless
'self.keep_temp' is true). The list of archive files created is
stored so it can be retrieved later by 'get_archive_files()'.
"""
# Don't warn about missing meta-data here -- should be (and is!)
# done elsewhere.
base_dir
=
self
.
distribution
.
get_fullname
()
base_name
=
os
.
path
.
join
(
self
.
dist_dir
,
base_dir
)
self
.
make_release_tree
(
base_dir
,
self
.
filelist
.
files
)
archive_files
=
[]
# remember names of files we create
# tar archive must be created last to avoid overwrite and remove
if
'tar'
in
self
.
formats
:
self
.
formats
.
append
(
self
.
formats
.
pop
(
self
.
formats
.
index
(
'tar'
)))
for
fmt
in
self
.
formats
:
file
=
self
.
make_archive
(
base_name
,
fmt
,
base_dir
=
base_dir
)
archive_files
.
append
(
file
)
self
.
distribution
.
dist_files
.
append
((
'sdist'
,
''
,
file
))
self
.
archive_files
=
archive_files
if
not
self
.
keep_temp
:
dir_util
.
remove_tree
(
base_dir
,
dry_run
=
self
.
dry_run
)
def
get_archive_files
(
self
):
"""Return the list of archive files created when the command
was run, or None if the command hasn't run yet.
"""
return
self
.
archive_files
# class sdist
Back
|
FazBrowse Home
|
New Git URL