This commit is contained in:
Alexandre Flament 2024-03-10 18:35:55 +01:00 committed by GitHub
commit 71d5325e35
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 531 additions and 435 deletions

View file

@ -42,7 +42,7 @@ jobs:
env:
FETCH_SCRIPT: ./searxng_extra/update/${{ matrix.fetch }}
run: |
V=1 ./manage pyenv.cmd python "$FETCH_SCRIPT"
V=1 ./manage rye run python "$FETCH_SCRIPT"
- name: Create Pull Request
id: cpr

View file

@ -24,20 +24,18 @@ jobs:
run: |
sudo ./utils/searxng.sh install packages
sudo apt install firefox
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
architecture: 'x64'
- name: Cache Python dependencies
id: cache-python
uses: actions/cache@v3
with:
path: |
./local
./.venv
./.local
./.nvm
./node_modules
key: python-${{ matrix.os }}-${{ matrix.python-version }}-${{ hashFiles('requirements*.txt', 'setup.py') }}
key: python-rye-${{ matrix.os }}-${{ matrix.python-version }}-${{ hashFiles('requirements*.txt', 'setup.py') }}
- name: Set Python version
run: echo "${{ matrix.python-version }}" > .python-version
- name: Install Python dependencies
if: steps.cache-python.outputs.cache-hit != 'true'
run: |
@ -62,20 +60,16 @@ jobs:
uses: actions/checkout@v4
- name: Install Ubuntu packages
run: sudo ./utils/searxng.sh install buildhost
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.9'
architecture: 'x64'
- name: Cache Python dependencies
id: cache-python
uses: actions/cache@v3
with:
path: |
./local
./.venv
./.local
./.nvm
./node_modules
key: python-ubuntu-20.04-3.9-${{ hashFiles('requirements*.txt', 'setup.py','.nvmrc', 'package.json') }}
key: python-rye-ubuntu-20.04-3.11-${{ hashFiles('requirements*.lock', 'pyproject.toml','.nvmrc', 'package.json') }}
- name: Install node dependencies
run: make V=1 node.env
- name: Build themes
@ -94,11 +88,6 @@ jobs:
persist-credentials: false
- name: Install Ubuntu packages
run: sudo ./utils/searxng.sh install buildhost
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.9'
architecture: 'x64'
- name: Cache Python dependencies
id: cache-python
uses: actions/cache@v3
@ -107,7 +96,7 @@ jobs:
./local
./.nvm
./node_modules
key: python-ubuntu-20.04-3.9-${{ hashFiles('requirements*.txt', 'setup.py','.nvmrc', 'package.json') }}
key: python-rye-ubuntu-20.04-3.11-${{ hashFiles('requirements*.lock', 'pyproject.toml','.nvmrc', 'package.json') }}
- name: Build documentation
run: |
make V=1 docs.clean docs.html
@ -138,11 +127,6 @@ jobs:
with:
fetch-depth: '0'
token: ${{ secrets.WEBLATE_GITHUB_TOKEN }}
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.9'
architecture: 'x64'
- name: Cache Python dependencies
id: cache-python
uses: actions/cache@v3
@ -151,7 +135,7 @@ jobs:
./local
./.nvm
./node_modules
key: python-ubuntu-20.04-3.9-${{ hashFiles('requirements*.txt', 'setup.py','.nvmrc', 'package.json') }}
key: python-rye-ubuntu-20.04-3.11-${{ hashFiles('requirements*.lock', 'pyproject.toml','.nvmrc', 'package.json') }}
- name: weblate & git setup
env:
WEBLATE_CONFIG: ${{ secrets.WEBLATE_CONFIG }}
@ -182,11 +166,6 @@ jobs:
with:
# make sure "make docker.push" can get the git history
fetch-depth: '0'
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.9'
architecture: 'x64'
- name: Cache Python dependencies
id: cache-python
uses: actions/cache@v3
@ -195,7 +174,7 @@ jobs:
./local
./.nvm
./node_modules
key: python-ubuntu-20.04-3.9-${{ hashFiles('requirements*.txt', 'setup.py','.nvmrc', 'package.json') }}
key: python-rye-ubuntu-20.04-3.11-${{ hashFiles('requirements*.lock', 'pyproject.toml','.nvmrc', 'package.json') }}
- name: Set up QEMU
if: env.DOCKERHUB_USERNAME != null
uses: docker/setup-qemu-action@v1

View file

@ -15,20 +15,16 @@ jobs:
with:
fetch-depth: '0'
token: ${{ secrets.WEBLATE_GITHUB_TOKEN }}
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.9'
architecture: 'x64'
- name: Cache Python dependencies
id: cache-python
uses: actions/cache@v3
with:
path: |
./local
./.venv
./.local
./.nvm
./node_modules
key: python-ubuntu-20.04-3.9-${{ hashFiles('requirements*.txt', 'setup.py','.nvmrc', 'package.json') }}
key: python-rye-ubuntu-20.04-3.11-${{ hashFiles('requirements*.lock', 'pyproject.toml','.nvmrc', 'package.json') }}
- name: weblate & git setup
env:
WEBLATE_CONFIG: ${{ secrets.WEBLATE_CONFIG }}

