Unable to install locally built python package - python

I recently noticed that I am unable to install my own Python packages. I was getting an error that indicated that a package containing Python modules was invalid. So, I updated my setup.py and removed some elements, this is what I have now:
from setuptools import setup
setup(
name='project',
version='0.3.0',
packages=['project'],
license='GPL',
#zip_safe=False,
#include_package_data=True,
#package_data = { 'package': [ 'README.txt', '*.py' ] },
install_requires=[
'PyYAML >= 3.11',
'logger >= 0.2.0',
],
entry_points={
'console_scripts': ['project = project:main']
},
)
I removed some elements and called the project project. Essentially, within project, I had a package, libraries, with some Python modules. Prior to removing these lines:
#zip_safe=False,
#include_package_data=True,
#package_data = { 'package': [ 'README.txt', '*.py' ] },
... it was not working recently.
Oddly enough though, this setup.py was working as far as I could tell up until a month ago. That said, after commenting those items out and running python setup.py build, I no longer get the error about the package being invalid, but at the same token, I see that nothing gets installed when running pip install dist/project-0.0.1.tar.gz. Inside the file, built by python setup.py sdist, I do see all the files that I would expect to see. They just don't get installed, so I'm effectively missing all of the packages underneath the root folder (which is everything except init).
What am I missing here?

EDIT:
The solution was:
packages=find_packages(),
The hackish solution for me was to do this:
packages=['project', 'project/libraries', 'project/system', 'project/services'],
For whatever reason, packages was no longer working recursively.
As soon as I did that, voila, it worked. I'll probably circle back to this later as I'm curious what changed.

Related

How to create a .exe similar to pip.exe, jupyter.exe, etc. from C:\Python37\Scripts?

In order to make pip or jupyter available from command-line on Windows no matter the current working directory with just pip ... or jupyter ..., Python on Windows seems to use this method:
put C:\Python37\Scripts in the PATH
create a small 100KB .exe file C:\Python37\Scripts\pip.exe or jupyter.exe that probably does not much more than calling a Python script with the interpreter (I guess?)
Then doing pip ... or jupyter ... in command-line works, no matter the current directory.
Question: how can I create a similar 100KB mycommand.exe that I could put in a directory which is in the PATH, so that I could do mycommand from anywhere in command-line?
Note: I'm not speaking about pyinstaller, cxfreeze, etc. (that I already know and have used before); I don't think these C:\Python37\Scripts\ exe files use this.
Assuming you are using setuptools to package this application, you need to create a console_scripts entry point as documented here:
https://packaging.python.org/guides/distributing-packages-using-setuptools/#console-scripts
For a single top-level module it could look like the following:
setup.py
#!/usr/bin/env python3
import setuptools
setuptools.setup(
py_modules=['my_top_level_module'],
entry_points={
'console_scripts': [
'mycommand = my_top_level_module:my_main_function',
],
},
# ...
name='MyProject',
version='1.0.0',
)
my_top_level_module.py
#!/usr/bin/env python3
def my_main_function():
print("Hi!")
if __name__ == '__main__':
my_main_function()
And then install it with a command such as:
path/to/pythonX.Y -m pip install path/to/MyProject

Custom logic in setup.py to change environment header

I have a Python package that I'm distributing on PyPI. I create a script called run_program1 that launches a GUI on the command line.
A snippet of my setup.py file:
setup(
name='my_package',
...
entry_points={
'gui_scripts': [
'run_program1 = program1:start_func',
]
}
)
Unfortunately, the run_program1 executable fails to when installed with Anaconda Python, with an error like this:
This program needs access to the screen. Please run with a Framework build of python, and only when you are logged in on the main display of your Mac.
This issue turns out to be a fundamental issue between Anaconda and setuptools:
https://groups.google.com/a/continuum.io/forum/#!topic/anaconda/9kQreoBIj3A
I'm trying to create an ugly hack to change the environment in the executable that pip creates -- run_program1 -- from #!/Users/***/anaconda2/bin/python to #/usr/bin/env pythonw. I can do this manually after installing on my machine by opening ~/anaconda2/bin/run_program1 and simply replacing the first line. With that edit, the executable works as expected. However, I need to create a hack that will allow me to do this for all users who use pip to install my_package.
I am using this approach to insert custom logic into my setup.py file: https://blog.niteoweb.com/setuptools-run-custom-code-in-setup-py/
class CustomInstallCommand(install):
"""Customized setuptools install command - prints a friendly greeting."""
def run(self):
print "Hello, developer, how are you? :)"
install.run(self)
setup(
...
cmdclass={
'install': CustomInstallCommand,
}, ...)
What I can't figure out is, what should I put into the custom class to change the header in the run_program1 executable? Any ideas of how to approach this?

