How to distribute man page with package?
I publish a Python package. I'd like it to install a man page. How to do that?
I'm not sure that there is a great answer for this right now, nor am I sure how we'd support it in a cross platform way. It's a good question though.
Controversial though, using data_files are a common way at present like: https://github.com/nose-devs/nose/blob/master/setup.py#L109
This is same problem for completion scripts. I have a discussion for completion scripts at: https://github.com/vcstools/wstool/pull/39
Finally, we did like this. https://github.com/wkentaro/wstool/blob/68003a95c2bde7b26101a9621de814ff82a73b64/setup.py
See https://bugs.python.org/issue14102
Sphinx can build man pages: http://sphinx-doc.org/man/sphinx-build.html?highlight=command%20line
This is good because it can be wholly consistent with your HTML docs and module docstrings.
That said, I'm not sure what the workflow is to build the pages and distribute them, or to distribute the documentation and build it on install...
Yeah, I was tried that here. https://github.com/vcstools/wstool/blob/master/setup.py#L63
2015年10月1日木曜日、Leo [email protected]さんは書きました:
Sphinx can build man pages: http://sphinx-doc.org/man/sphinx-build.html?highlight=command%20line
This is good because it can be wholly consistent with your HTML docs and module docstrings.
That said, I'm not sure what the workflow is to build the pages and distribute them, or to distribute the documentation and build it on install...
— Reply to this email directly or view it on GitHub https://github.com/pypa/packaging-problems/issues/72#issuecomment-144738406 .
和田 健太郎 / Kentaro Wada http://wkentaro.com
This is how I add man/info pages (generated by Sphinx). This is added to the setup.py file. It assumes that somewhere in your project you have directories named man and/or info. It will then grab the appropriate files from there and put them in {os_prefix}/share/man/manX or {os_prefix}/share/info.
from glob import glob
import os
def find_dirs(dir_name):
for dir, dirs, files in os.walk('.'):
if dir_name in dirs:
yield os.path.relpath(os.path.join(dir, dir_name))
# Find all of the man/info pages
data_files = []
man_sections = {}
for dir in find_dirs('man'):
for file in os.listdir(dir):
section = file.split('.')[-1]
man_sections[section] = man_sections.get(section, []) + [os.path.join(dir, file)]
for section in man_sections:
data_files.append(('share/man/man'+section, man_sections[section]))
info_pages = {}
for dir in find_dirs('info'):
for file in glob(os.path.join(dir, '*.info')):
info_pages[dir] = info_pages.get(dir, []) + [file]
for dir in info_pages:
data_files.append(('share/info', info_pages[dir]))
setup(
# Put your stuff here
include_package_data=True,
exclude_package_data={'': ['*.pyc']},
data_files=data_files,
)
Apologies for appending to such an old issue, but I also struggled with this problem and thought that it might help others trying to do the same. In addition to the manpage generation problem outlined here, I have struggled with installation of the manpages in a place outside of the Python directory when using setuptools, which moves all data_files inside of the *.egg file rather than to a specified directory under prefix as under distutils.
I was able to solve this by making a small modification to the solution of @wkentaro which again bypasses setuptools and uses the install_data command of distutils. Example below.
from distutils.command.install_data import install_data
# ....
class WstoolBuild(build):
"""Run additional commands before build command"""
def run(self):
self.run_command('build_man')
self.run_command('install_data') # Force setuptools to use distutils.command.install_data
build.run(self)
# Similar for build_py
Though after looking at this, and seeing how much setuptools internally relies on distutils, I wonder if the better solution is to create an additional argument to setup (similar to scripts) which will copy these into a specified directory.
I would suggest if you wish your code to be a system-wide application, installed specifically on some particular linux distribution, which would have some particular location rules where it installs man files, the path of least resistance currently would be to simply include the man files in the project, but use a system package format like deb or rpm to specify how to install them on that system.
The basic reason this is hard is because pip does not focus on trying to be able to correctly handle installing packages on a system level. Distutils has tried a little in the past, but obviously where it got to has left very, very much to be desired.
Yes, I think I've come around to your thinking. It's a shame because using distutils mostly gives the desired result, but I can see how it could break spectacularly on another platform that installs Python in any place other than /usr.
If the data file way is acceptable to folks, here is Jupyter talking about their new/modern way they distribute extensions with Hatchling using that same concept https://blog.jupyter.org/packaging-for-jupyter-in-2022-c7be64c38926
That article doesn’t mention man pages, only the undefined concept of «extensions» — could you point to some doc or code, maybe in their hatch plugin, that would help here?
You can use the shared-data option, for example: https://github.com/jupyter/notebook/blob/4e6282c1e522dd6358ac0235365885188a2ca031/pyproject.toml#L83-L86