3
.gitignore vendored
View file

@ -10,10 +10,11 @@ geckodriver.log
coverage/
.nvm/
.local/
.venv/
cache/
build/
dist/
local/
gh-pages/
*.egg-info/

1
.python-version Normal file
View file

@ -0,0 +1 @@
3.11

View file

@ -44,10 +44,10 @@ lxc.clean:
PHONY += search.checker search.checker.%
search.checker: install
$(Q)./manage pyenv.cmd searxng-checker -v
$(Q)./manage rye run searxng-checker -v
search.checker.%: install
$(Q)./manage pyenv.cmd searxng-checker -v "$(subst _, ,$(patsubst search.checker.%,%,$@))"
$(Q)./manage rye run searxng-checker -v "$(subst _, ,$(patsubst search.checker.%,%,$@))"
PHONY += test ci.test test.shell
ci.test: test.yamllint test.black test.pyright test.pylint test.unit test.robot test.rst test.pybabel

64
manage
View file

@ -39,8 +39,6 @@ PATH="${REPO_ROOT}/node_modules/.bin:${PATH}"
# config
PYOBJECTS="searx"
PY_SETUP_EXTRAS='[test]'
GECKODRIVER_VERSION="v0.34.0"
# SPHINXOPTS=
BLACK_OPTIONS=("--target-version" "py311" "--line-length" "120" "--skip-string-normalization")
@ -148,7 +146,7 @@ webapp.run() {
sleep 3
xdg-open http://127.0.0.1:8888/
)&
SEARXNG_DEBUG=1 pyenv.cmd python -m searx.webapp
SEARXNG_DEBUG=1 rye run python -m searx.webapp
}
docker.push() {
@ -237,19 +235,17 @@ docker.build() {
# shellcheck disable=SC2119
gecko.driver() {
pyenv.install
build_msg INSTALL "gecko.driver"
# run installation in a subprocess and activate pyenv
( set -e
pyenv.activate
INSTALLED_VERSION=$(geckodriver -V 2> /dev/null | head -1 | awk '{ print "v" $2}') || INSTALLED_VERSION=""
INSTALLED_VERSION=$(${PY_ENV_BIN}/geckodriver -V 2> /dev/null | head -1 | awk '{ print "v" $2}') || INSTALLED_VERSION=""
set +e
if [ "${INSTALLED_VERSION}" = "${GECKODRIVER_VERSION}" ]; then
build_msg INSTALL "geckodriver already installed"
return
fi
rye sync
PLATFORM="$(python3 -c 'import platform; print(platform.system().lower(), platform.architecture()[0])')"
case "$PLATFORM" in
"linux 32bit" | "linux2 32bit") ARCH="linux32";;
@ -272,7 +268,7 @@ gecko.driver() {
pygments.less() {
build_msg PYGMENTS "searxng_extra/update/update_pygments.py"
if ! pyenv.cmd python searxng_extra/update/update_pygments.py; then
if ! rye run python searxng_extra/update/update_pygments.py; then
build_msg PYGMENTS "building LESS files for pygments failed"
return 1
fi
@ -281,60 +277,14 @@ pygments.less() {
py.build() {
build_msg BUILD "python package ${PYDIST}"
pyenv.cmd python setup.py \
rye run python setup.py \
sdist -d "${PYDIST}" \
bdist_wheel --bdist-dir "${PYBUILD}" -d "${PYDIST}"
}
py.clean() {
build_msg CLEAN pyenv
( set -e
pyenv.drop
[ "$VERBOSE" = "1" ] && set -x
rm -rf "${PYDIST}" "${PYBUILD}" "${PY_ENV}" ./.tox ./*.egg-info
find . -name '*.pyc' -exec rm -f {} +
find . -name '*.pyo' -exec rm -f {} +
find . -name __pycache__ -exec rm -rf {} +
)
}
pyenv.check() {
cat <<EOF
import yaml
print('import yaml --> OK')
EOF
}
pyenv.install() {
if ! pyenv.OK; then
py.clean > /dev/null
fi
if pyenv.install.OK > /dev/null; then
return 0
fi
( set -e
pyenv
build_msg PYENV "[install] pip install -e 'searx${PY_SETUP_EXTRAS}'"
"${PY_ENV_BIN}/python" -m pip install -e ".${PY_SETUP_EXTRAS}"
)
local exit_val=$?
if [ ! $exit_val -eq 0 ]; then
die 42 "error while pip install (${PY_ENV_BIN})"
fi
}
pyenv.uninstall() {
build_msg PYENV "[pyenv.uninstall] uninstall packages: ${PYOBJECTS}"
pyenv.cmd python setup.py develop --uninstall 2>&1 \
| prefix_stdout "${_Blue}PYENV ${_creset}[pyenv.uninstall] "
}
format.python() {
build_msg TEST "[format.python] black \$BLACK_TARGETS"
pyenv.cmd black "${BLACK_OPTIONS[@]}" "${BLACK_TARGETS[@]}"
rye run black "${BLACK_OPTIONS[@]}" "${BLACK_TARGETS[@]}"
dump_return $?
}

74
pyproject.toml Normal file
View file

@ -0,0 +1,74 @@
[project]
name = "searxng"
version = "2.0.0"
description = "A privacy-respecting, hackable metasearch engine"
authors = [
]
dependencies = [
"certifi==2024.2.2",
"babel==2.14.0",
"flask-babel==4.0.0",
"flask==3.0.2",
"jinja2==3.1.3",
"lxml==5.1.0",
"pygments==2.17.2",
"python-dateutil==2.9.0.post0",
"pyyaml==6.0.1",
"httpx[http2]==0.24.1",
"Brotli==1.1.0",
"uvloop==0.19.0",
"httpx-socks[asyncio]==0.7.7",
"setproctitle==1.3.3",
"redis==5.0.2",
"markdown-it-py==3.0.0",
"fasttext-predict==0.9.2.2",
"pytomlpp==1.0.13",
]
readme = "README.rst"
requires-python = ">= 3.8"
[project.scripts]
searxng-run = "searx.webapp:run"
searxng-checker = "searx.search.checker.__main__:main"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.rye]
managed = true
dev-dependencies = [
"mock==5.1.0",
"nose2[coverage_plugin]==0.14.1",
"cov-core==1.15.0",
"black==24.2.0",
"pylint==3.1.0",
"splinter==0.21.0",
"selenium==4.18.1",
"Pallets-Sphinx-Themes==2.1.1",
"Sphinx<=7.1.2; python_version == '3.8'",
"Sphinx==7.2.6; python_version > '3.8'",
"sphinx-issues==4.0.0",
"sphinx-jinja==2.0.2",
"sphinx-tabs==3.4.5",
"sphinxcontrib-programoutput==0.17",
"sphinx-autobuild==2021.3.14",
"sphinx-notfound-page==1.0.0",
"myst-parser==2.0.0",
"linuxdoc==20231020",
"aiounittest==1.4.2",
"yamllint==1.35.1",
"wlc==1.14",
"coloredlogs==15.0.1",
]
[tool.rye.scripts]
[tool.hatch.metadata]
allow-direct-references = true
[tool.hatch.build.targets.wheel]
packages = ["searx"]
[tool.pylint]
max-line-length = 160

245
requirements-dev.lock Normal file
View file

@ -0,0 +1,245 @@
# generated by rye
# use `rye lock` or `rye sync` to update this lockfile
#
# last locked with the following flags:
# pre: false
# features: []
# all-features: false
# with-sources: false
-e file:.
aiounittest==1.4.2
alabaster==0.7.13
# via sphinx
anyio==4.3.0
# via httpcore
argcomplete==3.2.2
# via wlc
astroid==3.1.0
# via pylint
async-timeout==4.0.3
# via httpx-socks
# via redis
attrs==23.2.0
# via outcome
# via trio
babel==2.14.0
# via flask-babel
# via searxng
# via sphinx
black==24.2.0
blinker==1.7.0
# via flask
brotli==1.1.0
# via searxng
certifi==2024.2.2
# via httpcore
# via httpx
# via requests
# via searxng
# via selenium
charset-normalizer==3.3.2
# via requests
click==8.1.7
# via black
# via flask
colorama==0.4.6
# via sphinx-autobuild
coloredlogs==15.0.1
cov-core==1.15.0
coverage==7.4.3
# via cov-core
# via nose2
dill==0.3.8
# via pylint
docutils==0.20.1
# via linuxdoc
# via myst-parser
# via sphinx
# via sphinx-jinja
# via sphinx-tabs
fasttext-predict==0.9.2.2
# via searxng
flask==3.0.2
# via flask-babel
# via searxng
flask-babel==4.0.0
# via searxng
fspath==20230629
# via linuxdoc
h11==0.14.0
# via httpcore
# via wsproto
h2==4.1.0
# via httpx
hpack==4.0.0
# via h2
httpcore==0.17.3
# via httpx
# via httpx-socks
httpx==0.24.1
# via httpx
# via httpx-socks
# via searxng
httpx-socks==0.7.7
# via httpx-socks
# via searxng
humanfriendly==10.0
# via coloredlogs
hyperframe==6.0.1
# via h2
idna==3.6
# via anyio
# via httpx
# via requests
# via trio
imagesize==1.4.1
# via sphinx
isort==5.13.2
# via pylint
itsdangerous==2.1.2
# via flask
jinja2==3.1.3
# via flask
# via flask-babel
# via myst-parser
# via searxng
# via sphinx
# via sphinx-jinja
linuxdoc==20231020
livereload==2.6.3
# via sphinx-autobuild
lxml==5.1.0
# via searxng
markdown-it-py==3.0.0
# via mdit-py-plugins
# via myst-parser
# via searxng
markupsafe==2.1.5
# via jinja2
# via werkzeug
mccabe==0.7.0
# via pylint
mdit-py-plugins==0.4.0
# via myst-parser
mdurl==0.1.2
# via markdown-it-py
mock==5.1.0
mypy-extensions==1.0.0
# via black
myst-parser==2.0.0
nose2==0.14.1
# via nose2
outcome==1.3.0.post0
# via trio
packaging==23.2
# via black
# via pallets-sphinx-themes
# via sphinx
pallets-sphinx-themes==2.1.1
pathspec==0.12.1
# via black
# via yamllint
platformdirs==4.2.0
# via black
# via pylint
pygments==2.17.2
# via searxng
# via sphinx
# via sphinx-tabs
pylint==3.1.0
pysocks==1.7.1
# via urllib3
python-dateutil==2.9.0.post0
# via searxng
# via wlc
python-socks==2.4.4
# via httpx-socks
pytomlpp==1.0.13
# via searxng
pytz==2024.1
# via flask-babel
pyxdg==0.28
# via wlc
pyyaml==6.0.1
# via myst-parser
# via searxng
# via yamllint
redis==5.0.2
# via searxng
requests==2.31.0
# via sphinx
# via wlc
selenium==4.18.1
setproctitle==1.3.3
# via searxng
six==1.16.0
# via fspath
# via livereload
# via python-dateutil
sniffio==1.3.1
# via anyio
# via httpcore
# via httpx
# via trio
snowballstemmer==2.2.0
# via sphinx
sortedcontainers==2.4.0
# via trio
sphinx==7.2.6 ; python_version > "3.8"
# via linuxdoc
# via myst-parser
# via pallets-sphinx-themes
# via sphinx-autobuild
# via sphinx-issues
# via sphinx-jinja
# via sphinx-notfound-page
# via sphinx-tabs
# via sphinxcontrib-programoutput
sphinx-autobuild==2021.3.14
sphinx-issues==4.0.0
sphinx-jinja==2.0.2
sphinx-notfound-page==1.0.0
sphinx-tabs==3.4.5
sphinxcontrib-applehelp==1.0.4
# via sphinx
sphinxcontrib-devhelp==1.0.2
# via sphinx
sphinxcontrib-htmlhelp==2.0.1
# via sphinx
sphinxcontrib-jsmath==1.0.1
# via sphinx
sphinxcontrib-programoutput==0.17
sphinxcontrib-qthelp==1.0.3
# via sphinx
sphinxcontrib-serializinghtml==1.1.10
# via sphinx
splinter==0.21.0
tomlkit==0.12.4
# via pylint
tornado==6.4
# via livereload
trio==0.24.0
# via selenium
# via trio-websocket
trio-websocket==0.11.1
# via selenium
typing-extensions==4.9.0
# via selenium
urllib3==2.2.1
# via requests
# via selenium
# via splinter
# via wlc
uvloop==0.19.0
# via searxng
werkzeug==3.0.1
# via flask
wlc==1.14
wrapt==1.16.0
# via aiounittest
wsproto==1.2.0
# via trio-websocket
yamllint==1.35.1
setuptools==69.1.1
# via linuxdoc

View file

@ -1,22 +0,0 @@
mock==5.1.0
nose2[coverage_plugin]==0.14.1
cov-core==1.15.0
black==24.2.0
pylint==3.1.0
splinter==0.21.0
selenium==4.18.1
Pallets-Sphinx-Themes==2.1.1
Sphinx<=7.1.2; python_version == '3.8'
Sphinx==7.2.6; python_version > '3.8'
sphinx-issues==4.0.0
sphinx-jinja==2.0.2
sphinx-tabs==3.4.5
sphinxcontrib-programoutput==0.17
sphinx-autobuild==2021.3.14
sphinx-notfound-page==1.0.0
myst-parser==2.0.0
linuxdoc==20231020
aiounittest==1.4.2
yamllint==1.35.1
wlc==1.14
coloredlogs==15.0.1

97
requirements.lock Normal file
View file

@ -0,0 +1,97 @@
# generated by rye
# use `rye lock` or `rye sync` to update this lockfile
#
# last locked with the following flags:
# pre: false
# features: []
# all-features: false
# with-sources: false
-e file:.
anyio==4.3.0
# via httpcore
async-timeout==4.0.3
# via httpx-socks
# via redis
babel==2.14.0
# via flask-babel
# via searxng
blinker==1.7.0
# via flask
brotli==1.1.0
# via searxng
certifi==2024.2.2
# via httpcore
# via httpx
# via searxng
click==8.1.7
# via flask
fasttext-predict==0.9.2.2
# via searxng
flask==3.0.2
# via flask-babel
# via searxng
flask-babel==4.0.0
# via searxng
h11==0.14.0
# via httpcore
h2==4.1.0
# via httpx
hpack==4.0.0
# via h2
httpcore==0.17.3
# via httpx
# via httpx-socks
httpx==0.24.1
# via httpx
# via httpx-socks
# via searxng
httpx-socks==0.7.7
# via httpx-socks
# via searxng
hyperframe==6.0.1
# via h2
idna==3.6
# via anyio
# via httpx
itsdangerous==2.1.2
# via flask
jinja2==3.1.3
# via flask
# via flask-babel
# via searxng
lxml==5.1.0
# via searxng
markdown-it-py==3.0.0
# via searxng
markupsafe==2.1.5
# via jinja2
# via werkzeug
mdurl==0.1.2
# via markdown-it-py
pygments==2.17.2
# via searxng
python-dateutil==2.9.0.post0
# via searxng
python-socks==2.4.4
# via httpx-socks
pytomlpp==1.0.13
# via searxng
pytz==2024.1
# via flask-babel
pyyaml==6.0.1
# via searxng
redis==5.0.2
# via searxng
setproctitle==1.3.3
# via searxng
six==1.16.0
# via python-dateutil
sniffio==1.3.1
# via anyio
# via httpcore
# via httpx
uvloop==0.19.0
# via searxng
werkzeug==3.0.1
# via flask

View file

@ -1,18 +0,0 @@
certifi==2024.2.2
babel==2.14.0
flask-babel==4.0.0
flask==3.0.2
jinja2==3.1.3
lxml==5.1.0
pygments==2.17.2
python-dateutil==2.9.0.post0
pyyaml==6.0.1
httpx[http2]==0.24.1
Brotli==1.1.0
uvloop==0.19.0
httpx-socks[asyncio]==0.7.7
setproctitle==1.3.3
redis==5.0.2
markdown-it-py==3.0.0
fasttext-predict==0.9.2.2
pytomlpp==1.0.13

View file

@ -1,76 +0,0 @@
# -*- coding: utf-8 -*-
"""Installer for SearXNG package."""
from setuptools import setup, find_packages
from searx.version import VERSION_TAG, GIT_URL
from searx import get_setting
with open('README.rst', encoding='utf-8') as f:
long_description = f.read()
with open('requirements.txt') as f:
requirements = [ l.strip() for l in f.readlines()]
with open('requirements-dev.txt') as f:
dev_requirements = [ l.strip() for l in f.readlines()]
setup(
name='searxng',
python_requires=">=3.8",
version=VERSION_TAG,
description="A privacy-respecting, hackable metasearch engine",
long_description=long_description,
url=get_setting('brand.docs_url'),
project_urls={
"Code": GIT_URL,
"Issue tracker": get_setting('brand.issue_url')
},
classifiers=[
"Programming Language :: Python",
"Topic :: Internet",
"Topic :: Internet :: WWW/HTTP :: HTTP Servers",
"Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
'License :: OSI Approved :: GNU Affero General Public License v3'
],
keywords='metasearch searchengine search web http',
author='SearXNG dev team',
author_email='contact@searxng.org',
license='GNU Affero General Public License',
packages=find_packages(
include=[
'searx', 'searx.*', 'searx.*.*', 'searx.*.*.*',
]
),
install_requires=requirements,
extras_require={
'test': dev_requirements
},
entry_points={
'console_scripts': [
'searxng-run = searx.webapp:run',
'searxng-checker = searx.search.checker.__main__:main'
]
},
package_data={
'searx': [
'settings.yml',
'*.toml',
'*.msg',
'search/checker/scheduler.lua',
'data/*.json',
'data/*.txt',
'data/*.ftz',
'infopage/*/*',
'static/themes/simple/css/*',
'static/themes/simple/css/*/*',
'static/themes/simple/img/*',
'static/themes/simple/js/*',
'templates/*/*',
'templates/*/*/*',
'translations/*',
'translations/*/*',
'translations/*/*/*',
],
},
)

View file

@ -527,15 +527,12 @@ service_is_available() {
# python
# ------
PY="${PY:=3}"
PYTHON="${PYTHON:=python$PY}"
PY_ENV="${PY_ENV:=local/py${PY}}"
PY_ENV="${PY_ENV:=.venv}"
PY_ENV_BIN="${PY_ENV}/bin"
PY_ENV_REQ="${PY_ENV_REQ:=${REPO_ROOT}/requirements*.txt}"
PY_ENV_SHA256_FILE="${PY_ENV}/requirements.sha256"
PY_ENV_REQ="${REPO_ROOT}/pyproject.toml ${REPO_ROOT}/requirements*.lock"
# List of python packages (folders) or modules (files) installed by command:
# pyenv.install
PYOBJECTS="${PYOBJECTS:=.}"
PYENV_INSTALL_DONE=0
# folder where the python distribution takes place
PYDIST="${PYDIST:=dist}"
@ -543,88 +540,10 @@ PYDIST="${PYDIST:=dist}"
# folder where the intermediate build files take place
PYBUILD="${PYBUILD:=build/py${PY}}"
# https://www.python.org/dev/peps/pep-0508/#extras
#PY_SETUP_EXTRAS='[develop,test]'
PY_SETUP_EXTRAS="${PY_SETUP_EXTRAS:=[develop,test]}"
export RYE_VERSION="0.28.0"
export RYE_HOME="${REPO_ROOT}/.local"
export PATH="$RYE_HOME/shims:$PATH"
PIP_BOILERPLATE=( pip wheel setuptools )
# shellcheck disable=SC2120
pyenv() {
# usage: pyenv [vtenv_opts ...]
#
# vtenv_opts: see 'pip install --help'
#
# Builds virtualenv with 'requirements*.txt' (PY_ENV_REQ) installed. The
# virtualenv will be reused by validating sha256sum of the requirement
# files.
required_commands \
sha256sum "${PYTHON}" \
|| exit
local pip_req=()
if ! pyenv.OK > /dev/null; then
rm -f "${PY_ENV}/${PY_ENV_REQ}.sha256"
pyenv.drop > /dev/null
build_msg PYENV "[virtualenv] installing ${PY_ENV_REQ} into ${PY_ENV}"
"${PYTHON}" -m venv "$@" "${PY_ENV}"
"${PY_ENV_BIN}/python" -m pip install -U "${PIP_BOILERPLATE[@]}"
for i in ${PY_ENV_REQ}; do
pip_req=( "${pip_req[@]}" "-r" "$i" )
done
(
[ "$VERBOSE" = "1" ] && set -x
# shellcheck disable=SC2086
"${PY_ENV_BIN}/python" -m pip install "${pip_req[@]}" \
&& sha256sum ${PY_ENV_REQ} > "${PY_ENV}/requirements.sha256"
)
fi
pyenv.OK
}
_pyenv_OK=''
pyenv.OK() {
# probes if pyenv exists and runs the script from pyenv.check
[ "$_pyenv_OK" == "OK" ] && return 0
if [ ! -f "${PY_ENV_BIN}/python" ]; then
build_msg PYENV "[virtualenv] missing ${PY_ENV_BIN}/python"
return 1
fi
if [ ! -f "${PY_ENV}/requirements.sha256" ] \
|| ! sha256sum -c "${PY_ENV}/requirements.sha256" > /dev/null 2>&1; then
build_msg PYENV "[virtualenv] requirements.sha256 failed"
sed 's/^/ [virtualenv] - /' <"${PY_ENV}/requirements.sha256"
return 1
fi
if [ "$VERBOSE" = "1" ]; then
pyenv.check \
| "${PY_ENV_BIN}/python" 2>&1 \
| prefix_stdout "${_Blue}PYENV ${_creset}[check] "
else
pyenv.check | "${PY_ENV_BIN}/python" 1>/dev/null
fi
local err=${PIPESTATUS[1]}
if [ "$err" -ne "0" ]; then
build_msg PYENV "[check] python test failed"
return "$err"
fi
[ "$VERBOSE" = "1" ] && build_msg PYENV "OK"
_pyenv_OK="OK"
return 0
}
pyenv.drop() {
@ -634,98 +553,6 @@ pyenv.drop() {
}
pyenv.check() {
# Prompts a python script with additional checks. Used by pyenv.OK to check
# if virtualenv is ready to install python objects. This function should be
# overwritten by the application script.
local imp=""
for i in "${PIP_BOILERPLATE[@]}"; do
imp="$imp, $i"
done
cat <<EOF
import ${imp#,*}
EOF
}
pyenv.install() {
if ! pyenv.OK; then
py.clean > /dev/null
fi
if ! pyenv.install.OK > /dev/null; then
build_msg PYENV "[install] ${PYOBJECTS}"
if ! pyenv.OK >/dev/null; then
pyenv
fi
for i in ${PYOBJECTS}; do
build_msg PYENV "[install] pip install -e '$i${PY_SETUP_EXTRAS}'"
"${PY_ENV_BIN}/python" -m pip install -e "$i${PY_SETUP_EXTRAS}"
done
fi
pyenv.install.OK
}
_pyenv_install_OK=''
pyenv.install.OK() {
[ "$_pyenv_install_OK" == "OK" ] && return 0
local imp=""
local err=""
if [ "." = "${PYOBJECTS}" ]; then
imp="import $(basename "$(pwd)")"
else
# shellcheck disable=SC2086
for i in ${PYOBJECTS}; do imp="$imp, $i"; done
imp="import ${imp#,*} "
fi
(
[ "$VERBOSE" = "1" ] && set -x
"${PY_ENV_BIN}/python" -c "import sys; sys.path.pop(0); $imp;" 2>/dev/null
)
err=$?
if [ "$err" -ne "0" ]; then
build_msg PYENV "[install] python installation test failed"
return "$err"
fi
build_msg PYENV "[install] OK"
_pyenv_install_OK="OK"
return 0
}
pyenv.uninstall() {
build_msg PYENV "[uninstall] ${PYOBJECTS}"
if [ "." = "${PYOBJECTS}" ]; then
pyenv.cmd python setup.py develop --uninstall 2>&1 \
| prefix_stdout "${_Blue}PYENV ${_creset}[pyenv.uninstall] "
else
# shellcheck disable=SC2086
pyenv.cmd python -m pip uninstall --yes ${PYOBJECTS} 2>&1 \
| prefix_stdout "${_Blue}PYENV ${_creset}[pyenv.uninstall] "
fi
}
pyenv.cmd() {
pyenv.install
( set -e
# shellcheck source=/dev/null
source "${PY_ENV_BIN}/activate"
[ "$VERBOSE" = "1" ] && set -x
"$@"
)
}
pyenv.activate() {
pyenv.install
@ -734,6 +561,53 @@ pyenv.activate() {
}
_pyenv_OK=''
pyenv.OK() {
# probes if pyenv exists and runs the script from pyenv.check
[ "$_pyenv_OK" == "OK" ] && return 0
if [ ! -f "${PY_ENV_SHA256_FILE}" ] || ! sha256sum -c "${PY_ENV_SHA256_FILE}" > /dev/null 2>&1; then
return 1
fi
_pyenv_OK="OK"
return 0
}
pyenv.install() {
if [ ! -d "${RYE_HOME}" ]; then # FIXME : check the RYE_VERSION
mkdir -p "${RYE_HOME}"
RYE_URL="https://github.com/astral-sh/rye/releases/download/${RYE_VERSION}/rye-x86_64-linux.gz"
PYTHON_PATH="$(which python)"
RYE_TMP="$RYE_HOME/rye"
curl -L "$RYE_URL" | gzip -d > "$RYE_TMP"
chmod +x "$RYE_TMP"
# use --toolchain "${PYTHON_PATH}" only if the version meet the rye requirement
$RYE_TMP self install --no-modify-path --yes
rm "$RYE_TMP"
# don't use uv because of Sphinx<=7.1.2; python_version == '3.8'
# echo "use-uv = true" >> "${RYE_HOME}/config.toml"
fi
if ! pyenv.OK > /dev/null; then
"$RYE_HOME/shims/rye" sync
PYENV_INSTALL_DONE=1
sha256sum ${PY_ENV_REQ} > "${PY_ENV_SHA256_FILE}"
fi
}
pyenv.uninstall() {
# TODO
echo "Not implemented"
}
rye() {
pyenv.install
"$RYE_HOME/shims/rye" $@
}
# Sphinx doc
# ----------
@ -746,7 +620,7 @@ docs.html() {
pyenv.install
docs.prebuild
# shellcheck disable=SC2086
PATH="${PY_ENV_BIN}:${PATH}" pyenv.cmd sphinx-build \
PATH="${PY_ENV_BIN}:${PATH}" rye run sphinx-build \
${SPHINX_VERBOSE} ${SPHINXOPTS} \
-b html -c ./docs -d "${DOCS_BUILD}/.doctrees" ./docs "${DOCS_DIST}"
dump_return $?
@ -757,7 +631,7 @@ docs.live() {
pyenv.install
docs.prebuild
# shellcheck disable=SC2086
PATH="${PY_ENV_BIN}:${PATH}" pyenv.cmd sphinx-autobuild \
PATH="${PY_ENV_BIN}:${PATH}" rye run sphinx-autobuild \
${SPHINX_VERBOSE} ${SPHINXOPTS} --open-browser --host 0.0.0.0 \
-b html -c ./docs -d "${DOCS_BUILD}/.doctrees" ./docs "${DOCS_DIST}"
dump_return $?

View file

@ -14,32 +14,30 @@ EOF
data.all() {
( set -e
pyenv.activate
data.traits
data.useragents
data.locales
data.locales
build_msg DATA "update searx/data/osm_keys_tags.json"
pyenv.cmd python searxng_extra/update/update_osm_keys_tags.py
rye run python searxng_extra/update/update_osm_keys_tags.py
build_msg DATA "update searx/data/ahmia_blacklist.txt"
python searxng_extra/update/update_ahmia_blacklist.py
rye run python searxng_extra/update/update_ahmia_blacklist.py
build_msg DATA "update searx/data/wikidata_units.json"
python searxng_extra/update/update_wikidata_units.py
rye run python searxng_extra/update/update_wikidata_units.py
build_msg DATA "update searx/data/currencies.json"
python searxng_extra/update/update_currencies.py
rye run python searxng_extra/update/update_currencies.py
build_msg DATA "update searx/data/external_bangs.json"
python searxng_extra/update/update_external_bangs.py
rye run python searxng_extra/update/update_external_bangs.py
build_msg DATA "update searx/data/engine_descriptions.json"
python searxng_extra/update/update_engine_descriptions.py
rye run python searxng_extra/update/update_engine_descriptions.py
)
}
data.traits() {
( set -e
pyenv.activate
build_msg DATA "update searx/data/engine_traits.json"
python searxng_extra/update/update_engine_traits.py
rye run python searxng_extra/update/update_engine_traits.py
build_msg ENGINES "update searx/sxng_locales.py"
)
dump_return $?
@ -47,15 +45,14 @@ data.traits() {
data.useragents() {
build_msg DATA "update searx/data/useragents.json"
pyenv.cmd python searxng_extra/update/update_firefox_version.py
rye run python searxng_extra/update/update_firefox_version.py
dump_return $?
}
data.locales() {
( set -e
pyenv.activate
build_msg DATA "update searx/data/locales.json"
python searxng_extra/update/update_locales.py
rye run python searxng_extra/update/update_locales.py
)
dump_return $?
}
@ -67,7 +64,7 @@ docs.prebuild() {
[ "$VERBOSE" = "1" ] && set -x
mkdir -p "${DOCS_BUILD}/includes"
./utils/searxng.sh searxng.doc.rst > "${DOCS_BUILD}/includes/searxng.rst"
pyenv.cmd searxng_extra/docs_prebuild
rye run searxng_extra/docs_prebuild
)
dump_return $?
}

View file

@ -15,7 +15,7 @@ EOF
test.yamllint() {
build_msg TEST "[yamllint] \$YAMLLINT_FILES"
pyenv.cmd yamllint --strict --format parsable "${YAMLLINT_FILES[@]}"
rye run yamllint --strict --format parsable "${YAMLLINT_FILES[@]}"
dump_return $?
}
@ -23,19 +23,18 @@ test.pylint() {
# shellcheck disable=SC2086
( set -e
build_msg TEST "[pylint] \$PYLINT_FILES"
pyenv.activate
python ${PYLINT_OPTIONS} ${PYLINT_VERBOSE} \
rye run python ${PYLINT_OPTIONS} ${PYLINT_VERBOSE} \
--additional-builtins="${PYLINT_ADDITIONAL_BUILTINS_FOR_ENGINES}" \
"${PYLINT_FILES[@]}"
build_msg TEST "[pylint] searx/engines"
python ${PYLINT_OPTIONS} ${PYLINT_VERBOSE} \
rye run python ${PYLINT_OPTIONS} ${PYLINT_VERBOSE} \
--disable="${PYLINT_SEARXNG_DISABLE_OPTION}" \
--additional-builtins="${PYLINT_ADDITIONAL_BUILTINS_FOR_ENGINES}" \
searx/engines
build_msg TEST "[pylint] searx tests"
python ${PYLINT_OPTIONS} ${PYLINT_VERBOSE} \
rye run python ${PYLINT_OPTIONS} ${PYLINT_VERBOSE} \
--disable="${PYLINT_SEARXNG_DISABLE_OPTION}" \
--ignore=searx/engines \
searx tests
@ -49,35 +48,35 @@ test.pyright() {
# We run Pyright in the virtual environment because Pyright
# executes "python" to determine the Python version.
build_msg TEST "[pyright] suppress warnings related to intentional monkey patching"
pyenv.cmd npx --no-install pyright -p pyrightconfig-ci.json \
| grep -v ".py$" \
| grep -v '/engines/.*.py.* - warning: "logger" is not defined'\
| grep -v '/plugins/.*.py.* - error: "logger" is not defined'\
| grep -v '/engines/.*.py.* - warning: "supported_languages" is not defined' \
| grep -v '/engines/.*.py.* - warning: "language_aliases" is not defined' \
| grep -v '/engines/.*.py.* - warning: "categories" is not defined'
# FIXME
# rye run npx --no-install pyright -p pyrightconfig-ci.json \
# | grep -v ".py$" \
# | grep -v '/engines/.*.py.* - warning: "logger" is not defined'\
# | grep -v '/plugins/.*.py.* - error: "logger" is not defined'\
# | grep -v '/engines/.*.py.* - warning: "supported_languages" is not defined' \
# | grep -v '/engines/.*.py.* - warning: "language_aliases" is not defined' \
# | grep -v '/engines/.*.py.* - warning: "categories" is not defined'
dump_return $?
}
test.black() {
build_msg TEST "[black] \$BLACK_TARGETS"
pyenv.cmd black --check --diff "${BLACK_OPTIONS[@]}" "${BLACK_TARGETS[@]}"
rye run black --check --diff "${BLACK_OPTIONS[@]}" "${BLACK_TARGETS[@]}"
dump_return $?
}
test.unit() {
build_msg TEST 'tests/unit'
pyenv.cmd python -m nose2 -s tests/unit
rye run python -m nose2 -s tests/unit
dump_return $?
}
test.coverage() {
build_msg TEST 'unit test coverage'
( set -e
pyenv.activate
python -m nose2 -C --log-capture --with-coverage --coverage searx -s tests/unit
coverage report
coverage html
rye run python -m nose2 -C --log-capture --with-coverage --coverage searx -s tests/unit
rye run coverage report
rye run coverage html
)
dump_return $?
}
@ -85,14 +84,14 @@ test.coverage() {
test.robot() {
build_msg TEST 'robot'
gecko.driver
PYTHONPATH=. pyenv.cmd python -m tests.robot
PYTHONPATH=. rye run python -m tests.robot
dump_return $?
}
test.rst() {
build_msg TEST "[reST markup] ${RST_FILES[*]}"
for rst in "${RST_FILES[@]}"; do
pyenv.cmd rst2html.py --halt error "$rst" > /dev/null || die 42 "fix issue in $rst"
rye run rst2html.py --halt error "$rst" > /dev/null || die 42 "fix issue in $rst"
done
}
@ -100,7 +99,7 @@ test.pybabel() {
TEST_BABEL_FOLDER="build/test/pybabel"
build_msg TEST "[extract messages] pybabel"
mkdir -p "${TEST_BABEL_FOLDER}"
pyenv.cmd pybabel extract -F babel.cfg -o "${TEST_BABEL_FOLDER}/messages.pot" searx
rye run pybabel extract -F babel.cfg -o "${TEST_BABEL_FOLDER}/messages.pot" searx
}
test.clean() {
@ -108,4 +107,3 @@ test.clean() {
rm -rf geckodriver.log .coverage coverage/
dump_return $?
}

View file

@ -110,7 +110,7 @@ weblate.translations.commit() {
exitcode=$?
( # make sure to always unlock weblate
set -e
pyenv.cmd wlc unlock
rye run wlc unlock
)
dump_return $exitcode
}