Using Esky to Freeze/Package a Cocoa PyObjC Python Application

So I'm trying to put together an auto-update functionality for my standalone OSX Python application, that's built on PyObjC. It works great simply packaging it via py2app, but I'm attemping to freeze it with Esky as part of an effort to implement the update feature.
As far as I can tell it's my setup.py formatting for Esky. I'm not sure exactly how to tell Esky to pass on the name of my .Xib file to py2app. Here's what my direct py2app setup.py looks like, successfully including the required .Xib file for the GUI:
setup.py for Py2app
from setuptools import setup
APP = ['MyApp.py']
DATA_FILES = ['MyApp.xib']
OPTIONS = {'argv_emulation': False, 'packages' : ['PIL']}
setup(
app=APP,
data_files=DATA_FILES,
options={'py2app': OPTIONS},
setup_requires=['py2app'],
iconfile="MyApp.icns"
)
Looking around at other people's posts, it looks like you can pass settings to py2app via the slightly differently structured Esky setup.py, but I can't for the life of me figure out the exact structure of the arguments to pass the .Xib file to py2app, from Esky.
setup.py for Esky
from esky import bdist_esky
from distutils.core import setup
setup(name="MyApp",
version="1.3.3",
iconfile="MyApp.icns",
data_files=['MyApp.xib'],
scripts=["MyApp.py","midheaven.py"],
options={"bdist_esky":{
"includes":["PIL"],
"excludes":['pydoc'],
"freezer_module": "py2app",
"freezer_options": {
"plist": {
'argv_emulation': False,
'packages': ['PIL'],
},
"data_files": ['MyApp.xib'],
},
},
},
)
Everything packages without an error, but of course if I try to run the Esky freeze of the app it crashes right away. I'm positive it's because it's not attaching the .Xib GUI properly. Anyone have experience with this, or ideas on how this should actually be formatted? Would absolutely love to figure this out and have it up on here for posterity.
You are correct esky does something different than what you might expect. Looking in the demo/tutorial folder is what got me on the right path.
setup(name="MyApp",
data_files=[('', ['MyApp.xib']),
('files', ['file1', 'file2']),
('img', glob(r'.\img\*.*'))
]
...
So you have a whole bunch of tuples, where the first entry is the path in your package to include the files and the second is an iterable of files to put there
You can remove the second instance of data_files that you have in the options dict.
Update
Try
from esky.bdist_esky import Executable
executables = [Executable('example_gui.py', icon='myico.ico', gui_only=True,)]
setup(
scripts = executables
...

Building and distributing python moduel using rpm

I am trying to build and distribute rpm package of python module for centos. I have followed following steps
created virtualenv and installed requires
in module added setup.py with install_requires.
then using python2.7 from virtualenv build package
../env/bin/python2.7 setup.py bdist_rpm
Now I got src, no-arch and tar-gz files in 'dist' folder.
foo-0.1-1.noarch.rpm, foo-0.1-1.src.rpm, foo-0.1.tar.gz
I tried to install package src-rpm using 'sudo yum install foo-0.1-1.src.rpm',
got error something like wrong architecture
Then I tried to install package no-arch, 'sudo yum install foo-0.1-1.noarch.rpm' it works smoothly.
But after running script, it gave some import error. here I expect to download that module automatically.
The last thing is I am using some third party library which is not on pip.
So I want to whole setup using virtualenv with required modules. So after installing rpm, user can run script directly instead of installing third party libs separately and explicitly.
Some above steps may sounds wrong, as I am new to this stuff.
Following is code in setup.py
from setuptools import setup, find_packages
setup(
name = "foo",
version = "0.1",
packages = find_packages(),
scripts = ['foo/bar.py', ],
# Project uses reStructuredText, so ensure that the docutils get
# installed or upgraded on the target machine
install_requires = ['PyYAML', 'pyOpenSSL', 'pycrypto', 'privatelib1,'privatelib2', 'zope.interface'],
package_data = {
# If any package contains *.txt or *.rst files, include them:
'': ['*.txt', '*.rst'],
# And include any *.msg files found in the 'billing' package, too:
'foo': ['*.msg'],
},
# metadata for upload to PyPI
author = "foo bar",
description = "foo bar",
license = "",
keywords = "foo bar",
# could also include long_description, download_url, classifiers, etc.
)
Also I am using shebang in script as,
#!/usr/bin/env python2.7
Note:
I have multiple python setups. 2.6 and 2.7
By default 'python' commands gives 2.6
while command 'python2.7' gives python2.7
output of `'rpm -qp foo-0.1-1.noarch.rpm --requires' =>
`/usr/bin/python
python(abi) = 2.6
rpmlib(CompressedFileNames) <= 3.0.4-1
rpmlib(PayloadFilesHavePrefix) <= 4.0-1
When i install pakcage. script's shebang line (which is now '/usr/bin/bar.py') is getting changed to /usr/bin/python' But I exclusively want to run script on python2.7.
Thanks in advance

Changing console_script entry point interpreter for packaging

I'm packaging some python packages using a well known third party packaging system, and I'm encountering an issue with the way entry points are created.
When I install an entry point on my machine, the entry point will contain a shebang pointed at whatever python interpreter, like so:
in /home/me/development/test/setup.py
from setuptools import setup
setup(
entry_points={
"console_scripts": [
'some-entry-point = test:main',
]
}
)
in /home/me/.virtualenvs/test/bin/some-entry-point:
#!/home/me/.virtualenvs/test/bin/python
# EASY-INSTALL-ENTRY-SCRIPT: 'test==1.0.0','console_scripts','some-entry-point'
__requires__ = 'test==1.0.0'
import sys
from pkg_resources import load_entry_point
sys.exit(
load_entry_point('test==1.0.0', 'console_scripts', 'some-entry-point')()
)
As you can see, the entry point boilerplate contains a hard-coded path to the python interpreter that's in the virtual environment that I'm using to create my third party package.
Installing this entry point using my third-party packaging system results in the entry point being installed on the machine. However, with this hard-coded reference to a python interpreter which doesn't exist on the target machine, the user must run python /path/to/some-entry-point.
The shebang makes this pretty unportable. (which isn't a design goal of virtualenv for sure; but I just need to MAKE it a little more portable here.)
I'd rather not resort to crazed find/xargs/sed commands. (Although that's my fallback.)
Is there some way that I can change the interpreter path after the shebang using setuptools flags or configs?
You can customize the console_scripts' shebang line by setting 'sys.executable' (learned this from a debian bug report). That is to say...
sys.executable = '/bin/custom_python'
setup(
entry_points={
'console_scripts': [
... etc...
]
}
)
Better though would be to include the 'execute' argument when building...
setup(
entry_points={
'console_scripts': [
... etc...
]
},
options={
'build_scripts': {
'executable': '/bin/custom_python',
},
}
)
For future reference for someone who wants to do this at runtime without modifying the setup.py, it's possible to pass the interpreter path to setup.py build via pip with:
$ ./venv/bin/pip install --global-option=build \
--global-option='--executable=/bin/custom_python' .
...
$ head -1 ./venv/bin/some-entry-point
#!/bin/custom_python
Simply change the shebang of your setup.py to match the python you want your entry points to use:
#!/bin/custom_python
(I tried #damian answer but not working for me, maybe the setuptools version on Debian Jessie is too old)

Categories