How to resolve conflicts between dependencies in Plone? - python

I am writing an add-on for Plone 5.1. I have added dependency to my add-on's setup.py install_requires parameter. I have also added my add-on (esperonus.vimeo) to Plone's buildout.cfg. However, upon running buildout, I get this error:
ryselis#ryselis-All-Series:~/Plone/zinstance$ bin/buildout -c develop.cfg
mr.developer: Queued 'esperonus.vimeo_plone' for checkout.
mr.developer: Filesystem package 'esperonus.vimeo_plone' doesn't need a checkout.
Develop: '/home/ryselis/Plone/zinstance/src/esperonus.vimeo_plone'
Updating _mr.developer.
Installing instance.
Version and requirements information containing certifi:
[versions] constraint on certifi: 2017.11.5
Requirement of tuspy==0.2.1: certifi==2017.7.27.1
Requirement of requests>=2.4.0: certifi>=2017.4.17
While:
Installing instance.
Error: The requirement ('certifi==2017.7.27.1') is not allowed by your [versions] constraint (2017.11.5)
It looks like VimeoPy requires different version of certifi than tuspy (I guess this is Plone's dependency?). Is there anything I could do to add VimeoPy to my add-on?

This usually means that you have pinned version in your buildout configuration which are di8ffer from what a packages want's to install. You can remove the pinnings from the buildout configuration accept you have a reason for it.
New buildout versions usually have an option called "update-versions-file" which points to the buildout config file with the list of versions. Buildout will add all picked versions, which where not pinned and add them for you, so that you can rebuild this configuration later with exact the same versions.
But these pinnings are save to remove, especially if you have packages requiring diffent versions.

Related

How can Python Poetry be forced to use a certain setuptools version?

I would like to use the Python library pyhash in my project. The dependencies are managed by Poetry. If I add pyhash as a dependency, I get a build error: error in pyhash setup command: use_2to3 is invalid.
This is a well-known bug due to setuptools > 58.0.0 not supporting use_2to3 anymore. In a non-Poetry setup, the fix is easy. Just downgrade setuptools to <= 58.0.0: pip3 install setuptools==58.0.0.
However, in a Poetry project, I could not make this work. I added setuptools=58.0.0 as a dependency, but when I install my project I still get the use_2to3 error. I assume that poetry still uses a setuptools>58.0.0.
How can I fix this?
I found a workaround for my problem. In the case of pyhash, the dependency on use_2to3 has already been removed in the master branch. This fix has unfortunately not been released yet. However, it is possible for pip and also for poetry to install directly from a github repository. Any ref can be specified, so branches, tags and also individual commits.
The workaround with poetry means you have to add the pyhash dependency with the git repository as source:
poetry add git+https://github.com/flier/pyfasthash.git#20a53f9bb7bf15f98e3e549f523b49e1e0f62e15
One can also specify master, but this is not advisable, as any branch is a moving target and will lead to non-reproducable releases.

Python build error - Could not find a version that satisfies the requirement wheel

I am trying to build python wheel following the instructions as described in the link below. I am doing this first time.
https://packaging.python.org/en/latest/tutorials/packaging-projects/
I set up the folder structure, files and all. I have added this in pyproject.toml file.
[build-system]
requires= ["setuptools>=57.4.0","wheel>=0.37.1"]
build-backend = "setuptools.build_meta"
I have installed setuptoos and wheel on my virtual environment.
When I tried to run the build command, I am getting an SSL warnings and below error.
Could not find a version that satisfies the requirement wheel>=0.37.1
Could not fetch from URL https://pypi.org/simple
Even though have installed setuptools and wheel on my virtual environment, I think it is hitting the pypi to find and download these packages.
I don't know how the build module finds the modules/packages in "requires". I am not finding a way to direct to use the already installed setuptools and wheel on my machine instead of fetching from pypi.
Even if it tries to doanload again, how can derect to use our artifactory instead of pypi.
Any help in this is greatly appreciated.
I tried all below with differenct combinations but did not work. Obviously I am missing something.
1.
I added a pip.ini in my virtual environment (Lib\site-packages\pip).
Added the index-url with our organization's artifactory url.
Added trusted-host
Also tried pip.config
I downloaded the wheels for setuptools and wheel.
Added another argument in pyproject.toml
[easy-install]
find-links = c:\wheels
Added the wheels directly in the src folder.
Thanks.

Pip wheel collects 2 versions of a package then pip install gets a conflict

We use a pipeline that first uses pip wheel to collect all the packages that are needed in the project and then it creates a docker image that calls to pip install on the collected wheels.
The issue I am encountering is that when calling pip wheel, pip is collecting 2 different versions of a package. This has started occurring once a new version of the package is available.
The project has a requirement for an internal library ecs-deployer==10.1.2 and that library has in turn a requirement in the form of: elb-listener>=3.2.1+25,<4
The relevant output of pip wheel with the verbose option says:
Collecting elb-listener>=3.2.1+25,<4
Created temporary directory: /tmp/pip-unpack-zr930807
File was already downloaded /home/user/path/dist/elb_listener-3.2.2+26-py3-none-any.whl
Added elb-listener>=3.2.1+25,<4 from https://internal-repository.com/path/elb_listener/3.2.2%2B26/elb_listener-3.2.2%2B26-py3-none-any.whl#md5=foo (from ecs-deployer==10.1.2->service==1.0.0) to build tracker '/tmp/pip-req-tracker-1tz9t5ls'
Removed elb-listener>=3.2.1+25,<4 from https://internal-repository.com/path/elb_listener/3.2.2%2B26/elb_listener-3.2.2%2B26-py3-none-any.whl#md5=blabla (from ecs-deployer==10.1.2->service==1.0.0) to build tracker '/tmp/pip-req-tracker-1tz9t5ls'
And also:
Collecting elb-listener>=3.2.1+25,<4
Created temporary directory: /tmp/pip-unpack-yfnxim_u
File was already downloaded /home/user/path/dist/elb_listener-3.2.3+27-py3-none-any.whl
Added elb-listener>=3.2.1+25,<4 from https://internal-repository.com/path/elb_listener/3.2.3%2B27/elb_listener-3.2.3%2B27-py3-none-any.whl#md5=bar (from ecs-deployer==10.1.2->service==1.0.0) to build tracker '/tmp/pip-req-tracker-1tz9t5ls'
Then when the pip install is called I get this:
ERROR: Cannot install elb-listener 3.2.2+26 (from /opt/elb_listener-3.2.2+26-py3-none-any.whl) and cad-aws-elb-listener-target-group-builder 3.2.3+27 (from /opt/elb_listener-3.2.3+27-py3-none-any.whl) because these package versions have conflicting dependencies.
The conflict is caused by:
The user requested elb-listener 3.2.2+26 (from /opt/elb_listener-3.2.2+26-py3-none-any.whl)
The user requested elb-listener 3.2.3+27 (from /opt/elb_listener-3.2.3+27-py3-none-any.whl)
We use pip 20.2.3 with the option --use-feature=2020-resolver
Is it normal that pip wheel collects several versions of the same package?
If so, can I indicate in any way to either pip wheel to only collect one of the versions or to pip install to only use the latest version?
If not, is there any way to solve this problem? I guess changing the requirement to elb-listener>=3.2.1+27,<4 would solve it, but we don't have direct access to that library and it would take a while for other team to change it.
As per #sinoroc comment, upgrading the python to 3.10 and pip version to 21.2.4 solved this particular issue.
As far as I understood, "local version identifiers" such as 3.2.1+25 are far from usual, apparently they are not meant to be used anywhere public (like PyPI), and that might be the reason for all the trouble here. I am really not sure how well they are supported by Python packaging tools and maybe they confuse the dependency resolution.
Local version identifiers SHOULD NOT be used when publishing upstream projects to a public index server, but MAY be used to identify private builds created directly from the project source. Local version identifiers SHOULD be used by downstream projects when releasing a version that is API compatible with the version of the upstream project identified by the public version identifier, but contains additional changes (such as bug fixes). As the Python Package Index is intended solely for indexing and hosting upstream projects, it MUST NOT allow the use of local version identifiers.
-- "Local version identifiers" section of _PEP 440

How does pip wheel resolves transitive dependencies?

When I run pip wheel sentry-sdk it downloads the following wheel files:
certifi-2020.6.20-py2.py3-none-any.whl
sentry_sdk-0.18.0-py2.py3-none-any.whl
urllib3-1.25.10-py2.py3-none-any.whl
Where sentry_sdk-0.18.0-py2.py3-none-any.whl is the lib I actually want to use and the other ones are transitive dependencies required by this lib to work. I understand that the file is coming from PyPI however what I do not understand is how pip wheel is choosing the version of the aforementioned transitive dependencies.
More Context
My underlying problem is that the resolved version of the urllib3 clashes with another one already added to the pex file of the project I'm working on (I'm using Bazel to generate the pex) I'm considering downgrading the version of urllib3 to match my project's existing one. Looking at the setup.py from the sentry-sdk in GitHub it says it only requires it to be greater than 1.10.0 ("urllib3>=1.10.0") so I think the downgrade would work but I wanted to be sure to avoid production crashes.
Thanks
the current version of pip (2020-10-13) does not have a dependency resolver, it picks the first constraint greedily (so if urllib3 is encountered unbounded first, it will pick the latest version -- even if a later package has a more restrictive requirement)
this is being changed in pip, you can enable the resolver as an opt-in in pip>=20.2 and it will become the default in the future (later this year)

