I have python module, named models.py which i would like to upload to PyPi. When afterwards i install it using pip i would like it to appear as a package.
To explain myself, I have following project structure:
my_utils
mapper/
models.py
MANIFEST.in
setup.py
README
logger/
logger.py
logger_conf.json
MANIFEST.in
README
setup.py
I would like to create a distributed package out mapper.models, but when it is being installed on target machine, i would like it to appear in site-packages under mapper_tools.models.
My setup.py:
from distutils.core import setup
setup(
name='mapper_tools',
version='0.1.0',
description='some description',
author='myname',
author_email='my#email.com',
url='https://github.com/mapper-tools',
py_modules=['models'],
)
My MANIFEST.in:
include models.py README
Currently, after running pip install mapper-tools, I find models.py right under site-packages and I would like it to appear under mapper_tools.
Can i specify the structure that should be installed without changing the layout of my project?
Related
I'm trying to let users write code as a python module (folder with __init__.py defined) under whatever folder name they see fit. After that I want to install that module as a python package but define the import name myself.
The folder structure would be like this:
project_name/
user_defined_name/
__init__.py
...
setup.py
According to this I should be able to add this to my setup.py to get it working:
setuptools.setup(
package_dir={'my_defined_name': 'user_defined_name'},
packages=['user_defined_name']
)
But the only way that I was able to access the code was by using import user_defined_name. I tried installing the package without -e but that gave the same result. Leaving the packages=['..'] out of the setup functions also did not change the result.
My question is kind of the same as this one and there the only answers seem to be to change folder names and that is something that I would like to avoid. That question mentioned that it might be due to a problem in setuptools but that seemed fixed 3 years ago.
In short, it looks like you need something like that in your setup.py:
setuptools.setup(
package_dir={
'my_defined_name': 'user_defined_name',
},
packages=[
'my_defined_name',
],
)
as Ilia Novoselov said in a comment to your question.
This should work, if you package and install the project normally. You would be able to import my_defined_name.
Although, note that as far as I can tell, this will not work if you use an editable installation (python setup.py develop or python -m pip install --editable .). It will be impossible to import my_defined_name, but you would be able to import user_defined_name, which is not what you want.
#Oliver's answer here clarified this for me.
My TLDR is that to support both releases (python setup.py install and pip install .) and editable installs (python setup.py develop and pip install -e .) you must change your file structure to
project_name
setup.py
user_defined_name
my_defined_name
__init__.py
...
docs
tests
and your setup.py to
setuptools.setup(
package_dir={'': 'user_defined_name'},
packages=['my_defined_name']
)
You can support just releases (NOT editable installs) with
project_name
setup.py
user_defined_name
__init__.py
...
docs
tests
setuptools.setup(
package_dir={'my_defined_name': 'user_defined_name'},
packages=['my_defined_name']
)
Assume the project directory structure is below:
test-package:
__init__.py
hello.py
setup.py
And the setup.py is:
from setuptools import setup, find_packages
setup(
name="test-package",
packages=find_packages(),
version="1.0",
include_package_data=True,
)
'test-package' is the root directory of the project. Then do:
pip install .
In the site-packages directory, there is only:
test_package-1.0-py3.7.egg-info/
I can't see the source file 'hello.py'.
I know most python projects's package name is not the root directory of the project. But in case I want to create a root directory name as the package name like this, is that possible?
You need to make a parent folder for test-package and put setup.py in there also use underscores for the package name. Technically PEP8 recommends all lowercase with no underscores for package names, but it's not a strict recommendation.
my-project:
setup.py
test_package:
__init__.py
hello.py
this has a helpful tutorial: https://packaging.python.org/tutorials/packaging-projects/
Edit: package name should use underscores not dashes
I have created a custom python package following this guide, so I have the following structure:
mypackage/ <-- VCS root
mypackage/
submodule1/
submodule2/
setup.py
And setup.py contains exactly the same information as in the guide:
from setuptools import setup, find_packages
setup(name='mypackage',
version='0.1',
description='desc',
url='vcs_url',
author='Hodossy, Szabolcs',
author_email='myemail#example.com',
license='MIT',
packages=find_packages(),
install_requires=[
# deps
],
zip_safe=False)
I have noticed if I go into the folder where setup.py is, and then call python setup.py install in a virtual environment, in site-packages the following structure is installed:
.../site-packages/mypackage-0.1-py3.6.egg/mypackage/
submodule1/
submodule2/
but if I call it from one folder up like python mypackage/setup.py install, then the structure is the following:
.../site-packages/mypackage-0.1-py3.6.egg/mypackage/
mypackage/
submodule1/
submodule2/
This later one ruins all imports from my module, as the path is different for the submodules.
Could you explain what is happening here and how to prevent that kind of behaviour?
This is experienced with Python 3.6 on both Windows and Linux.
Your setup.py does not contain any paths, but seems to only find the files via find_packages. So of course it depends from where you run it. The setup.py isn't strictly tied to its location. Of course you could do things like chdir to the basename of the setup file path in sys.argv[0], but that's rather ugly.
The question is, WHY do you want to build it that way? It looks more like you would want a structure like
mypackage-source
mypackage
submodule1
submodule2
setup.py
And then execute setup.py from the work directory. If you want to be able to run it from anywhere, the better workaround would be to put a shellscript next to it, like
#!/bin/sh
cd ``basename $0``
python setup.py $#
which separates the task of changing to the right directory (here I assume the directory with setup.py in the workdir) from running setup.py
I read a lot of answers on this question, but no solution works for me.
Project layout:
generators_data\
en_family_names.txt
en_female_names.txt
__init__.py
generators.py
setup.py
I want include "generators_data" with it's content into installation. My setup.py:
from distutils.core import setup
setup(name='generators',
version='1.0',
package_data={'generators': ['generators_data/*']}
)
I tried
python setup.py install
got
running install
running build
running install_egg_info
Removing c:\Python27\Lib\site-packages\generators-1.0-py2.7.egg-info
Writing c:\Python27\Lib\site-packages\generators-1.0-py2.7.egg-info
but generators_data directory doesn't appear in "c:\Python27\Lib\site-packages\". Why?
The code you posted contains two issues: setup.py should be sibling to the package you want to distribute, not inside it, and you need to list packages in setup.py.
Try with this this layout:
generators/ # project root, the directory you get from git clone or equivalent
setup.py
generators/ # Python package
__init__.py
# other modules
generators_data/
names.txt
And this setup.py:
setup(name='generators',
version='1.0',
packages=['generators'],
package_data={'generators': ['generators_data/*']},
)
I'm trying to remove all of the tests directories as well as the tests.py files when creating an RPM from a setup.py file using bdist_rpm. I have tried excluding it from find_packages(), but it only removes tests packages, which is only half the issue. any tests.py files remain in packages that don't have a tests directory. How can I remove both tests directories and tests.py files? Here is my setup.py
from setuptools import setup, find_packages
setup(name='mydjangoui',
version='1.0',
description='A django application',
package_dir={'':'mydjangoui'},
packages=find_packages('mydjangoui',
exclude=['tests.*', '*.tests.*', '*.tests', 'tests']),
)
I'm building the rpm with the following command:
python setup.py bdist_rpm
There is an app (marketing) that contains tests.py, tests.pyo, tests.pyc as well as some valid models.py and views.py files. I want to remove the tests.py[o|c] files from this app before the RPM is created.
Output from find_packages(exclude=['*tests*'])
>>> find_packages(exclude=['*tests*'])
['motd', 'assessment', 'account', 'platform', 'custom', 'catalog', 'utils', 'asset', 'editors', 'scheduler', 'base', 'marketing', 'results']
Final update solving the problem:
Use the following find_packages() call to ignore any module or sub module named tests:
setup(name='mydjangoapp',
version='1.0',
description='A django app',
package_dir={'':'mock'},
packages=find_packages('mock', exclude=['tests', '*.tests']),
)
We might still have files named tests.py in our resulting RPM, though.
To purge these, create a file named MANIFEST.in inside your project folder and add the following line to it which tells distutils to ignore files named tests.py in any folder:
recursive-exclude * tests.py
This will not include, e.g., marketing/tests.py anymore.
If you get warnings about non-existing, previously defined files, clean up the generated files before re-creating the RPM package:
python setup.py clean --all
Hope that helps.