Mitmproxy and installation with yocto recipes - python

I want to install the third-party tool called Mitmproxy in an embedded Linux environment with a low footprint, e.g. a Raspberry PI.
Rather than install using a standard Raspbian OS, I want to customize the install with Yocto and define the packages. This involves writing recipes to customize the packages that are installed. A good example at a high leve is described here.
Unfortunately this involves appending various Python3 packages as well pip-mitmproxy as well as all the dependencies of pip-mitmproxy in the local.conf file, e.g.
IMAGE_INSTALL_append = " python3"
IMAGE_INSTALL_append = " pip-mitmproxy"
Different recipe files need to be added in this case.
The challenge that I've found is getting the right versions of all the dependencies. I looked import pkg_resources but it doesn't seem to give me everything. Is there another recommended approach perhaps by looking at the source code.

I created Python venv on normal Linux Mint so pip freeze shows me empty list
After installing mitmproxy I run again pip freeze and it shows me
blinker==1.4
Brotli==1.0.7
certifi==2020.6.20
cffi==1.14.1
click==7.1.2
cryptography==2.9.2
Flask==1.1.2
h11==0.9.0
h2==3.2.0
hpack==3.0.0
hyperframe==5.2.0
itsdangerous==1.1.0
Jinja2==2.11.2
kaitaistruct==0.8
ldap3==2.7
MarkupSafe==1.1.1
mitmproxy==5.2
passlib==1.7.2
protobuf==3.11.3
publicsuffix2==2.20191221
pyasn1==0.4.8
pycparser==2.20
pyOpenSSL==19.1.0
pyparsing==2.4.7
pyperclip==1.8.0
ruamel.yaml==0.16.10
ruamel.yaml.clib==0.2.0
six==1.15.0
sortedcontainers==2.1.0
tornado==6.0.4
urwid==2.0.1
Werkzeug==1.0.1
wsproto==0.15.0
zstandard==0.13.0
But it is hard to say if it needs some C/C++ libraries for this.
For example pyOpenSSL will need library OpenSSL but I can't find it in setup.py or setup.cfg. There is only information about openssl-devel which means it may need openssl.
It seems the only way is to install and run it to see error messages :)

Related

Problem when download Python package and then install from .whl files