Installing via `setup.py develop` fails - pip works

My python package footools needs html5lib via install_requires in setup.py.
setup.py develop fails
Installing via setup.py develop fails:
cd src/footools/
python setup.py develop
Processing dependencies for footools==2016.205
Searching for html5lib==0.9999999
Reading https://source.example.com/pypi/simple/html5lib/
Download error on https://source.example.com/pypi/simple/html5lib/:
[Errno 185090050] _ssl.c:354: error:0B084002:x509
certificate routines:X509_load_cert_crl_file:system lib --
Some packages may not be found!
Couldn't find index page for 'html5lib' (maybe misspelled?)
pip works
But direct download works:
bar#workdevel123:~/src/footools> pip install html5lib==0.9999999
/home/bar/lib/python2.7/site-packages/pip/_vendor/requests/packages/urllib3/util/ssl_.py:79:
InsecurePlatformWarning: A true SSLContext object is not available.
This prevents urllib3 from configuring SSL appropriately
and may cause certain SSL connections to fail.
For more information, see
https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning.
InsecurePlatformWarning
Collecting html5lib==0.9999999
/home/bar/lib/python2.7/site-packages/pip/_vendor/requests/packages/urllib3/util/ssl_.py:79:
InsecurePlatformWarning: A true SSLContext object is not available.
This prevents urllib3 from configuring SSL appropriately and
may cause certain SSL connections to fail.
For more information,
see https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning.
InsecurePlatformWarning
Downloading https://source.example.com/pypi/packages/html5lib-0.9999999.tar.gz
Requirement already satisfied (use --upgrade to upgrade):
six in /usr/lib/python2.7/site-packages (from html5lib==0.9999999)
Installing collected packages: html5lib
Running setup.py install for html5lib
Successfully installed html5lib-0.9999999
Questions
What is the difference between these two methods?
Why are they different?
What is the correct way to install a dependency in python?
setup.py
The setup.py is not special:
import setuptools
setuptools.setup(
name='foo',
version='2016.210',
long_description=open('README.txt').read(),
packages=setuptools.find_packages(),
install_requires=[
# about twenty packages before this line
'html5lib==0.9999999'
],
include_package_data=True,
entry_points={
'console_scripts': [
'foo=foo.utils.bar:main',
],
},
)
python setup.py develop, or setuptools in general uses easy_install to satisfy dependencies which in turn uses urllib2 whereas pip uses requests. See here for easy_install vs pip.
pip is more modern and among other things has capability to uninstall packages and complies with PEP 438 -- Transitioning to release-file hosting on PyPI. You can achieve the same thing as python setup.py develop with pip install -e src/footools/, note if the project path is in the current directory use, ./footools.
The requests package bundles CA certs in the package itself, python -c 'import pip;print(pip.download.requests.certs.where())'.
setuptools uses system installed CA certs python -c 'from setuptools import ssl_support;print(ssl_support.cert_paths)'.
You have to update system installed CA certs using tools like update-ca-certificates for Ubuntu to either update CA certs automatically or download from https://curl.haxx.se/docs/caextract.html and install into one of the paths shown by setuptools or set setuptools.ssl_support.cert_paths to an empty sequence like [] and do pip install certifi.
Calling setuptools.ssl_support.find_ca_bundle() will reveal the location of CA certs.
setuptools is a collection of enhancements to the Python distutils (for Python 2.6 and up) that allow developers to more easily build and distribute Python packages, especially ones that have dependencies on other packages.
So, among other stuff, you can create packages that can be upload to Pypi, and later installed using pip (therefore distibuting your module).
That said, they actually should not be that different in the installation part. You are running the develop mode, so maybe you have to fiddle a bit with the directories or fix the authorization error.
In the Development Mode the project is deployed into a staging area (in some way similar to the process of a virtual environment)
deployment is done in such a way that changes to the project source are immediately available in the staging area(s), without needing to run a build or install step after each change.
Meaning also everything will be available for that python interpreter. It can be later unstaged.
I noticed that html5lib is being fetched from different places: /pypi/simple/in one case and /pypi/packages/ in the other.
dependency_links
A list of strings naming URLs to be searched when satisfying dependencies. These links will be used if needed to install packages specified by setup_requires or tests_require.
Back to the problem I think it is most probably the ssl issue, since in pip it handled graciously (i.e., nice warning and there is some kind of workaround), but the same does not happen with setuptools. If there is an error in the request that is not handled then Couldn't find index page for 'html5lib' could be because of that.
What is the difference between these two methods?
Nothing terribly important to you as a user, aside from their different user interfaces. They are two stops on the scenic historical train ride of Python package management. There were others along the way.
Why are they different?
Back in the day, Python didn't ship with a package management system. Third party solutions filled the void. They were designed by different people at different moments in time. If you look at other programming languages, you sometimes see similar stories; sometimes you see happier stories; sometimes more tragic.
What is the correct way to install a dependency in python?
Both of these methods are technically correct. Pip is the more modern method, and in my experience it is both more popular and handier to work with. As of Python 3.4 and up, Pip has been included in the CPython distribution and is officially 'preferred'. So you can see which way the wind is blowing.

Categories