Python script dependent on data file (distutils) - python

I have the following directory structure :
data __ __init__.py
|__ file1
|__ file2
script
README
MANIFEST.in
__init__.py
setup.py
The Python script script uses the data files in data. I am trying to make a source tarball for this script so that it can be used systemwide.
The __init__.py file is empty. The file 'script' invokes the data files through 'data/file1' and data/file2. The contents of MANIFEST.in are:
include README script
recursive-include data *
In setup.py, amongst other things, I have :
packages = ["data"],
package_data = ["data": "*"],
scripts = ["script"]
After setting up the distribution (using sdist), I tried installing it on my system. When I try using script, it says :
Traceback (most recent call last):
File "/home/nsoum/anaconda/bin/script", line 54, in <module>
with open('data/file1', 'r') as do:
IOError: [Errno 2] No such file or directory: 'data/file1'
I guess this means that the relative paths of the data-files is not preserved. How do I work around that and make sure that my script has access to the data files ?
Thank you.

What happens is that open('data/file1', 'r') operates relative to the current working directory of the process while the path is really relative to the code file. The best way to get at data files relative to the code distribution is to use setuptools rather than bare distutils for building and distributing your package. setuptools has API for getting at a package's data resource files.

Related

Python Versioneer is not generating a -version.py file

I am trying to add versioning to my current Python project. I have installed Versioneer and setup the setup.cfg file to the best of my understanding of the documentation. When I run versioneer install I receive an error stating it cannot find the _version.py file. Below is the copy of the file and error I receive.
[versioneer]
VCS = git
style = pep440
versionfile_source = hw-assesment-tool/_version.py
versionfile_build = hw-assesment-tool/_version.py
tag_prefix =
parentdir_prefix =
and this is the error I get:
FileNotFoundError: [Errno 2] No such file or directory: 'hw-assesment-tool/_version.py'
I had that problem with a similar setup.cfg file, but in a tiny project with no nested directories and I ended up needing to remove the directory in front of _version.py because the versioneer.py script searches from the directory that contains the setup.cfg and so it was trying to look in a directory that didn't exist.
I'm not sure how your file structure is set up but it might work if you try changing it to:
versionfile_source = _version.py
versionfile_build = _version.py
If all your source files are in the same directory as the setup.cfg then that should fix it.

Irerate over package_data files and copy them to current working directory

Background
I'm developing a python package with roughly the following directory structure:
mossutils/
setup.py
mossutils/
__init__.py
init.py
data/
style.css
script.js
...
My package's setup.py declares console_scripts and includes package_data files:
setup(
name='mossutils',
packages=['mossutils'],
package_data={"mossutils": ["data/*"]},
entry_points = {
"console_scripts": ['mu-init = mossutils.init:main']
},
...)
Installing the package via pip install works as expected: everything is installed in my Python's Lib\site-packages, including the data directory and all files in it, and script mu-init can be executed from the shell (or rather, command prompt, since I'm using Windows).
Goal
Script mu-init is supposed to do some kind of project scaffolding in the current working directory it is invoked from. In particular, it should copy all package_data files (data/style.css, data/script.js, ...) to the current directory.
Solution Attempt
Using module pkgutil, I can read the content of a file, e.g.
import pkgutil
...
data = pkgutil.get_data(__name__, "data/style.css")
Questions
Is there a way for my init.py script to iterate over the contents of the data directory, without hard-coding the file names (in init.py)?
Can the files from the data directory be copied to the current working directory, without opening the source file, reading the content, and writing it to a destination file?
You can get the list of files in the directory using pkg_resources library, which is distributed together with setuptools.
import pkg_resources
pkg_resources.resource_listdir("mossutils", "data")

Creating an egg file generates only EGG-INFO folder

I have a python file named file_processor.py. I would like to create an egg file out of this python file to use it in another projects. My setup.py file looks as following:
from setuptools import setup, find_packages
setup(
name = "file_processor",
version = "0.5",
packages = find_packages()
)
And I run this script with the following command:
python setup.py bdist_egg
This command generates 3 folders, namely: build, dist, file_processor.egg-info. My .egg file is located in the dist folder. However, if I change its extension from .egg to .zip to see the contents, I find only one folder which is EGG-INFO, and not the actual python file. An so, if I try to add that .egg file into my project path and import file_processor module, python throws an error that no module named file_processor found. What am I doing wrong here? Note: I got the information for generating egg files from this link
Wheel files are generally preferred over eggs these days.
Regardless, I would guess that you don't have the file_processor.py in a separate directory and you have it in the same directory as the setup.py, it needs to be in it's own directory.
You should also include a __init__.py in that directory, inside the file you can put
from .file_processor import *
This will import all the functions from your file into the package so you can use them.
This tutorial is quite good if you're looking for more information https://python-packaging.readthedocs.io/en/latest/minimal.html

