Как я могу упаковать файл css с помощью приложения для установки в одном флаконе с setuptools? - PullRequest
0 голосов
/ 03 мая 2018

Учитывая простое приложение для колб, которое организовано так:

app_repo/
--> flask_app.py
--> custom.css
--> setup.py
--> MANIFEST.in

Я хотел бы упаковать это для выпуска на PyPi, но у меня проблемы с упаковкой файла css вместе с приложением.

Файл setup.py выглядит следующим образом:

from setuptools import setup

setup(
    name='myapp',
    version='1',
    py_modules=['flask_app'],
    data_files=[('', ['custom.css'])],
    entry_points={'console_scripts':
                  ['runapp = flask_app:app.run_server']},    
)

Я также включаю файл custom.css в файл MANIFEST.in.

Внутри flask_app.py у меня есть строка вроде:

CSS_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'custom.css')

, которая позволяет мне направлять файл css с помощью send_from_directory Flask.

При разработке приложения из каталога репозитория и запуске колбы, приложение находит файл css и все работает правильно. Но когда я упаковываю приложение с помощью python setup.py sdist, файл css не помещается рядом с flask_app.py и, таким образом, не обнаруживается.

В unix запись data_files в setup.py приводит к тому, что установленные файлы выглядят так:

/usr/local/custom.css
/usr/local/lib/python3.6/site-packages/flask_app.py

Но я бы хотел, чтобы это отражало функциональность репозитория:

/usr/local/lib/python3.6/site-packages/custom.css
/usr/local/lib/python3.6/site-packages/flask_app.py

Есть ли способ иметь непакетное приложение для работы с отдельными файлами, которое можно установить и запустить из точки входа, которая гарантирует, что файл css находится в том же каталоге, где установлен модуль python?

Я знаю, что могу создать пакет, поместить файл app и css в пакет, а затем использовать package_data в файле setup.py, но я ищу решение, которое позволило бы мне не создавать никаких пакетов .

1 Ответ

0 голосов
/ 03 мая 2018

Существует способ размещения файлов данных в каталогах пакетов сайта, но он опирается на:

  1. строительные колёса (поэтому исходные коды запрещены)
  2. недокументированное поведение bdist_wheel, поэтому будьте осторожны, этот трюк может перестать работать с будущими версиями wheel пакета.

Изменить целевой каталог custom.css на /:

setup(
    data_files=[('/', ['custom.css'])],
    ...
)

Почему это работает? Это недокументированное поведение wheel: обычно, когда вы создаете и устанавливаете исходный дистрибутив (например, .tar.gz или .zip), файлы данных помещаются в указанный целевой каталог, например, data_files=[('/etc', ['hosts'])] перезапишет системный файл /etc/hosts (при условии, что у вас есть разрешение root). Как вы можете видеть, повреждение системы может быть произвольным, поэтому wheel избегает этого путем релятивизации абсолютных путей: в приведенном выше примере hosts будет записано не в /etc, а в /path/to/python/site-packages/etc. Вот что используется в уловке: файлы данных, которые должны быть записаны в системный корень (/), будут записаны в пакеты сайта.

Однако это нигде не задокументировано, поэтому может измениться в будущем. Следите за этой проблемой для окончательного решения.

Также имейте в виду, что если вы создаете исходный дистрибутив вместо колеса (через python setup.py sdist), его можно установить так, чтобы custom.css записывалось в системный корень вместо пакетов сайта:

$ pip install myapp --no-binary=myapp

Другое дело: вместо разрешения пути к файлу относительно flask_app.py вы можете использовать pkg_resources, поэтому вам не нужно возиться со строками пути:

from pkg_resources import Requirement, resource_filename
CSS_PATH = resource_filename(Requirement.parse('myapp'), 'custom.css')
...