Предпочтительное решение: записать файлы в исходный каталог, удалить их после завершения sdist
Вы можете переопределить команду sdist
, чтобы записывать файлы в исходный каталог и очищать их после завершения команды:
import os
from distutils import dir_util
from setuptools import setup
from setuptools.command.sdist import sdist as sdist_orig
class sdist(sdist_orig):
def run(self):
# generate data files
genbase = os.path.join(os.path.dirname(__file__), 'temp')
self.mkpath(genbase)
with open(os.path.join(genbase, 'data.txt'), 'w') as fp:
fp.write('hello distutils world')
# run original sdist
super().run()
# clean up generated data files
dir_util.remove_tree(genbase, dry_run=self.dry_run)
setup(
...
data_files=[
('generated', ['temp/data.txt']),
],
cmdclass={'sdist': sdist},
)
Создание файлов данных без записи их в исходный каталог
Адаптация исходных метаданных в sdist
temp
Несмотря на то, что это достаточно грязно, наименее хакерским способом может быть обновление исходных метаданных непосредственно в каталоге sdist. Таким образом, у вас все еще будут действительные метаданные яйца, и вам не придется иметь дело с отсутствующими исходными файлами на всем пути sdist
.
genfiles = ['temp/data.txt']
class sdist(sdist_orig):
def make_release_tree(self, base_dir, files):
super().make_release_tree(base_dir, files)
for path in genfiles:
fullpath = os.path.join(base_dir, path)
self.mkpath(os.path.dirname(fullpath))
if not self.dry_run:
with open(fullpath, 'w') as fp:
fp.write('hello distutils world')
# also adapt source metadata file
cmd_egg_info = self.get_finalized_command('egg_info')
sourcemeta = os.path.join(base_dir,
cmd_egg_info.egg_name + '.egg-info',
'SOURCES.txt')
with open(sourcemeta, 'a') as fp:
fp.write('\n')
fp.write(path)
setup(
...,
data_files=[
('generated', genfiles),
],
cmdclass={'sdist': sdist},
)
По сути, сгенерированные файлы данных просто игнорируются до тех пор, пока не произойдет фактическое копирование исходных файлов. Затем генерируются файлы (вместо копирования существующих файлов), и, поскольку в противном случае исходные метаданные были бы неполными, они обновляются созданными файлами.
Записать несуществующие файлы в метаданные
Я бы настоятельно не рекомендовал этого делать.
Все остальные подходы были бы намного более грязными, так как они записывали бы несуществующие файлы в метаданные и заставляли бы distutils
/setuptools
игнорировать несуществующие файлы на всем пути генерации исходного дистрибутива. Но если вы настаиваете, вот решение с наименьшим возможным исправлением обезьяны:
genfiles = ['temp/data.txt']
class FileList(setuptools.command.egg_info.FileList):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.files += genfiles
def _safe_path(self, path):
return path in genfiles or super()._safe_path(path)
class sdist(sdist_orig):
def run(self):
# monkeypatch begin
FileListOrig = setuptools.command.egg_info.FileList
setuptools.command.egg_info.FileList = FileList
# monkeypatch end
super().run()
# restore the original class
setuptools.command.egg_info.FileList = FileListOrig
def make_release_tree(self, base_dir, files):
super().make_release_tree(base_dir, files)
for path in genfiles:
fullpath = os.path.join(base_dir, path)
self.mkpath(os.path.dirname(fullpath))
if not self.dry_run:
with open(fullpath, 'w') as fp:
fp.write('hello distutils world')
setup(
...,
data_files=[
('generated', genfiles),
],
cmdclass={'sdist': sdist},
)
person
hoefling
schedule
12.05.2018