I want to download Python package pipy.org and move them to another machine and finally install that packages with downloaded .whl files in that machine
This is requirements.txt file:
amqp==5.1.1
anytree==2.8.0
asgiref==3.5.2
async-timeout==4.0.2
attrs==22.1.0
autobahn==22.7.1
Automat==22.10.0
beautifulsoup4==4.11.1
billiard==3.6.4.0
celery==5.2.7
certifi==2022.9.24
cffi==1.15.1
channels==4.0.0
channels-redis==4.0.0
charset-normalizer==2.1.1
click==8.1.3
click-didyoumean==0.3.0
click-plugins==1.1.1
click-repl==0.2.0
constantly==15.1.0
coreapi==2.3.3
coreschema==0.0.4
cryptography==38.0.3
daphne==4.0.0
Deprecated==1.2.13
Django==4.0.8
django-celery-beat==2.3.0
django-celery-results==2.4.0
django-filter==22.1
django-jalali==6.0.0
django-timezone-field==5.0
djangorestframework==3.14.0
djangorestframework-simplejwt==5.2.2
drf-yasg==1.21.4
et-xmlfile==1.1.0
gunicorn==20.1.0
h2==4.1.0
hpack==4.0.0
hyperframe==6.0.1
hyperlink==21.0.0
idna==3.4
incremental==22.10.0
inflection==0.5.1
itypes==1.2.0
jdatetime==4.1.0
Jinja2==3.1.2
kombu==5.2.4
lxml==4.9.1
MarkupSafe==2.1.1
msgpack==1.0.4
multitasking==0.0.11
numpy==1.23.3
openpyxl==3.0.10
packaging==21.3
pandas==1.5.0
pandas-datareader==0.10.0
Pillow==9.2.0
priority==1.3.0
prompt-toolkit==3.0.31
psutil==5.9.2
psycopg2==2.9.4
pyasn1==0.4.8
pyasn1-modules==0.2.8
pycparser==2.21
PyJWT==2.6.0
pyOpenSSL==22.1.0
pyparsing==3.0.9
python-crontab==2.6.0
python-dateutil==2.8.2
python-dotenv==0.21.0
pytz==2022.4
redis==4.3.4
requests==2.28.1
ruamel.yaml==0.17.21
ruamel.yaml.clib==0.2.7
service-identity==21.1.0
simplejson==3.17.6
six==1.16.0
soupsieve==2.3.2.post1
sqlparse==0.4.3
Twisted==22.10.0
txaio==22.2.1
typing_extensions==4.4.0
tzdata==2022.5
Unidecode==1.3.6
uritemplate==4.1.1
urllib3==1.26.12
vine==5.0.0
wcwidth==0.2.5
wrapt==1.14.1
yfinance==0.1.74
zope.interface==5.5.1
I did download packages with:
pip download -r requirements.txt
This is list of downloaded pacakges in ~/LocalPythonPackage directory:
→ ls
amqp-5.1.1-py3-none-any.whl lxml-4.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl
anytree-2.8.0-py2.py3-none-any.whl MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
asgiref-3.5.2-py3-none-any.whl msgpack-1.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
async_timeout-4.0.2-py3-none-any.whl multitasking-0.0.11-py3-none-any.whl
attrs-22.1.0-py2.py3-none-any.whl numpy-1.23.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
autobahn-22.7.1.tar.gz openpyxl-3.0.10-py2.py3-none-any.whl
Automat-22.10.0-py2.py3-none-any.whl packaging-21.3-py3-none-any.whl
beautifulsoup4-4.11.1-py3-none-any.whl pandas-1.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
billiard-3.6.4.0-py3-none-any.whl pandas_datareader-0.10.0-py3-none-any.whl
celery-5.2.7-py3-none-any.whl Pillow-9.2.0-cp310-cp310-manylinux_2_28_x86_64.whl
certifi-2022.9.24-py3-none-any.whl priority-1.3.0-py2.py3-none-any.whl
cffi-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl prompt_toolkit-3.0.31-py3-none-any.whl
channels-4.0.0-py3-none-any.whl psutil-5.9.2-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
channels_redis-4.0.0-py3-none-any.whl psycopg2-2.9.4.tar.gz
charset_normalizer-2.1.1-py3-none-any.whl pyasn1-0.4.8-py2.py3-none-any.whl
click-8.1.3-py3-none-any.whl pyasn1_modules-0.2.8-py2.py3-none-any.whl
click_didyoumean-0.3.0-py3-none-any.whl pycparser-2.21-py2.py3-none-any.whl
click_plugins-1.1.1-py2.py3-none-any.whl PyJWT-2.6.0-py3-none-any.whl
click_repl-0.2.0-py3-none-any.whl pyOpenSSL-22.1.0-py3-none-any.whl
constantly-15.1.0-py2.py3-none-any.whl pyparsing-3.0.9-py3-none-any.whl
coreapi-2.3.3-py2.py3-none-any.whl python-crontab-2.6.0.tar.gz
coreschema-0.0.4.tar.gz python_dateutil-2.8.2-py2.py3-none-any.whl
cryptography-38.0.3-cp36-abi3-manylinux_2_28_x86_64.whl python_dotenv-0.21.0-py3-none-any.whl
daphne-4.0.0-py3-none-any.whl pytz-2022.4-py2.py3-none-any.whl
Deprecated-1.2.13-py2.py3-none-any.whl redis-4.3.4-py3-none-any.whl
Django-4.0.8-py3-none-any.whl requests-2.28.1-py3-none-any.whl
django_celery_beat-2.3.0-py3-none-any.whl ruamel.yaml-0.17.21-py3-none-any.whl
django_celery_results-2.4.0-py3-none-any.whl ruamel.yaml.clib-0.2.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl
django_filter-22.1-py3-none-any.whl service_identity-21.1.0-py2.py3-none-any.whl
django_jalali-6.0.0-py3-none-any.whl setuptools-65.6.3-py3-none-any.whl
djangorestframework-3.14.0-py3-none-any.whl simplejson-3.17.6-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl
djangorestframework_simplejwt-5.2.2-py3-none-any.whl six-1.16.0-py2.py3-none-any.whl
django_timezone_field-5.0-py3-none-any.whl soupsieve-2.3.2.post1-py3-none-any.whl
drf_yasg-1.21.4-py3-none-any.whl sqlparse-0.4.3-py3-none-any.whl
et_xmlfile-1.1.0-py3-none-any.whl Twisted-22.10.0-py3-none-any.whl
gunicorn-20.1.0-py3-none-any.whl txaio-22.2.1-py2.py3-none-any.whl
h2-4.1.0-py3-none-any.whl typing_extensions-4.4.0-py3-none-any.whl
hpack-4.0.0-py3-none-any.whl tzdata-2022.5-py2.py3-none-any.whl
hyperframe-6.0.1-py3-none-any.whl Unidecode-1.3.6-py3-none-any.whl
hyperlink-21.0.0-py2.py3-none-any.whl uritemplate-4.1.1-py2.py3-none-any.whl
idna-3.4-py3-none-any.whl urllib3-1.26.12-py2.py3-none-any.whl
incremental-22.10.0-py2.py3-none-any.whl vine-5.0.0-py2.py3-none-any.whl
inflection-0.5.1-py2.py3-none-any.whl wcwidth-0.2.5-py2.py3-none-any.whl
itypes-1.2.0-py2.py3-none-any.whl wrapt-1.14.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
jdatetime-4.1.0-py3-none-any.whl yfinance-0.1.74-py2.py3-none-any.whl
Jinja2-3.1.2-py3-none-any.whl zope.interface-5.5.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl
and after copy all `.whl files to traget computer, I did run this code:
pip install --no-index --find-links ~/LocalPythonPackage -r requirements.txt
But I got this error:
ERROR: Could not find a version that satisfies the requirement MarkupSafe==2.1.1 (from versions: none)
ERROR: No matching distribution found for MarkupSafe==2.1.1
I use python3.11 and Ubuntu 20.04.5 LTS in both computers. I think that, this problem is for dependencies or different in OS.
Can you help me to solve this problem?
TL;DR
You need to use --platform and --only-binary=:all: (sometimes need to specify --abi and --python-version as well) flags to download wheels that is compatible with your installation target machine.
pip3 download --only-binary=:all: --platform manylinux2014_aarch64 -r requirements.txt
(Important: if your target machine is not aarch64 architecture, replace the manylinux2014_aarch64 with the correct platform tag)
Some wheels are platform dependent
The error happens because pip can't install the MarkupSafe wheel you provided in the directory, therefore it says it can't find a valid distribution.
Since you mentioned the two computers are same in Python version and OS distribution, I'm gonna guess that the two computers you use are different in architectures. (ex. the target computer is aarch64)
The following explanation and solution are based on this guess.
The Python Packaging User Guide states a Python wheel could be either a "pure Python wheel" or a "platform wheel". When a Python package contains extensions that requires compilation, the produced wheel will be platform-specific and cannot be installed on other non-compatible platforms.
In your case, the wheel MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl is a platform wheel built for Python 3.10 runtime, manylinux2014 and x86_64 architecture machines.
The wheel filename is defined in PEP 491, formatted as {distribution}-{version}(-{build tag})?-{python tag}-{abi tag}-{platform tag}.whl.
The last three components of the filename before the extension are called “compatibility tags.” The compatibility tags express the package’s basic interpreter requirements and are detailed in PEP 425.
Hence by the name of a wheel (to be precise, the last three component in the filename) you can find out if it is a pure Python wheel or a platform wheel.
Newer Python versions (except different major versions) can still install platform wheels built for older minor versions
Another answer in the post says you need to install a wheel that has the same miner Python version in the Python tag, but that is usually not true.
According to PEP 425:
The tags are used by installers to decide which built distribution (if any) to download from a list of potential built distributions. The installer maintains a list of (pyver, abi, arch) tuples that it will support. If the built distribution’s tag is in the list, then it can be installed.
That means pip is responsible for make decision whether a distribution could be installed on the current system.
Let's take a look at the source code of pip. The CandidateEvaluator evaluate possible distribution candidates when trying to install a package.
If you trace the code all the way to _py_interpreter_range, you'll find out a list of older Python minor versions are appended to the supported tags in descending order.
For Python 3.11, Python 3.10, Python 3.9, Python 3.8... are all considered supported tags for pip.
Solution
pip download with the --platform, --python-version, --implementation, and --abi options provides the ability to fetch dependencies for an interpreter and system other than the ones that pip is running on. --only-binary=:all: or --no-deps is required when using any of these options.
from https://pip.pypa.io/en/stable/cli/pip_download/.
To download MarkupSafe for manylinux2014_aarch64:
$ pip3 download --only-binary=:all: --platform manylinux2014_aarch64 MarkupSafe
And change your package preparation command to:
pip3 download --only-binary=:all: --platform manylinux2014_aarch64 -r requirements.txt
You use Python 3.11 but wheels you show above are for Python 3.10. You should download packages on a host with the same processor architecture (x64 seems to be your case), the same OS and version (Ubuntu 20) and the same minor Python version (Python 3.11.*, that is any Python 3.11 does but not Python 3.10) as the target host.
Or use Python 3.10 on the offline host.

Is there an alternative way to install dependencies for an Alexa Skill (requirements.txt is troublesome)?

I'm trying to develop an Alexa Skill which uses MechanicalSoup to scrape some data from a web search. My code works but I'm unable to install MechanicalSoup via the 'requirements.txt' file. I've even added all of MechanicalSoup's dependencies, like so:
boto3==1.9.216
ask-sdk-core==1.11.0
requests==2.25.1
beautifulsoup4==4.9.3
lxml==4.9.0
soupsieve==2.3.2.post1
urllib3==1.26.9
certifi==2022.5.18.1
chardet==4.0.0
idna==2.10
mechanicalsoup==1.2.0
but I'm having no luck.
My events log looks like this:
Do you have any idea what I can do to get this to work? Is there a way to install directly with pip install, if so, how?
Thanks
Maybe:
your requirements.txt doesn't work? you could try to pip install -r requirements.txt on your computer, to see if the requirements actually work
Your build server builds with a different version of python then your computer? for example, you could have python 3.10, while alexa has python 2.7

How to force pip to get a wheel package (even for package dependencies)?

I'm trying to build a multistage docker image with some python packages. For some reason, pip wheel command still downloads source files .tar.gz for few packages even though .whl files exist in Pypi. For example: it does it for pandas, numpy.
Here is my requirements.txt:
# REST client
requests
# ETL
pandas
# SFTP
pysftp
paramiko
# LDAP
ldap3
# SMB
pysmb
First stage of the Dockerfile:
ARG IMAGE_TAG=3.7-alpine
FROM python:${IMAGE_TAG} as python-base
COPY ./requirements.txt /requirements.txt
RUN mkdir /wheels && \
apk add build-base openssl-dev pkgconfig libffi-dev
RUN pip wheel --wheel-dir=/wheels --requirement /requirements.txt
ENTRYPOINT tail -f /dev/null
Output below shows that it is downloading source package for Pandas but it got a wheel for Requests package. Also, surprisingly it takes a lot of time (I really mean a lot of time) to download and build these packages !!
Step 5/11 : RUN pip wheel --wheel-dir=/wheels --requirement /requirements.txt
---> Running in d7bd8b3bd471
Collecting requests (from -r /requirements.txt (line 4))
Downloading https://files.pythonhosted.org/packages/51/bd/23c926cd341ea6b7dd0b2a00aba99ae0f828be89d72b2190f27c11d4b7fb/requests-2.22.0-py2.py3-none-any.whl (57kB)
Saved /wheels/requests-2.22.0-py2.py3-none-any.whl
Collecting pandas (from -r /requirements.txt (line 7))
Downloading https://files.pythonhosted.org/packages/0b/1f/8fca0e1b66a632b62cc1ae38e197befe48c5cee78f895edf4bf8d340454d/pandas-0.25.0.tar.gz (12.6MB)
I would like to know how I can force it get a wheel file for all the required packages and also for the dependencies listed in these packages. I observed that some dependencies get a wheel file but others get the source packages.
NOTE: code above is a combination of multiple online sources.
Any help to make this build process easier is greatly appreciated.
Thanks in Advance.
You are using Alpine Linux. This one is somewhat unique as it uses musl as the underlying libc implementation, as opposed to the most other Linux distros which use glibc.
If a Python project implements C extensions (this is what e.g. numpy or pandas do), it has two options: either
offer a source dist (.tar.gz, .tar.bz2 or .zip) so that the C extensions are compiled using the C compiler/library found on the target system, or
offer a wheel that contains compiled C extensions. If the extensions are compiled against glibc, they will be unusable on systems using musl, and AFAIK vice versa too.
Now, Python defines the manylinux1 platform tag which is specified in PEP 513 and updated in PEP 571. Basically, the name says it all - wheels with compiled C extensions should be built against glibc and thus will work on many distros (that use glibc), but not on some (Alpine being one of them).
For you, it means that you have two possibilities: either build packages from source dists (this is what pip already does), or install the prebuilt packages via Alpine's package manager. E.g. for py3-pandas it would mean doing:
# echo "#edge http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories
# apk update
# apk add py3-pandas#edge
However, I don't see a big issue with building packages from source. When done right, you capture it in a separate layer placed as high as possible in the image, so it is cached and not rebuilt each time.
You might ask, why there's no platform tag analogous to manylinux1, but for musl-based distros? Because no one has written a PEP similar to PEP 513 that defines a musllinux platform tag yet. If you are interested in the current state of it, take a look at the issue #37.
Update
PEP 656 That defines a musllinux platform tag is now accepted, so it (hopefully) won't last long until prebuilt wheels for Alpine start to ship. You can track the current implementation state in auditwheel#305.
For Python 3, your packages will be installed from wheels with ordinary pip call:
pip install pandas numpy
From the docs:
Pip prefers Wheels where they are available. To disable this, use the --no-binary flag for pip install.
If no satisfactory wheels are found, pip will default to finding source archives.

Why wouldn't this project I published to PyPI install with pip?

I've published a project to PyPI for the first time (https://pypi.org/project/xontrib-autojump/). But I get the following error when I try to install the project with this pip command:
$ pip install xontrib-autojump --user
Collecting xontrib-autojump
Could not find a version that satisfies the requirement xontrib-autojump (from versions: 0.1.linux-x86_64, 0.2.linux-x86_64, 0.3.linux-x86_64, 0.4.linux-x86_64)
No matching distribution found for xontrib-autojump
This project does appear when I run pip search xontrib-autojump:
$ pip search xontrib-autojump
xontrib-autojump (0.4) - autojump support for xonsh
...
Why can't I install this package with pip?
There are a number of possible problem areas - the main one is that it looks to me that you have not followed the naming convention needed to specify which python version the download is suitable for.
It is also a very good idea to set the metadata as this assist with finding packages.
The Packaging Tutorial is very helpful on this. It is also recommend that you test the upload and install process using the test instance of pypi.
The other big problem st that you "package" does not contain any python code and is not a python package in any way shape or form.

Installing gevent in virtualenv

I am just starting with virtualenv, but I am trying to install gevent within a virtualenv environment (I am running Windows). When I use PIP from virtualenv, I get this error:
MyEnv>pip install gevent
Downloading/unpacking gevent
Running setup.py egg_info for package gevent
Please provide path to libevent source with --libevent DIR
The package index has MSIs and EXEs for installing on Windows (http://pypi.python.org/pypi/gevent/0.13.7), but I don't know how to install those into a virtualenv environment (or if that is even possible). When I try pip install gevent-0.13.7.win32-py2.7.exe from the virtualenv promp, I get an error as well:
ValueError: ('Expected version spec in', 'D:\\Downloads\\gevent-0.13.7.win32-py2.7.exe', 'at', ':\\Downloads\\gevent-0.13.7.win32-py2.7.exe')
Does someone know how to do this?
Pip doesn't support installing binary packages, yet. If you want to install from binary package you have to use easy_install - easy_install gevent-0.13.7.win32-py2.7.exe
Microsoft Windows XP [Wersja 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.
Z:\>virtualenv z:\venv\gevent-install
New python executable in z:\venv\gevent-install\Scripts\python.exe
Installing distribute..................................................................................................
............................................................................................done.
Installing pip.................done.
Z:\>venv\gevent-install\Scripts\activate
(gevent-install) Z:\>easy_install c:\python\packages\gevent-0.13.7.win32-py2.7.exe
Processing gevent-0.13.7.win32-py2.7.exe
creating 'c:\docume~1\pdobro~1\ustawi~1\temp\easy_install-b5nj3i\gevent-0.13.7-py2.7-win32.egg' and adding 'c:\docume~1
pdobro~1\ustawi~1\temp\easy_install-b5nj3i\gevent-0.13.7-py2.7-win32.egg.tmp' to it
creating z:\venv\gevent-install\lib\site-packages\gevent-0.13.7-py2.7-win32.egg
Extracting gevent-0.13.7-py2.7-win32.egg to z:\venv\gevent-install\lib\site-packages
Adding gevent 0.13.7 to easy-install.pth file
Installed z:\venv\gevent-install\lib\site-packages\gevent-0.13.7-py2.7-win32.egg
Processing dependencies for gevent==0.13.7
Searching for greenlet
Reading http://pypi.python.org/simple/greenlet/
Reading http://bitbucket.org/ambroff/greenlet
Reading https://github.com/python-greenlet/greenlet
Best match: greenlet 0.3.4
Downloading http://pypi.python.org/packages/2.7/g/greenlet/greenlet-0.3.4-py2.7-win32.egg#md5=9941aa246358c586bb274812e
130629
Processing greenlet-0.3.4-py2.7-win32.egg
creating z:\venv\gevent-install\lib\site-packages\greenlet-0.3.4-py2.7-win32.egg
Extracting greenlet-0.3.4-py2.7-win32.egg to z:\venv\gevent-install\lib\site-packages
Adding greenlet 0.3.4 to easy-install.pth file
Installed z:\venv\gevent-install\lib\site-packages\greenlet-0.3.4-py2.7-win32.egg
Finished processing dependencies for gevent==0.13.7
(gevent-install) Z:\>
See Can I install Python windows packages into virtualenvs? Another option is to install from source and you can do this with pip but this requires setting up compiler and environment which is much harder than the simple command above.
From the error message, it would appear you need libevent source code. I would imagine you need to go a step further and compile/install libevent system-wide so pip can find it.
I would start by downloading the latest stable source from http://libevent.org/.
Compile and install it using instructions in the README: https://github.com/libevent/libevent#readme
To compile it on Windows, you'll need to use GNU-style build utilities like make and autoconf. I recommend http://www.mingw.org/.
Once you've installed libevent system-wide, I imagine pip will find it and proceed with gevent installation.
In the msi for gevent-0.13.7 there's an option to select an alternate installation point. point it to the root dir of your particular virtual environment (just above where /Lib and /Scripts are located). That should install it correctly.
You also need to make sure greenlets are installed. For that you can use Piotr's suggested method with easy_install on the .exe.

Categories