calling external script during python package install - python

I am interested in building a Windows distribution for my application.
The application requires that a number of environmental variables and/or registry entries be set for the software to function properly. Supposing I write a script 'set_vars.py' to create and set these entries, is there a way to call this script when the application is installed via
python setup.py install
From the documentation detailing 'setup.py', I did not see an obvious way to call pre-install or post-install scripts.
I would rather not have set_vars.py called from an init.py in the distribution because the variables only really need to be set up once at install time.

Assuming you already have the needed action scripted, you could just --install-script=set_vars.py to your call to setup.py, or, even better (for convenience), add the option to your setup.cfg file.

Related

setuptools "eager_resources" to executable directory

I maintain a Python utility that allows bpy to be installable as a Python module. Due to the hugeness of the spurce code, and the length of time it takes to download the libraries, I have chosen to provide this module as a wheel.
Unfortunately, platform differences and Blender runtime expectations makes support for this tricky at times.
Currently, one of my big goals is to get the Blender addon scripts directory to install into the correct location. The directory (simply named after the version of Blender API) has to exist in the same directory as the Python executable.
Unfortunately the way that setuptools works (or at least the way that I have it configured) the 2.79 directory is not always placed as a sibling to the Python executable. It fails on Windows platforms outside of virtual environments.
However, I noticed in setuptools documentation that you can specify eager_resources that supposedly guarantees the location of extracted files.
https://setuptools.readthedocs.io/en/latest/setuptools.html#automatic-resource-extraction
https://setuptools.readthedocs.io/en/latest/pkg_resources.html#resource-extraction
There was a lot of hand waving and jargon in the documentation, and 0 examples. I'm really confused as to how to structure my setup.py file in order to guarantee the resource extraction. Currently, I just label the whole 2.79 directory as "scripts" in my setuptools Extension and ship it.
Is there a way to write my setup.py and package my module so as to guarantee the 2.79 directory's location is the same as the currently running python executable when someone runs
py -3.6.8-32 -m pip install bpy
Besides simply "hacking it in"? I was considering writing a install_requires module that would simply move it if possible but that is mangling with the user's file system and kind of hacky. However it's the route I am going to go if this proves impossible.
Here is the original issue for anyone interested.
https://github.com/TylerGubala/blenderpy/issues/13
My build process is identical to the process descsribed in my answer here
https://stackoverflow.com/a/51575996/6767685
Maybe try the data_files option of distutils/setuptools.
You could start by adding data_files=[('mydata', ['setup.py'],)], to your setuptools.setup function call. Build a wheel, then install it and see if you can find mydata/setup.py somewhere in your sys.prefix.
In your case the difficult part will be to compute the actual target directory (mydata in this example). It will depend on the platform (Linux, Windows, etc.), if it's in a virtual environment or not, if it's a global or local install (not actually feasible with wheels currently, see update below) and so on.
Finally of course, check that everything gets removed cleanly on uninstall. It's a bit unnecessary when working with virtual environments, but very important in case of a global installation.
Update
Looks like your use case requires a custom step at install time of your package (since the location of the binary for the Python interpreter relative to sys.prefix can not be known in advance). This can not be done currently with wheels. You have seen it yourself in this discussion.
Knowing this, my recommendation would be to follow the advice from Jan Vlcinsky in his comment for his answer to this question:
Post install script after installing a wheel.
Add an extra setuptools console entry point to your package (let's call it bpyconfigure).
Instruct the users of your package to run it immediately after installing your package (pip install bpy && bpyconfigure).
The purpose of bpyconfigure should be clearly stated (in the documentation and maybe also as a notice shown in the console right after starting bpyconfigure) since it would write into locations of the file system where pip install does not usually write.
bpyconfigure should figure out where is the Python interpreter, and where to write the extra data.
The extra data to write should be packaged as package_data, so that it can be found with pkg_resources.
Of course bpyconfigure --uninstall should be available as well!

Can I specify conflicting packages with Python's setuptools?

I wrote a plugin for pytest which adds command line option. Another plugin adds command line option with the same name. Thus, they shouldn't be both installed at the same time.
Is there anything I can configure with my setup.py script to prevent user from doing so?
There isn't a convenient option for setup to specify conflicts (more importantly, it looks like setuptools are not capable to detect conflicts reliably), but you can use access to installed packages (the solution based on pkg_resources) described in this answer to write your own code in setup.py script which would detect and handle conflicts. This is not perfect, but can be a workaround.

How to ditribute my Unix application?

I created a command-line python tool for Unix systems.
I want my script to be executed from anywhere just like any Unix command. One solution is to make my script executable and move it to /usr/bin.
But the script works with external files, and I guess moving all these files with my script in /usr/bin is a bad habit, as it will be hard to delete them one by one in the future.
Where should I put the directory of my application ? How to add the main script to the PATH, to execute it from anywhere ?
I would like then to create a package that could move my files in the right place, and delete them in the case the user wants to uninstall my application.
I don't know how to do this.
Thank you.
There are many way of distributing a Linux application.
It will depend on the distribution you are using, since they do not all use the same package manager. For example, you would create a .deb package for Debian, Ubuntu and there derivatives, an Arch package for Archlinux, etc...
You could then share the package with anyone to let them install your tool.
However, since your tool is in written in Python, you can also make a python package. You could then upload it to the Python Package Index to let anyone install it using python's pip package manager.
To create a python package, you will need to create a file called setup.py, and, from it, to call the setup method from the setuptool packages.
You will probably want to read the python documentation about writing such a script: https://setuptools.readthedocs.io/en/latest/setuptools.html
You may especially be interested by this sections:
Including Data Files
Automatic Script Creation
If you do things correctly, setuptools will take care of installing your script and its files somewhere in the PATH so it can be executed from the command line.
You should use setuptools to distribute your application, creating a setup.py file to configure its setup and installation.
Binaries can be delivered using the console_scripts option, while data files can be delivered using either package_data.

How does one package a python application that includes a gsettings schema with setuptools?

I'm trying to use setuptools to package a python application that relies on gsettings for storing and retrieving user's preferences. However I have not used said tool before and I am unsure about what to do with the setup.py script in order to instruct it to install and compile the schema. It seems that the data_files argument can be used to specify additional files that will be installed in a specified directory, but how do make sure that glib-compile-schemas gets executed?

Installing nosetests - permission denied

Trying to install nosetests as per the learnpythonthehardway tutorial, I'm having problems. Any clues on what I should try next?
$ easy_install nose
Searching for nose
Best match: nose 1.1.2
Processing nose-1.1.2-py2.6.egg
nose 1.1.2 is already the active version in easy-install.pth
Installing nosetests-2.6 script to /usr/local/bin
error: /usr/local/bin/nosetests-2.6: Permission denied`
One question about installing that I have: if I have something saved in a random location on my computer, can it be imported into a python script regardless of where it is? So if I execute runthis.py that's in a folder called "projects", and I have from setup tools import setup as the first line of the program, does setup tools have to be anywhere in particular (such as the "projects" folder) for python to find it?
Are you able to use sudo?
If so, simply use sudo easy_install nose to install as root.
If not, you'll need to install somewhere you can write to, not the default location which you don't have permission to modify. This can be done easily in the traditional way, or using virtualenv which can a bit trickier to get set up initially.
As for the second question, no, python will only find things that are in directories found in sys.path, which is set to the contents of the PYTHONPATH environment variable plus the installed python's own library directories by default.
It is often (highly!) advisable to set up your own "local" repository of packages, for whatever language system (be it Python or otherwise) that you are using. Leave the "system installed" packages, whatever they might be, completely alone ... in case some uber-important system tool (the package-manager, anyone?) might also be using them and might be dependent on them.
The means of doing this vary from language to language, but they'll be documented somewhere all the same. You might even find that the "distro" that you're using has already anticipated this requirement and has set-aside some agreed upon location, e.g. "/usr/local/..." just for your own personal use.

Categories

Resources