What is the graft command in Python's MANIFEST.in file?

I found a Python project with a MANIFEST.in file. I can guess at the meaning of much of it, but I am unclear on the meaning of the line:
graft tools
You can see such a file in JoshData/pdfminer/MANIFEST.in or openstack/deb-python-falcon/MANIFEST.in for instance.
It is a python project which uses the MANIFEST.in template
A MANIFEST.in file can be added in a project to define the list of files to include in the distribution built by the sdist command.
When sdist is run, it will look for the MANIFEST.in file and interpret it to generate the MANIFEST file that contains the list of files that will be included in the package.
The manifest template has one command per line, where each command specifies a set of files to include or exclude from the source distribution.
Among the MANIFEST commands, you do have:
graft dir
include all files under dir
See the Distutils tutorial
The MANIFEST.in file took me a while to understand.
It's the file that distutils uses to collect all the files in your project that will go into the final installer tarball (the file that gets distributed).

sphinx-build fail - autodoc can't import/find module

I'm trying to get started with Sphinx and seem to have relentless problems.
Command: docs/sphinx-quickstart
I answer all the questions and everything works fine.
Command: docs/ls
Everything looks normal. Result: build Makefile source
Command: sphinx-build -d build/doctrees source build/html
It seems to work. I was able to open the index.html file and see a "shell" of what I'm wanting.
When I try and put my actual source code as the source folder I run into problems.
Command: sphinx-build -d build/doctrees ../ys_utils build/html
Result:
Making output directory...
Running Sphinx v1.1.3
loading pickled environment... not yet created
No builder selected, using default: html
loading intersphinx inventory from http://docs.python.org/objects.inv...
building [html]: targets for 1 source files that are out of date
updating environment: 1 added, 0 changed, 0 removed
Traceback (most recent call last):
File "/usr/local/lib/python2.6/dist-packages/Sphinx-1.1.3-py2.6.egg/sphinx/ext/autodoc.py", line 321, in import_object
__import__(self.modname)
ImportError: No module named ys_utils
Traceback (most recent call last):
File "/usr/local/lib/python2.6/dist-packages/Sphinx-1.1.3-py2.6.egg/sphinx/ext/autodoc.py", line 321, in import_object
__import__(self.modname)
ImportError: No module named ys_utils.test_validate_ut
Traceback (most recent call last):
File "/usr/local/lib/python2.6/dist-packages/Sphinx-1.1.3-py2.6.egg/sphinx/ext/autodoc.py", line 321, in import_object
__import__(self.modname)
ImportError: No module named ys_utils.git_utils
Traceback (most recent call last):
File "/usr/local/lib/python2.6/dist-packages/Sphinx-1.1.3-py2.6.egg/sphinx/ext/autodoc.py", line 321, in import_object
__import__(self.modname)
ImportError: No module named setup.setup
/home/ricomoss/workspace/nextgen/ys_utils/ys_utils.rst:4: WARNING: autodoc can't import/find module 'ys_utils', it reported error: "No module named ys_utils", please check your spelling and sys.path
/home/ricomoss/workspace/nextgen/ys_utils/ys_utils.rst:10: WARNING: autodoc can't import/find module 'ys_utils.test_validate_ut', it reported error: "No module named ys_utils.test_validate_ut", please check your spelling and sys.path
/home/ricomoss/workspace/nextgen/ys_utils/ys_utils.rst:12: WARNING: don't know which module to import for autodocumenting u'UnitTests' (try placing a "module" or "currentmodule" directive in the document, or giving an explicit module name)
/home/ricomoss/workspace/nextgen/ys_utils/ys_utils.rst:18: WARNING: autodoc can't import/find module 'ys_utils.git_utils', it reported error: "No module named ys_utils.git_utils", please check your spelling and sys.path
/home/ricomoss/workspace/nextgen/ys_utils/ys_utils.rst:24: WARNING: autodoc can't import/find module 'setup.setup', it reported error: "No module named setup.setup", please check your spelling and sys.path
WARNING: master file /home/ricomoss/workspace/nextgen/ys_utils/index.rst not found
looking for now-outdated files... none found
pickling environment... done
checking consistency... /home/ricomoss/workspace/nextgen/ys_utils/ys_utils.rst:: WARNING: document isn't included in any toctree
done
preparing documents... done
writing output... [ 50%] index
Exception occurred:
File "/usr/local/lib/python2.6/dist-packages/Sphinx-1.1.3-py2.6.egg/sphinx/environment.py", line 1213, in get_doctree
f = open(doctree_filename, 'rb')
IOError: [Errno 2] No such file or directory: '/home/ricomoss/workspace/nextgen/docs/build/doctrees/index.doctree'
The full traceback has been saved in /tmp/sphinx-err-jjJ7gM.log, if you want to report the issue to the developers.
Please also report this if it was a user error, so that a better error message can be provided next time.
Either send bugs to the mailing list at <http://groups.google.com/group/sphinx-dev/>,
or report them in the tracker at <http://bitbucket.org/birkenfeld/sphinx/issues/>. Thanks!
What is wrong, and how can I fix it?
Edit:
I'd like to be able to use a Makefile to handle this. As of now I have two folders in my project.
nextgen/ls
docs ys_utils
I need nextgen/docs/Makefile to generate the HTML for ys_utils and all other modules I'm going to have.
Autodoc can't find your modules, because they are not in sys.path.
You have to include the path to your modules in in the sys.path in your conf.py.
Look at the top of your conf.py (just after the import of sys), there is a sys.path.insert() statement, which you can adapt.
By the way: you can use the Makefile created by Sphinx to create your documentation.
Just call
make
to see the options.
If something went wrong before try:
make clean
before running make html.
solution
It sounds like os.path.append() is working OK for folks, but if you follow the conf.py template, you would insert the module path to the front of sys.path using os.path.insert(0, ...), and just add an extra .
import os
import sys
sys.path.insert(0, os.path.abspath('..'))
If you have setup your sphinx project to use separate build and source directories, that call should instead be:
sys.path.insert(0, os.path.abspath('../..'))
about sys.path ...
To run python code, the python interpreter needs to know where it is. With the sphinx config being a python script, it's location needs to be made known, which is done by adding it the the sys.path variable using the insert method (see the docs on module search path).
The path added to sys.path in this case is a "relative" path, which is specified using dots. This is a general way of specifying the path, which allows the code to be moved and still point correctly to the correct path in your codebase.
. - current path of the conf.py
.. - parent path of the conf.py
../.. - parent of the parent path, etc.
I use linux, so directories are specified with a forward slash, but a cross-platform method for specifying parent directories can be acheived with pathlib.
from pathlib import Path
parent = Path(__file__).parent
parents_parent = Path(__file__).parents[1]
in conf.py
just add the path to your project folder.
sys.path.append('/home/workspace/myproj/myproj')
If
module root path is correctly set in conf.py
__init__.py is placed correctly
rst syntax is correct
and your autodoc still cannot find the modules...
It may be because the dependencies of those modules are not satisfied under your python environment. You will want to check if all the import statements are working within the modules.
I don't know why (maybe in my case autodoc couldn't install my package), but I always got module-not-found errors until I explicitly included all directories containing modules to the path.
For the following example folder structure
project_dir
|- setup.py
|- src
| |- __init__.py
| |- source1.py
| |- sub_project
| |- __init__.py
| |- source2.py
|- docs
|- conf.py
|- source
| |- index.rst
|- _build
I included
for x in os.walk('../../src'):
sys.path.insert(0, x[0])
to the beginning of conf.py such that all involved directories would be added.
I got this same error but it was caused by a completely different reason than explained in the other answers.
My .. automethod:: mymodule.func directive should actually have been:
.. automethod:: mymodule::func
See the New in version 1.3 section in the autoclass documentation.
i add the following line at the beggining of file conf.py:
import os
import sys
sys.path.insert(0, os.path.abspath('..'))
sys.path.append(os.path.abspath(
os.path.join(__file__, "../../src")
))
my project has the next structure:
project_dir
|- setup.py
|- src
| |- __init__.py
| |- ....
|- docs
|- conf.py
|- ...
I think I did this the first time I tried to add a file to the toctree. I think it was because I left out the blank line between the :maxdepth line and the file name.
.. Animatrix Concepts documentation master file, created by
sphinx-quickstart on Thu Mar 22 18:06:15 2012.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to Animatrix Concepts documentation!
============================================
Contents:
.. toctree::
:maxdepth: 2
stuff
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
Above is my index.rst file. stuff.rst resides in the same directory as it.
You can use Pweave and noweb formatting to generate rst documents that include the output of the code embedded in them. Basically, you write your rst file, with python code embedded in marked chunks like this:
<<echo=False>>=
print("some text that will appear in the rst file")
#
and Pweave will execute those chunks, and replace them with their output in a resulting rst file, which you can then use with sphinx. See the Pweave reST example for more details of how it looks.
A lot of solutions in the thread are discussed in the right direction.
For me, the command on the official docs was helpful.
import pathlib
import sys
sys.path.insert(0, pathlib.Path(__file__).parents[2].resolve().as_posix())

Categories