MOTOR-1139 Switch to Pytest (#222)
This commit is contained in:
parent
70136ad1f2
commit
f905df8553
@ -403,9 +403,6 @@ functions:
|
||||
set -x
|
||||
export LIBMONGOCRYPT_URL="${libmongocrypt_url}"
|
||||
export TEST_ENCRYPTION=1
|
||||
if [ -n "${EXTRA_PATH}" ]; then
|
||||
export PATH="${EXTRA_PATH}:$PATH"
|
||||
fi
|
||||
PYTHON_BINARY="${PYTHON_BINARY}" \
|
||||
TOX_BINARY="${TOX_BINARY}" \
|
||||
TOX_ENV="${TOX_ENV}" \
|
||||
@ -424,7 +421,6 @@ functions:
|
||||
working_dir: "src"
|
||||
script: |
|
||||
# DO NOT ECHO WITH XTRACE (which PREPARE_SHELL does)
|
||||
|
||||
CLIENT_PEM=${DRIVERS_TOOLS}/.evergreen/x509gen/client.pem \
|
||||
CA_PEM=${DRIVERS_TOOLS}/.evergreen/x509gen/ca.pem \
|
||||
PYTHON_BINARY=${PYTHON_BINARY} \
|
||||
@ -799,7 +795,7 @@ tasks:
|
||||
commands:
|
||||
- func: "run tox"
|
||||
vars:
|
||||
TOX_ENV: py3-sphinx-docs
|
||||
TOX_ENV: docs
|
||||
|
||||
- name: "doctest"
|
||||
commands:
|
||||
@ -809,7 +805,7 @@ tasks:
|
||||
TOPOLOGY: "server"
|
||||
- func: "run tox"
|
||||
vars:
|
||||
TOX_ENV: py3-sphinx-doctest
|
||||
TOX_ENV: doctest
|
||||
|
||||
# }}}
|
||||
|
||||
@ -831,127 +827,95 @@ axes:
|
||||
- id: tox-env
|
||||
display_name: "Tox Env RHEL8"
|
||||
values:
|
||||
- id: "tornado5-pypy37"
|
||||
- id: "test-pypy38"
|
||||
variables:
|
||||
TOX_ENV: "tornado5-pypy37"
|
||||
PYTHON_BINARY: "/opt/python/pypy3.7/bin/pypy3"
|
||||
- id: "tornado5-py37"
|
||||
TOX_ENV: "test"
|
||||
PYTHON_BINARY: "/opt/python/pypy3.8/bin/python3"
|
||||
- id: "test-py37"
|
||||
variables:
|
||||
TOX_ENV: "tornado5-py37"
|
||||
TOX_ENV: "test"
|
||||
PYTHON_BINARY: "/opt/python/3.7/bin/python3"
|
||||
- id: "tornado6-pypy37"
|
||||
- id: "test-py37"
|
||||
variables:
|
||||
TOX_ENV: "tornado6-pypy37"
|
||||
PYTHON_BINARY: "/opt/python/pypy3.7/bin/pypy3"
|
||||
- id: "tornado6-py37"
|
||||
variables:
|
||||
TOX_ENV: "tornado6-py37"
|
||||
TOX_ENV: "test"
|
||||
PYTHON_BINARY: "/opt/python/3.7/bin/python3"
|
||||
- id: "tornado6-py38"
|
||||
- id: "test-py38"
|
||||
variables:
|
||||
TOX_ENV: "tornado6-py38"
|
||||
TOX_ENV: "test"
|
||||
PYTHON_BINARY: "/opt/python/3.8/bin/python3"
|
||||
- id: "tornado6-py39"
|
||||
- id: "test-py39"
|
||||
variables:
|
||||
TOX_ENV: "tornado6-py39"
|
||||
TOX_ENV: "test"
|
||||
PYTHON_BINARY: "/opt/python/3.9/bin/python3"
|
||||
- id: "tornado6-py310"
|
||||
- id: "test-py310"
|
||||
variables:
|
||||
TOX_ENV: "tornado6-py310"
|
||||
TOX_ENV: "test"
|
||||
PYTHON_BINARY: "/opt/python/3.10/bin/python3"
|
||||
- id: "tornado6-py311"
|
||||
- id: "test-py311"
|
||||
variables:
|
||||
TOX_ENV: "tornado6-py311"
|
||||
TOX_ENV: "test"
|
||||
PYTHON_BINARY: "/opt/python/3.11/bin/python3"
|
||||
- id: "tornado6-py312"
|
||||
- id: "test-py312"
|
||||
variables:
|
||||
TOX_ENV: "tornado6-py312"
|
||||
TOX_ENV: "test"
|
||||
PYTHON_BINARY: "/opt/python/3.12/bin/python3"
|
||||
- id: "tornado_git-py38"
|
||||
- id: "test-pymongo-latest"
|
||||
variables:
|
||||
TOX_ENV: "tornado_git-py38"
|
||||
PYTHON_BINARY: "/opt/python/3.8/bin/python3"
|
||||
- id: "asyncio-pypy37"
|
||||
variables:
|
||||
TOX_ENV: "asyncio-pypy37"
|
||||
PYTHON_BINARY: "/opt/python/pypy3.7/bin/pypy3"
|
||||
- id: "asyncio-py37"
|
||||
variables:
|
||||
TOX_ENV: "asyncio-py37"
|
||||
TOX_ENV: "test-pymongo-latest"
|
||||
PYTHON_BINARY: "/opt/python/3.7/bin/python3"
|
||||
- id: "asyncio-py38"
|
||||
- id: "synchro-py37"
|
||||
variables:
|
||||
TOX_ENV: "asyncio-py38"
|
||||
PYTHON_BINARY: "/opt/python/3.8/bin/python3"
|
||||
- id: "asyncio-py39"
|
||||
variables:
|
||||
TOX_ENV: "asyncio-py39"
|
||||
PYTHON_BINARY: "/opt/python/3.9/bin/python3"
|
||||
- id: "asyncio-py310"
|
||||
variables:
|
||||
TOX_ENV: "asyncio-py310"
|
||||
PYTHON_BINARY: "/opt/python/3.10/bin/python3"
|
||||
- id: "asyncio-py311"
|
||||
variables:
|
||||
TOX_ENV: "asyncio-py311"
|
||||
PYTHON_BINARY: "/opt/python/3.11/bin/python3"
|
||||
- id: "asyncio-py312"
|
||||
variables:
|
||||
TOX_ENV: "asyncio-py312"
|
||||
PYTHON_BINARY: "/opt/python/3.12/bin/python3"
|
||||
- id: "py3-pymongo-latest"
|
||||
variables:
|
||||
TOX_ENV: "py3-pymongo-latest"
|
||||
PYTHON_BINARY: "/opt/python/3.7/bin/python3"
|
||||
- id: "synchro37"
|
||||
variables:
|
||||
TOX_ENV: "synchro37"
|
||||
TOX_ENV: "synchro"
|
||||
PYTHON_BINARY: "/opt/python/3.7/bin/python3"
|
||||
- id: "synchro312"
|
||||
- id: "synchro-py312"
|
||||
variables:
|
||||
TOX_ENV: "synchro312"
|
||||
TOX_ENV: "synchro"
|
||||
PYTHON_BINARY: "/opt/python/3.12/bin/python3"
|
||||
|
||||
- id: tox-env-rhel7
|
||||
display_name: "Tox Env RHEL7"
|
||||
values:
|
||||
- id: "tornado6-py39"
|
||||
- id: "test"
|
||||
variables:
|
||||
TOX_ENV: "tornado6-py39"
|
||||
PYTHON_BINARY: "/opt/python/3.9/bin/python3"
|
||||
- id: "asyncio-py39"
|
||||
variables:
|
||||
TOX_ENV: "asyncio-py39"
|
||||
TOX_ENV: "test"
|
||||
PYTHON_BINARY: "/opt/python/3.9/bin/python3"
|
||||
|
||||
# Test Python 3.8 only on Mac.
|
||||
- id: tox-env-osx
|
||||
display_name: "Tox Env OSX"
|
||||
values:
|
||||
- id: "tornado5"
|
||||
- id: "test"
|
||||
variables:
|
||||
TOX_ENV: "tornado5"
|
||||
EXTRA_PATH: "/Library/Frameworks/Python.framework/Versions/3.8/bin/"
|
||||
- id: "tornado_git"
|
||||
variables:
|
||||
TOX_ENV: "tornado_git"
|
||||
EXTRA_PATH: "/Library/Frameworks/Python.framework/Versions/3.8/bin/"
|
||||
TOX_ENV: "test"
|
||||
PYTHON_BINARY: "/Library/Frameworks/Python.framework/Versions/3.8/bin/python3"
|
||||
|
||||
- id: tox-env-win
|
||||
display_name: "Tox Env Windows"
|
||||
values:
|
||||
- id: "asyncio"
|
||||
- id: "test-py37"
|
||||
variables:
|
||||
TOX_ENV: "asyncio"
|
||||
EXTRA_PATH: "c:\\python\\Python37"
|
||||
- id: "tornado6"
|
||||
TOX_ENV: "test"
|
||||
PYTHON_BINARY: "c:/python/Python37/python.exe"
|
||||
- id: "test-py38"
|
||||
variables:
|
||||
TOX_ENV: "tornado6"
|
||||
EXTRA_PATH: "c:\\python\\Python37"
|
||||
- id: "tornado6"
|
||||
TOX_ENV: "test"
|
||||
PYTHON_BINARY: "c:/python/Python39/python.exe"
|
||||
- id: "test-py39"
|
||||
variables:
|
||||
TOX_ENV: "tornado6"
|
||||
EXTRA_PATH: "c:\\python\\Python38"
|
||||
TOX_ENV: "test"
|
||||
PYTHON_BINARY: "c:/python/Python39/python.exe"
|
||||
- id: "test-py310"
|
||||
variables:
|
||||
TOX_ENV: "test"
|
||||
PYTHON_BINARY: "c:/python/Python310/python.exe"
|
||||
- id: "test-py311"
|
||||
variables:
|
||||
TOX_ENV: "test"
|
||||
PYTHON_BINARY: "c:/python/Python311/python.exe"
|
||||
- id: "test-py312"
|
||||
variables:
|
||||
TOX_ENV: "test"
|
||||
PYTHON_BINARY: "c:/python/Python312/python.exe"
|
||||
|
||||
- id: os
|
||||
display_name: "Operating System"
|
||||
@ -959,27 +923,15 @@ axes:
|
||||
- id: "rhel84"
|
||||
display_name: "RHEL 8.4"
|
||||
run_on: "rhel84-small"
|
||||
variables:
|
||||
INSTALL_TOX: true
|
||||
VIRTUALENV: "/opt/python/3.7/bin/python3 -m virtualenv"
|
||||
- id: "rhel76"
|
||||
display_name: "RHEL 7.6"
|
||||
run_on: "rhel76-small"
|
||||
variables:
|
||||
INSTALL_TOX: true
|
||||
VIRTUALENV: "/opt/python/3.7/bin/python3 -m virtualenv"
|
||||
- id: "win"
|
||||
display_name: "Windows"
|
||||
run_on: "windows-64-vsMulti-small"
|
||||
variables:
|
||||
INSTALL_TOX: true
|
||||
VIRTUALENV: "/cygdrive/c/python/Python37/python.exe -m virtualenv"
|
||||
- id: "macos-1100"
|
||||
display_name: "macOS 11.00"
|
||||
run_on: "macos-1100"
|
||||
variables:
|
||||
INSTALL_TOX: true
|
||||
VIRTUALENV: "/Library/Frameworks/Python.framework/Versions/3.8/bin/python3 -m venv"
|
||||
|
||||
buildvariants:
|
||||
|
||||
@ -994,7 +946,7 @@ buildvariants:
|
||||
# TODO: synchro needs PyMongo's updated SSL test certs,
|
||||
# which may require Motor test suite changes.
|
||||
- os: "*"
|
||||
tox-env: ["synchro37", "synchro312"]
|
||||
tox-env: ["synchro-py37", "synchro-py312"]
|
||||
ssl: "ssl"
|
||||
tasks:
|
||||
- ".rapid"
|
||||
@ -1052,7 +1004,7 @@ buildvariants:
|
||||
|
||||
- matrix_name: "enterprise-auth"
|
||||
display_name: "Enterprise Auth-${tox-env}"
|
||||
matrix_spec: {"tox-env": ["synchro37", "synchro312"], ssl: "ssl"}
|
||||
matrix_spec: {"tox-env": ["synchro-py37", "synchro-py312"], ssl: "ssl"}
|
||||
run_on:
|
||||
- "rhel84-small"
|
||||
tasks:
|
||||
@ -1063,9 +1015,7 @@ buildvariants:
|
||||
run_on:
|
||||
- "rhel84-small"
|
||||
expansions:
|
||||
TOX_ENV: "py3-sphinx-docs"
|
||||
INSTALL_TOX: true
|
||||
VIRTUALENV: "/opt/python/3.7/bin/python3 -m virtualenv"
|
||||
TOX_ENV: "docs"
|
||||
PYTHON_BINARY: "/opt/python/3.7/bin/python3"
|
||||
tasks:
|
||||
- name: "docs"
|
||||
@ -1075,9 +1025,7 @@ buildvariants:
|
||||
run_on:
|
||||
- "rhel84-small"
|
||||
expansions:
|
||||
TOX_ENV: "py3-sphinx-doctest"
|
||||
INSTALL_TOX: true
|
||||
VIRTUALENV: "/opt/python/3.7/bin/python3 -m virtualenv"
|
||||
TOX_ENV: "doctest"
|
||||
PYTHON_BINARY: "/opt/python/3.7/bin/python3"
|
||||
tasks:
|
||||
- name: "doctest"
|
||||
|
||||
@ -26,4 +26,4 @@ export GSSAPI_PRINCIPAL=${PRINCIPAL}
|
||||
export TOX_TESTENV_PASSENV="*"
|
||||
|
||||
# --sitepackages allows use of pykerberos without a test dep.
|
||||
/opt/python/3.7/bin/python3 -m tox -e "$TOX_ENV" --sitepackages -- -x test.test_auth
|
||||
/opt/python/3.7/bin/python3 -m tox -m "$TOX_ENV" --sitepackages -- -x test.test_auth
|
||||
|
||||
@ -6,14 +6,16 @@ set -o errexit # Exit the script with error if any of the commands fail
|
||||
# AUTH Set to enable authentication. Defaults to "noauth"
|
||||
# SSL Set to enable SSL. Defaults to "nossl"
|
||||
# TOX_ENV Tox environment name, e.g. "tornado5-py37"
|
||||
# TOX_BINARY Path to tox executable
|
||||
# INSTALL_TOX Whether to install tox in a virtualenv
|
||||
# PYTHON_BINARY Path to python
|
||||
# VIRTUALENV Path to virtualenv script
|
||||
|
||||
AUTH=${AUTH:-noauth}
|
||||
SSL=${SSL:-nossl}
|
||||
|
||||
if [ -z $PYTHON_BINARY ]; then
|
||||
echo "PYTHON_BINARY is undefined!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$AUTH" != "noauth" ]; then
|
||||
export DB_USER="bob"
|
||||
export DB_PASSWORD="pwd123"
|
||||
@ -24,24 +26,50 @@ if [ "$SSL" != "nossl" ]; then
|
||||
export CA_PEM="$DRIVERS_TOOLS/.evergreen/x509gen/ca.pem"
|
||||
fi
|
||||
|
||||
if [ "$TOX_ENV" = "synchro37" ]; then
|
||||
SETUP_ARGS="-- --check-exclude-patterns"
|
||||
fi
|
||||
|
||||
if [ "${INSTALL_TOX}" = "true" ]; then
|
||||
$VIRTUALENV motorenv
|
||||
set +o xtrace
|
||||
if [ -f motorenv/bin/activate ]; then
|
||||
source motorenv/bin/activate
|
||||
# Usage:
|
||||
# createvirtualenv /path/to/python /output/path/for/venv
|
||||
# * param1: Python binary to use for the virtualenv
|
||||
# * param2: Path to the virtualenv to create
|
||||
createvirtualenv () {
|
||||
PYTHON=$1
|
||||
VENVPATH=$2
|
||||
if $PYTHON -m virtualenv --version; then
|
||||
VIRTUALENV="$PYTHON -m virtualenv"
|
||||
elif $PYTHON -m venv -h > /dev/null; then
|
||||
# System virtualenv might not be compatible with the python3 on our path
|
||||
VIRTUALENV="$PYTHON -m venv"
|
||||
else
|
||||
# Windows.
|
||||
ls -l motorenv
|
||||
source motorenv/Scripts/activate
|
||||
echo "Cannot test without virtualenv"
|
||||
exit 1
|
||||
fi
|
||||
set -o xtrace
|
||||
pip install "tox>=3.18,<4"
|
||||
TOX_BINARY=tox
|
||||
# Workaround for bug in older versions of virtualenv.
|
||||
$VIRTUALENV $VENVPATH || $PYTHON -m venv $VENVPATH
|
||||
if [ "Windows_NT" = "$OS" ]; then
|
||||
# Workaround https://bugs.python.org/issue32451:
|
||||
# mongovenv/Scripts/activate: line 3: $'\r': command not found
|
||||
dos2unix $VENVPATH/Scripts/activate || true
|
||||
. $VENVPATH/Scripts/activate
|
||||
else
|
||||
. $VENVPATH/bin/activate
|
||||
fi
|
||||
|
||||
python -m pip install --upgrade pip
|
||||
python -m pip install --upgrade setuptools wheel tox
|
||||
}
|
||||
|
||||
|
||||
if $PYTHON_BINARY -m tox --version; then
|
||||
run_tox() {
|
||||
$PYTHON_BINARY -m tox -m $TOX_ENV "$@"
|
||||
}
|
||||
else # No toolchain present, set up virtualenv before installing tox
|
||||
createvirtualenv "$PYTHON_BINARY" toxenv
|
||||
trap "deactivate; rm -rf toxenv" EXIT HUP
|
||||
python -m pip install tox
|
||||
run_tox() {
|
||||
python -m tox -m $TOX_ENV "$@"
|
||||
}
|
||||
fi
|
||||
|
||||
# Run the tests, and store the results in Evergreen compatible XUnit XML
|
||||
${TOX_BINARY} -e ${TOX_ENV} ${SETUP_ARGS} "$@"
|
||||
run_tox "${@:1}"
|
||||
|
||||
31
.flake8
Normal file
31
.flake8
Normal file
@ -0,0 +1,31 @@
|
||||
[flake8]
|
||||
max-line-length = 100
|
||||
enable-extensions = G
|
||||
extend-ignore =
|
||||
G200, G202, G001
|
||||
# black adds spaces around ':'
|
||||
E203,
|
||||
# E501 line too long (let black handle line length)
|
||||
E501
|
||||
# B305 `.next()` is not a thing on Python 3. Use the `next()` builtin. For Python 2 compatibility, use `six.next()`.
|
||||
B305
|
||||
per-file-ignores =
|
||||
# F841 local variable 'foo' is assigned to but never used
|
||||
# E731 do not assign a lambda expression, use a def
|
||||
# F811 redefinition of unused 'foo' from line XXX
|
||||
test/*/test_examples.py: F841,E731,F811
|
||||
|
||||
# F811 redefinition of unused 'foo' from line XXX
|
||||
# B011 Do not call assert False since python -O removes these calls. Instead callers should raise AssertionError().
|
||||
|
||||
test/*: F811,B011
|
||||
|
||||
# E402 module level import not at top of file
|
||||
doc/examples/monitoring_example.py: E402
|
||||
|
||||
# F403 'from foo import *' used; unable to detect undefined names
|
||||
# F401 'foo' imported but unused
|
||||
synchro/__init__.py: F403,F401
|
||||
|
||||
# F401 'foo' imported but unused
|
||||
motor/__init__.py: F401
|
||||
118
.github/workflows/test-python.yml
vendored
118
.github/workflows/test-python.yml
vendored
@ -4,55 +4,34 @@ on:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
concurrency:
|
||||
group: tests-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash -eux {0}
|
||||
|
||||
jobs:
|
||||
|
||||
pre-commit:
|
||||
name: pre-commit
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2
|
||||
- uses: pre-commit/action@v2.0.0
|
||||
with:
|
||||
extra_args: --all-files --hook-stage=manual
|
||||
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 10
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-20.04]
|
||||
python-version: ["3.7", "3.11"]
|
||||
python-version: ["3.7", "3.12"]
|
||||
fail-fast: false
|
||||
name: CPython ${{ matrix.python-version }}-${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
cache: 'pip'
|
||||
cache-dependency-path: 'setup.py'
|
||||
- name: Start MongoDB with Custom Options
|
||||
run: |
|
||||
mkdir data
|
||||
mongod --fork --dbpath=$(pwd)/data --logpath=$PWD/mongo.log --setParameter enableTestCommands=1
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
python -m pip install -U pip tox tox-gh-actions setuptools
|
||||
- name: Run tests
|
||||
run: |
|
||||
tox
|
||||
|
||||
docs:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.7
|
||||
cache: 'pip'
|
||||
cache-dependency-path: 'setup.py'
|
||||
cache-dependency-path: 'pyproject.toml'
|
||||
allow-prereleases: true
|
||||
- name: Start MongoDB with Custom Options
|
||||
run: |
|
||||
mkdir data
|
||||
@ -60,30 +39,85 @@ jobs:
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
python -m pip install -U pip tox
|
||||
- name: Run docs
|
||||
- name: Run tests
|
||||
run: |
|
||||
tox -e py3-sphinx-docs
|
||||
tox -e py3-sphinx-doctest
|
||||
tox -e py3-sphinx-linkcheck
|
||||
tox -m test
|
||||
|
||||
lint:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: 3.8
|
||||
cache: 'pip'
|
||||
cache-dependency-path: 'pyproject.toml'
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
python -m pip install -U pip tox
|
||||
- name: Run linters
|
||||
run: |
|
||||
tox -m lint-manual
|
||||
tox -m manifest
|
||||
|
||||
docs:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: 3.7
|
||||
cache: 'pip'
|
||||
cache-dependency-path: 'pyproject.toml'
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
python -m pip install -U pip tox
|
||||
- name: Run docs
|
||||
run: tox -m docs
|
||||
- name: Run linkcheck
|
||||
run: tox -m linkcheck
|
||||
- name: Start MongoDB with Custom Options
|
||||
run: |
|
||||
mkdir data
|
||||
mongod --fork --dbpath=$(pwd)/data --logpath=$PWD/mongo.log --setParameter enableTestCommands=1
|
||||
- name: Run doctest
|
||||
run: tox -m doctest
|
||||
|
||||
release:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: 3.7
|
||||
cache: 'pip'
|
||||
cache-dependency-path: 'pyproject.toml'
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
python -m pip install -U pip
|
||||
- name: Run the release script
|
||||
run: |
|
||||
bash release.sh
|
||||
|
||||
typing:
|
||||
name: Typing Tests
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ['3.7', '3.11']
|
||||
python-version: ['3.7', '3.12']
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v2
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
cache: 'pip'
|
||||
cache-dependency-path: 'setup.py'
|
||||
cache-dependency-path: 'pyproject.toml'
|
||||
allow-prereleases: true
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install -U pip tox
|
||||
- name: Run mypy
|
||||
run: |
|
||||
tox -e typecheck-mypy
|
||||
tox -m typecheck-mypy
|
||||
|
||||
@ -29,14 +29,14 @@ Control how the tests connect to MongoDB with these environment variables:
|
||||
|
||||
Install `tox`_ and run it from the command line in the repository directory.
|
||||
You will need a variety of Python interpreters installed. For a minimal test,
|
||||
ensure you have Python 3.9, and run::
|
||||
ensure you have your desired Python version on your path, and run::
|
||||
|
||||
> tox -e asyncio-py39
|
||||
> tox -m test
|
||||
|
||||
The doctests pass with Python 3.7 and a MongoDB 5.0 instance running on
|
||||
The doctests pass with Python 3.7+ and a MongoDB 5.0 instance running on
|
||||
port 27017:
|
||||
|
||||
> tox -e py3-sphinx-doctest
|
||||
> tox -m doctest
|
||||
|
||||
.. _tox: https://testrun.org/tox/
|
||||
|
||||
@ -55,7 +55,7 @@ To set up ``pre-commit`` locally, run::
|
||||
|
||||
To run ``pre-commit`` manually, run::
|
||||
|
||||
> tox -e lint
|
||||
> tox -m lint
|
||||
|
||||
General Guidelines
|
||||
------------------
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
include README.rst
|
||||
include LICENSE
|
||||
include tox.ini
|
||||
include pytest.ini
|
||||
include pyproject.toml
|
||||
include mypy.ini
|
||||
include doc/Makefile
|
||||
include doc/examples/tornado_change_stream_templates/index.html
|
||||
@ -17,12 +19,13 @@ recursive-include doc *.bat
|
||||
recursive-include synchro *.py
|
||||
recursive-include motor *.pyi
|
||||
recursive-include motor *.typed
|
||||
recursive-include motor *.py
|
||||
|
||||
exclude .flake8
|
||||
exclude .readthedocs.yaml
|
||||
exclude .git-blame-ignore-revs
|
||||
exclude .pre-commit-config.yaml
|
||||
exclude release.sh
|
||||
exclude ez_setup.py
|
||||
exclude RELEASE.rst
|
||||
exclude CONTRIBUTING.rst
|
||||
exclude .evergreen/*
|
||||
|
||||
@ -32,9 +32,9 @@ and a `source distribution <https://packaging.python.org/guides/distributing-pac
|
||||
#. Add release notes to `doc/changelog.rst`. Generally just summarize/clarify
|
||||
the git log, but you might add some more long form notes for big changes.
|
||||
|
||||
#. Search and replace the `devN` version number w/ the new version number (see
|
||||
#. Replace the `devN` version number w/ the new version number (see
|
||||
note above in `Versioning`_). Make sure version number is updated in
|
||||
`setup.py` and `motor/__init__.py`. Commit the change and tag the release.
|
||||
``motor/_version.py``. Commit the change and tag the release.
|
||||
Immediately bump the version number to `dev0` in a new commit::
|
||||
|
||||
$ # Bump to release version number
|
||||
@ -67,7 +67,7 @@ and a `source distribution <https://packaging.python.org/guides/distributing-pac
|
||||
new version does not show up automatically, trigger a rebuild of "latest":
|
||||
https://readthedocs.org/projects/motor/builds/
|
||||
|
||||
#. Bump the version number to <next version>.dev0 in setup.py/__init__.py,
|
||||
#. Bump the version number to <next version>.dev0 in motor/_version.py,
|
||||
commit, push.
|
||||
|
||||
#. Publish the release version in Jira.
|
||||
|
||||
447
ez_setup.py
447
ez_setup.py
@ -1,447 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Setuptools bootstrapping installer.
|
||||
|
||||
Maintained at https://github.com/pypa/setuptools/tree/bootstrap.
|
||||
|
||||
Run this script to install or upgrade setuptools.
|
||||
"""
|
||||
|
||||
import codecs
|
||||
import contextlib
|
||||
import json
|
||||
import optparse
|
||||
import os
|
||||
import platform
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import textwrap
|
||||
import zipfile
|
||||
from distutils import log
|
||||
|
||||
try:
|
||||
from urllib.parse import urljoin
|
||||
from urllib.request import urlopen
|
||||
except ImportError:
|
||||
from urllib2 import urlopen
|
||||
from urlparse import urljoin
|
||||
|
||||
try:
|
||||
from site import USER_SITE
|
||||
except ImportError:
|
||||
USER_SITE = None
|
||||
|
||||
LATEST = object()
|
||||
DEFAULT_VERSION = LATEST
|
||||
DEFAULT_URL = "https://pypi.io/packages/source/s/setuptools/"
|
||||
DEFAULT_SAVE_DIR = os.curdir
|
||||
|
||||
|
||||
def _python_cmd(*args):
|
||||
"""
|
||||
Execute a command.
|
||||
|
||||
Return True if the command succeeded.
|
||||
"""
|
||||
args = (sys.executable,) + args
|
||||
return subprocess.call(args) == 0
|
||||
|
||||
|
||||
def _install(archive_filename, install_args=()):
|
||||
"""Install Setuptools."""
|
||||
with archive_context(archive_filename):
|
||||
# installing
|
||||
log.warning("Installing Setuptools")
|
||||
if not _python_cmd("setup.py", "install", *install_args):
|
||||
log.warning("Something went wrong during the installation.")
|
||||
log.warning("See the error message above.")
|
||||
# exitcode will be 2
|
||||
return 2
|
||||
|
||||
|
||||
def _build_egg(egg, archive_filename, to_dir):
|
||||
"""Build Setuptools egg."""
|
||||
with archive_context(archive_filename):
|
||||
# building an egg
|
||||
log.warning("Building a Setuptools egg in %s", to_dir)
|
||||
_python_cmd("setup.py", "-q", "bdist_egg", "--dist-dir", to_dir)
|
||||
# returning the result
|
||||
log.warning(egg)
|
||||
if not os.path.exists(egg):
|
||||
raise IOError("Could not build the egg.")
|
||||
|
||||
|
||||
class ContextualZipFile(zipfile.ZipFile):
|
||||
|
||||
"""Supplement ZipFile class to support context manager for Python 2.6."""
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, type, value, traceback):
|
||||
self.close()
|
||||
|
||||
def __new__(cls, *args, **kwargs):
|
||||
"""Construct a ZipFile or ContextualZipFile as appropriate."""
|
||||
if hasattr(zipfile.ZipFile, "__exit__"):
|
||||
return zipfile.ZipFile(*args, **kwargs)
|
||||
return super().__new__(cls)
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def archive_context(filename):
|
||||
"""
|
||||
Unzip filename to a temporary directory, set to the cwd.
|
||||
|
||||
The unzipped target is cleaned up after.
|
||||
"""
|
||||
tmpdir = tempfile.mkdtemp()
|
||||
log.warning("Extracting in %s", tmpdir)
|
||||
old_wd = os.getcwd()
|
||||
try:
|
||||
os.chdir(tmpdir)
|
||||
with ContextualZipFile(filename) as archive:
|
||||
archive.extractall()
|
||||
|
||||
# going in the directory
|
||||
subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
|
||||
os.chdir(subdir)
|
||||
log.warning("Now working in %s", subdir)
|
||||
yield
|
||||
|
||||
finally:
|
||||
os.chdir(old_wd)
|
||||
shutil.rmtree(tmpdir)
|
||||
|
||||
|
||||
def _do_download(version, download_base, to_dir, download_delay):
|
||||
"""Download Setuptools."""
|
||||
py_desig = "py{sys.version_info[0]}.{sys.version_info[1]}".format(sys=sys)
|
||||
tp = "setuptools-{version}-{py_desig}.egg"
|
||||
egg = os.path.join(to_dir, tp.format(**locals()))
|
||||
if not os.path.exists(egg):
|
||||
archive = download_setuptools(version, download_base, to_dir, download_delay)
|
||||
_build_egg(egg, archive, to_dir)
|
||||
sys.path.insert(0, egg)
|
||||
|
||||
# Remove previously-imported pkg_resources if present (see
|
||||
# https://bitbucket.org/pypa/setuptools/pull-request/7/ for details).
|
||||
if "pkg_resources" in sys.modules:
|
||||
_unload_pkg_resources()
|
||||
|
||||
import setuptools
|
||||
|
||||
setuptools.bootstrap_install_from = egg
|
||||
|
||||
|
||||
def use_setuptools(
|
||||
version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=DEFAULT_SAVE_DIR, download_delay=15
|
||||
):
|
||||
"""
|
||||
Ensure that a setuptools version is installed.
|
||||
|
||||
Return None. Raise SystemExit if the requested version
|
||||
or later cannot be installed.
|
||||
"""
|
||||
version = _resolve_version(version)
|
||||
to_dir = os.path.abspath(to_dir)
|
||||
|
||||
# prior to importing, capture the module state for
|
||||
# representative modules.
|
||||
rep_modules = "pkg_resources", "setuptools"
|
||||
imported = set(sys.modules).intersection(rep_modules)
|
||||
|
||||
try:
|
||||
import pkg_resources
|
||||
|
||||
pkg_resources.require("setuptools>=" + version)
|
||||
# a suitable version is already installed
|
||||
return
|
||||
except ImportError:
|
||||
# pkg_resources not available; setuptools is not installed; download
|
||||
pass
|
||||
except pkg_resources.DistributionNotFound:
|
||||
# no version of setuptools was found; allow download
|
||||
pass
|
||||
except pkg_resources.VersionConflict as VC_err:
|
||||
if imported:
|
||||
_conflict_bail(VC_err, version)
|
||||
|
||||
# otherwise, unload pkg_resources to allow the downloaded version to
|
||||
# take precedence.
|
||||
del pkg_resources
|
||||
_unload_pkg_resources()
|
||||
|
||||
return _do_download(version, download_base, to_dir, download_delay)
|
||||
|
||||
|
||||
def _conflict_bail(VC_err, version):
|
||||
"""
|
||||
Setuptools was imported prior to invocation, so it is
|
||||
unsafe to unload it. Bail out.
|
||||
"""
|
||||
conflict_tmpl = textwrap.dedent(
|
||||
"""
|
||||
The required version of setuptools (>={version}) is not available,
|
||||
and can't be installed while this script is running. Please
|
||||
install a more recent version first, using
|
||||
'easy_install -U setuptools'.
|
||||
|
||||
(Currently using {VC_err.args[0]!r})
|
||||
"""
|
||||
)
|
||||
msg = conflict_tmpl.format(**locals())
|
||||
sys.stderr.write(msg)
|
||||
sys.exit(2)
|
||||
|
||||
|
||||
def _unload_pkg_resources():
|
||||
sys.meta_path = [
|
||||
importer
|
||||
for importer in sys.meta_path
|
||||
if importer.__class__.__module__ != "pkg_resources.extern"
|
||||
]
|
||||
del_modules = [name for name in sys.modules if name.startswith("pkg_resources")]
|
||||
for mod_name in del_modules:
|
||||
del sys.modules[mod_name]
|
||||
|
||||
|
||||
def _clean_check(cmd, target):
|
||||
"""
|
||||
Run the command to download target.
|
||||
|
||||
If the command fails, clean up before re-raising the error.
|
||||
"""
|
||||
try:
|
||||
subprocess.check_call(cmd)
|
||||
except subprocess.CalledProcessError:
|
||||
if os.access(target, os.F_OK):
|
||||
os.unlink(target)
|
||||
raise
|
||||
|
||||
|
||||
def download_file_powershell(url, target):
|
||||
"""
|
||||
Download the file at url to target using Powershell.
|
||||
|
||||
Powershell will validate trust.
|
||||
Raise an exception if the command cannot complete.
|
||||
"""
|
||||
target = os.path.abspath(target)
|
||||
ps_cmd = (
|
||||
"[System.Net.WebRequest]::DefaultWebProxy.Credentials = "
|
||||
"[System.Net.CredentialCache]::DefaultCredentials; "
|
||||
'(new-object System.Net.WebClient).DownloadFile("%(url)s", "%(target)s")' % locals()
|
||||
)
|
||||
cmd = [
|
||||
"powershell",
|
||||
"-Command",
|
||||
ps_cmd,
|
||||
]
|
||||
_clean_check(cmd, target)
|
||||
|
||||
|
||||
def has_powershell():
|
||||
"""Determine if Powershell is available."""
|
||||
if platform.system() != "Windows":
|
||||
return False
|
||||
cmd = ["powershell", "-Command", "echo test"]
|
||||
with open(os.path.devnull, "wb") as devnull:
|
||||
try:
|
||||
subprocess.check_call(cmd, stdout=devnull, stderr=devnull)
|
||||
except Exception:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
download_file_powershell.viable = has_powershell
|
||||
|
||||
|
||||
def download_file_curl(url, target):
|
||||
cmd = ["curl", url, "--location", "--silent", "--output", target]
|
||||
_clean_check(cmd, target)
|
||||
|
||||
|
||||
def has_curl():
|
||||
cmd = ["curl", "--version"]
|
||||
with open(os.path.devnull, "wb") as devnull:
|
||||
try:
|
||||
subprocess.check_call(cmd, stdout=devnull, stderr=devnull)
|
||||
except Exception:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
download_file_curl.viable = has_curl
|
||||
|
||||
|
||||
def download_file_wget(url, target):
|
||||
cmd = ["wget", url, "--quiet", "--output-document", target]
|
||||
_clean_check(cmd, target)
|
||||
|
||||
|
||||
def has_wget():
|
||||
cmd = ["wget", "--version"]
|
||||
with open(os.path.devnull, "wb") as devnull:
|
||||
try:
|
||||
subprocess.check_call(cmd, stdout=devnull, stderr=devnull)
|
||||
except Exception:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
download_file_wget.viable = has_wget
|
||||
|
||||
|
||||
def download_file_insecure(url, target):
|
||||
"""Use Python to download the file, without connection authentication."""
|
||||
src = urlopen(url)
|
||||
try:
|
||||
# Read all the data in one block.
|
||||
data = src.read()
|
||||
finally:
|
||||
src.close()
|
||||
|
||||
# Write all the data in one block to avoid creating a partial file.
|
||||
with open(target, "wb") as dst:
|
||||
dst.write(data)
|
||||
|
||||
|
||||
download_file_insecure.viable = lambda: True
|
||||
|
||||
|
||||
def get_best_downloader():
|
||||
downloaders = (
|
||||
download_file_powershell,
|
||||
download_file_curl,
|
||||
download_file_wget,
|
||||
download_file_insecure,
|
||||
)
|
||||
viable_downloaders = (dl for dl in downloaders if dl.viable())
|
||||
return next(viable_downloaders, None)
|
||||
|
||||
|
||||
def download_setuptools(
|
||||
version=DEFAULT_VERSION,
|
||||
download_base=DEFAULT_URL,
|
||||
to_dir=DEFAULT_SAVE_DIR,
|
||||
delay=15,
|
||||
downloader_factory=get_best_downloader,
|
||||
):
|
||||
"""
|
||||
Download setuptools from a specified location and return its filename.
|
||||
|
||||
`version` should be a valid setuptools version number that is available
|
||||
as an sdist for download under the `download_base` URL (which should end
|
||||
with a '/'). `to_dir` is the directory where the egg will be downloaded.
|
||||
`delay` is the number of seconds to pause before an actual download
|
||||
attempt.
|
||||
|
||||
``downloader_factory`` should be a function taking no arguments and
|
||||
returning a function for downloading a URL to a target.
|
||||
"""
|
||||
version = _resolve_version(version)
|
||||
# making sure we use the absolute path
|
||||
to_dir = os.path.abspath(to_dir)
|
||||
zip_name = "setuptools-%s.zip" % version
|
||||
url = download_base + zip_name
|
||||
saveto = os.path.join(to_dir, zip_name)
|
||||
if not os.path.exists(saveto): # Avoid repeated downloads
|
||||
log.warning("Downloading %s", url)
|
||||
downloader = downloader_factory()
|
||||
downloader(url, saveto)
|
||||
return os.path.realpath(saveto)
|
||||
|
||||
|
||||
def _resolve_version(version):
|
||||
"""
|
||||
Resolve LATEST version
|
||||
"""
|
||||
if version is not LATEST:
|
||||
return version
|
||||
|
||||
meta_url = urljoin(DEFAULT_URL, "/pypi/setuptools/json")
|
||||
resp = urlopen(meta_url)
|
||||
with contextlib.closing(resp):
|
||||
try:
|
||||
charset = resp.info().get_content_charset()
|
||||
except Exception:
|
||||
# Python 2 compat; assume UTF-8
|
||||
charset = "UTF-8"
|
||||
reader = codecs.getreader(charset)
|
||||
doc = json.load(reader(resp))
|
||||
|
||||
return str(doc["info"]["version"])
|
||||
|
||||
|
||||
def _build_install_args(options):
|
||||
"""
|
||||
Build the arguments to 'python setup.py install' on the setuptools package.
|
||||
|
||||
Returns list of command line arguments.
|
||||
"""
|
||||
return ["--user"] if options.user_install else []
|
||||
|
||||
|
||||
def _parse_args():
|
||||
"""Parse the command line for options."""
|
||||
parser = optparse.OptionParser()
|
||||
parser.add_option(
|
||||
"--user",
|
||||
dest="user_install",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="install in user site package",
|
||||
)
|
||||
parser.add_option(
|
||||
"--download-base",
|
||||
dest="download_base",
|
||||
metavar="URL",
|
||||
default=DEFAULT_URL,
|
||||
help="alternative URL from where to download the setuptools package",
|
||||
)
|
||||
parser.add_option(
|
||||
"--insecure",
|
||||
dest="downloader_factory",
|
||||
action="store_const",
|
||||
const=lambda: download_file_insecure,
|
||||
default=get_best_downloader,
|
||||
help="Use internal, non-validating downloader",
|
||||
)
|
||||
parser.add_option(
|
||||
"--version",
|
||||
help="Specify which version to download",
|
||||
default=DEFAULT_VERSION,
|
||||
)
|
||||
parser.add_option(
|
||||
"--to-dir",
|
||||
help="Directory to save (and re-use) package",
|
||||
default=DEFAULT_SAVE_DIR,
|
||||
)
|
||||
options, args = parser.parse_args()
|
||||
# positional arguments are ignored
|
||||
return options
|
||||
|
||||
|
||||
def _download_args(options):
|
||||
"""Return args for download_setuptools function from cmdline args."""
|
||||
return dict(
|
||||
version=options.version,
|
||||
download_base=options.download_base,
|
||||
downloader_factory=options.downloader_factory,
|
||||
to_dir=options.to_dir,
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
"""Install or upgrade setuptools and EasyInstall."""
|
||||
options = _parse_args()
|
||||
archive = download_setuptools(**_download_args(options))
|
||||
return _install(archive, _build_install_args(options))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@ -1325,14 +1325,14 @@ class AgnosticCollection(AgnosticBaseProperties):
|
||||
# Latent cursor that will send initial command on first "async for".
|
||||
return cursor_class(self, self._async_list_indexes, session=session, **kwargs)
|
||||
|
||||
def _list_search_indexes(self, session=None, **kwargs):
|
||||
def _list_search_indexes(self, *args, **kwargs):
|
||||
"""Return a cursor over search indexes for the current collection."""
|
||||
cursor_class = create_class_with_framework(
|
||||
AgnosticLatentCommandCursor, self._framework, self.__module__
|
||||
)
|
||||
|
||||
# Latent cursor that will send initial command on first "async for".
|
||||
return cursor_class(self, self._async_list_search_indexes, session=session, **kwargs)
|
||||
return cursor_class(self, self._async_list_search_indexes, *args, **kwargs)
|
||||
|
||||
# TODO: MOTOR-1169
|
||||
if hasattr(Collection, "list_search_indexes"):
|
||||
|
||||
82
pyproject.toml
Normal file
82
pyproject.toml
Normal file
@ -0,0 +1,82 @@
|
||||
[build-system]
|
||||
requires = ["setuptools>61.0"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "motor"
|
||||
dynamic = ["version"]
|
||||
description = "Non-blocking MongoDB driver for Tornado or asyncio"
|
||||
readme = "README.rst"
|
||||
license = { file = "LICENSE" }
|
||||
requires-python = ">=3.7"
|
||||
authors = [
|
||||
{ name = "A. Jesse Jiryu Davis", email = "jesse@mongodb.com" },
|
||||
]
|
||||
keywords = [
|
||||
"asyncio",
|
||||
"bson",
|
||||
"gridfs",
|
||||
"mongo",
|
||||
"mongodb",
|
||||
"motor",
|
||||
"pymongo",
|
||||
"tornado",
|
||||
]
|
||||
classifiers = [
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
"Intended Audience :: Developers",
|
||||
"License :: OSI Approved :: Apache Software License",
|
||||
"Natural Language :: English",
|
||||
"Operating System :: MacOS :: MacOS X",
|
||||
"Operating System :: Microsoft :: Windows",
|
||||
"Operating System :: Unix",
|
||||
"Typing :: Typed",
|
||||
"Programming Language :: Python",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.7",
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: Implementation :: CPython",
|
||||
"Programming Language :: Python :: Implementation :: PyPy",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
]
|
||||
dependencies = [
|
||||
"pymongo>=4.4,<5",
|
||||
]
|
||||
|
||||
[project.optional-dependencies]
|
||||
aws = [
|
||||
"pymongo[aws]>=4.4,<5",
|
||||
]
|
||||
encryption = [
|
||||
"pymongo[encryption]>=4.4,<5",
|
||||
]
|
||||
gssapi = [
|
||||
"pymongo[gssapi]>=4.4,<5",
|
||||
]
|
||||
ocsp = [
|
||||
"pymongo[ocsp]>=4.4,<5",
|
||||
]
|
||||
snappy = [
|
||||
"pymongo[snappy]>=4.4,<5",
|
||||
]
|
||||
srv = [
|
||||
"pymongo[srv]>=4.4,<5",
|
||||
]
|
||||
test = [
|
||||
"pytest>=7", "mockupdb", "tornado>=5", "aiohttp", "motor[encryption]"
|
||||
]
|
||||
zstd = [
|
||||
"pymongo[zstd]>=4.4,<5",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
Homepage = "https://github.com/mongodb/motor/"
|
||||
|
||||
[tool.setuptools.dynamic]
|
||||
version = {attr = "motor._version.version"}
|
||||
|
||||
[tool.setuptools.packages.find]
|
||||
include = ["motor"]
|
||||
15
pytest.ini
Normal file
15
pytest.ini
Normal file
@ -0,0 +1,15 @@
|
||||
[pytest]
|
||||
testpaths =
|
||||
test
|
||||
addopts = -ra --junitxml=xunit-results/TEST-results.xml
|
||||
filterwarnings =
|
||||
error
|
||||
ignore:Bare functions are deprecated, use async ones:DeprecationWarning
|
||||
ignore:Application.make_handler:DeprecationWarning
|
||||
ignore:unclosed <socket.socket:ResourceWarning
|
||||
ignore:unclosed event loop:ResourceWarning
|
||||
ignore: The fetch_next property is deprecated:DeprecationWarning
|
||||
ignore:The next_object method is deprecated:DeprecationWarning
|
||||
ignore:unclosed <ssl.SSLSocket:ResourceWarning
|
||||
ignore:datetime.utcfromtimestamp:DeprecationWarning
|
||||
ignore:datetime.utcnow:DeprecationWarning
|
||||
15
release.sh
15
release.sh
@ -8,22 +8,15 @@
|
||||
set -o xtrace # Write all commands first to stderr
|
||||
set -o errexit # Exit the script with error if any of the commands fail
|
||||
|
||||
# Only build distributions with Python 3.5.2 or later.
|
||||
python3 -c "import sys; exit(sys.version_info < (3, 5, 2))"
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ERROR: Run this script with Python 3.5.2 or later."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Cleanup destinations
|
||||
rm -rf build
|
||||
rm -rf dist
|
||||
|
||||
# Build the source dist first
|
||||
python3 setup.py sdist
|
||||
# Install deps
|
||||
python3 -m pip install build
|
||||
|
||||
# Build the wheel
|
||||
python3 setup.py bdist_wheel
|
||||
# Build the source dist and wheel
|
||||
python3 -m build .
|
||||
|
||||
# Cleanup
|
||||
rm -rf build
|
||||
|
||||
192
setup.py
192
setup.py
@ -1,193 +1,3 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
if sys.version_info[:2] < (3, 10):
|
||||
from distutils.cmd import Command
|
||||
from distutils.errors import DistutilsOptionError as OptionError
|
||||
else:
|
||||
from setuptools import Command
|
||||
from setuptools.errors import OptionError
|
||||
|
||||
|
||||
from setuptools import setup
|
||||
|
||||
if sys.version_info[:2] < (3, 7):
|
||||
raise Exception("This version of Motor requires Python>=3.7")
|
||||
|
||||
classifiers = """\
|
||||
Intended Audience :: Developers
|
||||
License :: OSI Approved :: Apache Software License
|
||||
Development Status :: 5 - Production/Stable
|
||||
Natural Language :: English
|
||||
Programming Language :: Python :: 3
|
||||
Programming Language :: Python :: 3.7
|
||||
Programming Language :: Python :: 3.8
|
||||
Programming Language :: Python :: 3.9
|
||||
Programming Language :: Python :: 3.10
|
||||
Programming Language :: Python :: 3.11
|
||||
Operating System :: MacOS :: MacOS X
|
||||
Operating System :: Unix
|
||||
Operating System :: Microsoft :: Windows
|
||||
Programming Language :: Python
|
||||
Programming Language :: Python :: Implementation :: CPython
|
||||
Programming Language :: Python :: Implementation :: PyPy
|
||||
Typing :: Typed
|
||||
"""
|
||||
|
||||
description = "Non-blocking MongoDB driver for Tornado or asyncio"
|
||||
|
||||
with open("README.rst") as readme:
|
||||
long_description = readme.read()
|
||||
|
||||
pymongo_ver = ">=4.4,<5"
|
||||
|
||||
install_requires = ["pymongo" + pymongo_ver]
|
||||
|
||||
extras_require = {
|
||||
"encryption": ["pymongo[encryption]" + pymongo_ver],
|
||||
"ocsp": ["pymongo[ocsp]" + pymongo_ver],
|
||||
"snappy": ["pymongo[snappy]" + pymongo_ver],
|
||||
"zstd": ["pymongo[zstd]" + pymongo_ver],
|
||||
"aws": ["pymongo[aws]" + pymongo_ver],
|
||||
"srv": ["pymongo[srv]" + pymongo_ver],
|
||||
"gssapi": ["pymongo[gssapi]" + pymongo_ver],
|
||||
}
|
||||
|
||||
tests_require = ["mockupdb>=1.4.0"]
|
||||
|
||||
|
||||
class test(Command):
|
||||
description = "run the tests"
|
||||
|
||||
user_options = [
|
||||
("test-module=", "m", "Discover tests in specified module"),
|
||||
("test-suite=", "s", "Test suite to run (e.g. 'some_module.test_suite')"),
|
||||
("failfast", "f", "Stop running tests on first failure or error"),
|
||||
("tornado-warnings", "w", "Let Tornado log warnings"),
|
||||
("xunit-output=", "x", "Generate a results directory with XUnit XML format"),
|
||||
]
|
||||
|
||||
def initialize_options(self):
|
||||
self.test_module = None
|
||||
self.test_suite = None
|
||||
self.failfast = False
|
||||
self.tornado_warnings = False
|
||||
self.xunit_output = None
|
||||
|
||||
def finalize_options(self):
|
||||
if self.test_suite is None and self.test_module is None:
|
||||
self.test_module = "test"
|
||||
elif self.test_module is not None and self.test_suite is not None:
|
||||
raise OptionError("You may specify a module or suite, but not both")
|
||||
|
||||
def run(self):
|
||||
# Installing required packages, running egg_info and build_ext are
|
||||
# part of normal operation for setuptools.command.test.test. Motor
|
||||
# has no extensions so build_ext is a no-op.
|
||||
if self.distribution.install_requires:
|
||||
self.distribution.fetch_build_eggs(self.distribution.install_requires)
|
||||
if self.distribution.tests_require:
|
||||
self.distribution.fetch_build_eggs(self.distribution.tests_require)
|
||||
if self.xunit_output:
|
||||
self.distribution.fetch_build_eggs(["unittest-xml-reporting>=1.14.0,<2.0.0a0"])
|
||||
self.run_command("egg_info")
|
||||
build_ext_cmd = self.reinitialize_command("build_ext")
|
||||
build_ext_cmd.inplace = 1
|
||||
self.run_command("build_ext")
|
||||
|
||||
from test import MotorTestLoader, env, suppress_tornado_warnings
|
||||
from test import test_environment as testenv
|
||||
|
||||
loader = MotorTestLoader()
|
||||
loader.avoid("high_availability", reason="Runs separately")
|
||||
|
||||
if not (testenv.HAVE_ASYNCIO or testenv.HAVE_TORNADO):
|
||||
raise ImportError("No tornado nor asyncio")
|
||||
elif not testenv.HAVE_TORNADO:
|
||||
loader.avoid("tornado_tests", reason="no tornado")
|
||||
elif not testenv.HAVE_ASYNCIO:
|
||||
loader.avoid("asyncio_tests", reason="no asyncio")
|
||||
|
||||
if not testenv.HAVE_AIOHTTP:
|
||||
loader.avoid("asyncio_tests.test_aiohttp_gridfs", reason="no aiohttp")
|
||||
|
||||
# Decide if we can run async / await tests with Tornado.
|
||||
if not testenv.HAVE_TORNADO:
|
||||
test_motor_await = "tornado_tests.test_motor_await"
|
||||
loader.avoid(test_motor_await, reason="no tornado")
|
||||
|
||||
if self.test_suite is None:
|
||||
suite = loader.discover(self.test_module)
|
||||
else:
|
||||
suite = loader.loadTestsFromName(self.test_suite)
|
||||
|
||||
runner_kwargs = dict(verbosity=2, failfast=self.failfast)
|
||||
|
||||
if self.xunit_output:
|
||||
try:
|
||||
from xmlrunner import XMLTestRunner
|
||||
except ImportError:
|
||||
self.xunit_output = False
|
||||
else:
|
||||
runner_kwargs["output"] = self.xunit_output
|
||||
runner_class = XMLTestRunner
|
||||
|
||||
if not self.xunit_output:
|
||||
import unittest
|
||||
|
||||
runner_class = unittest.TextTestRunner
|
||||
|
||||
runner = runner_class(**runner_kwargs)
|
||||
if "SKIP_ENV_SETUP" not in os.environ:
|
||||
env.setup()
|
||||
if not self.tornado_warnings:
|
||||
suppress_tornado_warnings()
|
||||
|
||||
result = runner.run(suite)
|
||||
sys.exit(not result.wasSuccessful())
|
||||
|
||||
|
||||
packages = [
|
||||
"motor",
|
||||
"motor.frameworks",
|
||||
"motor.frameworks.tornado",
|
||||
"motor.frameworks.asyncio",
|
||||
"motor.aiohttp",
|
||||
]
|
||||
|
||||
|
||||
version_ns = {}
|
||||
with open("motor/_version.py") as fp:
|
||||
exec(fp.read(), version_ns)
|
||||
version = version_ns["version"]
|
||||
|
||||
|
||||
setup(
|
||||
name="motor",
|
||||
version=version,
|
||||
packages=packages,
|
||||
description=description,
|
||||
long_description=long_description,
|
||||
author="A. Jesse Jiryu Davis",
|
||||
author_email="jesse@mongodb.com",
|
||||
url="https://github.com/mongodb/motor/",
|
||||
python_requires=">=3.7",
|
||||
install_requires=install_requires,
|
||||
extras_require=extras_require,
|
||||
license="http://www.apache.org/licenses/LICENSE-2.0",
|
||||
classifiers=[c for c in classifiers.split("\n") if c],
|
||||
keywords=[
|
||||
"mongo",
|
||||
"mongodb",
|
||||
"pymongo",
|
||||
"gridfs",
|
||||
"bson",
|
||||
"motor",
|
||||
"tornado",
|
||||
"asyncio",
|
||||
],
|
||||
tests_require=tests_require,
|
||||
test_suite="test",
|
||||
zip_safe=False,
|
||||
cmdclass={"test": test},
|
||||
)
|
||||
setup()
|
||||
|
||||
@ -490,11 +490,7 @@ class Collection(Synchro):
|
||||
aggregate = WrapOutgoing()
|
||||
aggregate_raw_batches = WrapOutgoing()
|
||||
list_indexes = WrapOutgoing()
|
||||
create_search_index = WrapOutgoing()
|
||||
create_search_indexes = WrapOutgoing()
|
||||
drop_search_index = WrapOutgoing()
|
||||
list_search_indexes = WrapOutgoing()
|
||||
update_search_index = WrapOutgoing()
|
||||
watch = WrapOutgoing()
|
||||
__bool__ = WrapOutgoing()
|
||||
|
||||
|
||||
@ -188,6 +188,8 @@ excluded_tests = [
|
||||
"TestUnifiedPoolClearedError.test_PoolClearedError_does_not_mark_server_unknown",
|
||||
# These tests have hard-coded values that differ from motor.
|
||||
"TestClient.test_handshake.*",
|
||||
# This test is not a valid unittest target.
|
||||
"TestRangeQueryProse.run_test_cases",
|
||||
]
|
||||
|
||||
|
||||
|
||||
@ -14,10 +14,8 @@
|
||||
|
||||
"""Test Motor, an asynchronous driver for MongoDB and Tornado."""
|
||||
|
||||
import logging
|
||||
import unittest
|
||||
from test.test_environment import CLIENT_PEM, db_user, env # noqa: F401
|
||||
from unittest import SkipTest
|
||||
from unittest import SkipTest # noqa: F401
|
||||
|
||||
try:
|
||||
# Enable the fault handler to dump the traceback of each running
|
||||
@ -33,45 +31,6 @@ except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
def suppress_tornado_warnings():
|
||||
for name in ["tornado.general", "tornado.access"]:
|
||||
logger = logging.getLogger(name)
|
||||
logger.setLevel(logging.ERROR)
|
||||
|
||||
|
||||
class SkippedModule(object):
|
||||
def __init__(self, name, reason):
|
||||
def runTest(self):
|
||||
raise SkipTest(str(reason))
|
||||
|
||||
self.test_case = type(str(name), (unittest.TestCase,), {"runTest": runTest})
|
||||
|
||||
|
||||
class MotorTestLoader(unittest.TestLoader):
|
||||
def __init__(self, avoid=None, reason=None):
|
||||
super().__init__()
|
||||
self._avoid = []
|
||||
|
||||
def avoid(self, *prefixes, **kwargs):
|
||||
"""Skip a module.
|
||||
|
||||
The usual "raise SkipTest" from a module doesn't work if the module
|
||||
won't even parse in Python 2, so prevent TestLoader from importing
|
||||
modules with the given prefix.
|
||||
|
||||
"prefix" is a path prefix like "asyncio_tests".
|
||||
"""
|
||||
for prefix in prefixes:
|
||||
self._avoid.append((prefix, kwargs["reason"]))
|
||||
|
||||
def _get_module_from_name(self, name):
|
||||
for prefix, reason in self._avoid:
|
||||
if name.startswith(prefix):
|
||||
return SkippedModule(name, reason)
|
||||
|
||||
return super()._get_module_from_name(name)
|
||||
|
||||
|
||||
class MockRequestHandler(object):
|
||||
"""For testing MotorGridOut.stream_to_handler."""
|
||||
|
||||
|
||||
@ -47,6 +47,8 @@ class TestAsyncIOSSL(unittest.TestCase):
|
||||
self.loop = asyncio.new_event_loop()
|
||||
|
||||
def tearDown(self):
|
||||
if not hasattr(self, "loop"):
|
||||
return
|
||||
self.loop.stop()
|
||||
self.loop.run_forever()
|
||||
self.loop.close()
|
||||
|
||||
@ -104,6 +104,8 @@ def is_server_resolvable():
|
||||
|
||||
|
||||
class TestEnvironment(object):
|
||||
__test__ = False
|
||||
|
||||
def __init__(self):
|
||||
self.initialized = False
|
||||
self.host = None
|
||||
@ -369,3 +371,5 @@ class TestEnvironment(object):
|
||||
|
||||
|
||||
env = TestEnvironment()
|
||||
if "SKIP_ENV_SETUP" not in os.environ:
|
||||
env.setup()
|
||||
|
||||
@ -101,7 +101,8 @@ class MotorTest(testing.AsyncTestCase):
|
||||
|
||||
def tearDown(self):
|
||||
env.sync_cx.motor_test.test_collection.delete_many({})
|
||||
self.cx.close()
|
||||
if hasattr(self, "cx"):
|
||||
self.cx.close()
|
||||
super().tearDown()
|
||||
|
||||
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
# limitations under the License.
|
||||
|
||||
"""Test Motor, an asynchronous driver for MongoDB and Tornado."""
|
||||
import asyncio
|
||||
import os
|
||||
import test
|
||||
import unittest
|
||||
@ -158,6 +159,7 @@ class ExecutorForkTest(MotorTest):
|
||||
parent_conn, child_conn = Pipe()
|
||||
lock_pid = os.fork()
|
||||
if lock_pid == 0: # Child
|
||||
asyncio.set_event_loop(asyncio.new_event_loop())
|
||||
self.loop = IOLoop.current()
|
||||
client = self.motor_client()
|
||||
try:
|
||||
|
||||
@ -191,7 +191,7 @@ class TestTransactionsConvenientAPI(MotorTest):
|
||||
self.assertEqual(
|
||||
listener.started_command_names(), ["insert", "commitTransaction", "commitTransaction"]
|
||||
)
|
||||
self.set_fail_point(client, {"configureFailPoint": "failCommand", "mode": "off"})
|
||||
await self.set_fail_point(client, {"configureFailPoint": "failCommand", "mode": "off"})
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@ -72,6 +72,8 @@ def get_primary_pool(client):
|
||||
|
||||
# Ignore auth commands like saslStart, so we can assert lsid is in all commands.
|
||||
class TestListener(monitoring.CommandListener):
|
||||
__test__ = False
|
||||
|
||||
def __init__(self):
|
||||
self.results = defaultdict(list)
|
||||
|
||||
|
||||
215
tox.ini
215
tox.ini
@ -4,41 +4,45 @@
|
||||
# Adapted from Tornado's tox.ini.
|
||||
|
||||
[tox]
|
||||
requires =
|
||||
tox>=4
|
||||
|
||||
envlist =
|
||||
# Tornado 5 supports Python 3.4+.
|
||||
tornado5-{py37},
|
||||
|
||||
# Tornado 6 supports Python 3.5+.
|
||||
tornado6-{pypy37,py37,py38,py39,py310,py311,py312},
|
||||
|
||||
# Test Tornado's dev version in a few configurations.
|
||||
tornado_git-{py38},
|
||||
|
||||
# Run the unit test suite
|
||||
test
|
||||
# Ensure the sphinx build has no errors or warnings.
|
||||
py3-sphinx-docs,
|
||||
|
||||
docs,
|
||||
# Run the doctests, include examples and tutorial, via Sphinx.
|
||||
py3-sphinx-doctest,
|
||||
|
||||
# asyncio without Tornado.
|
||||
asyncio-{py37,py38,py39,py310,py311,py312},
|
||||
|
||||
doctest,
|
||||
# Check links of sphinx docs
|
||||
linkcheck,
|
||||
# Test with the latest PyMongo.
|
||||
py3-pymongo-latest,
|
||||
|
||||
test-pymongo-latest,
|
||||
# Apply PyMongo's test suite to Motor via Synchro.
|
||||
synchro37
|
||||
synchro312
|
||||
|
||||
synchro
|
||||
# Run pre-commit on all files.
|
||||
lint
|
||||
|
||||
# Run pre-commit on all files with manual checks.
|
||||
lint-manual
|
||||
# Check the sdist integrity.
|
||||
manifest
|
||||
|
||||
# Typecheck with mypy
|
||||
typecheck-mypy
|
||||
|
||||
|
||||
labels = # Use labels and -m instead of -e so that tox -m <label> fails instantly if the label does not exist
|
||||
test = test
|
||||
docs = docs
|
||||
doctest = doctest
|
||||
checklink = checklink
|
||||
test-pymongo-latest = test-pymongo-latest
|
||||
synchro = synchro
|
||||
lint = lint
|
||||
lint-manual = lint-manual
|
||||
linkcheck = linkcheck
|
||||
manifest = manifest
|
||||
typecheck-mypy = typecheck-mypy
|
||||
|
||||
[testenv]
|
||||
passenv =
|
||||
DB_IP
|
||||
@ -54,152 +58,85 @@ passenv =
|
||||
FLE_AZURE_CLIENTSECRET
|
||||
FLE_GCP_EMAIL
|
||||
FLE_GCP_PRIVATEKEY
|
||||
AIOHTTP_NO_EXTENSIONS
|
||||
|
||||
|
||||
basepython =
|
||||
py37: {env:PYTHON_BINARY:python3.7}
|
||||
py38: {env:PYTHON_BINARY:python3.8}
|
||||
py39: {env:PYTHON_BINARY:python3.9}
|
||||
py310: {env:PYTHON_BINARY:python3.10}
|
||||
py311: {env:PYTHON_BINARY:python3.11}
|
||||
py312: {env:PYTHON_BINARY:python3.12}
|
||||
pypy37: {env:PYTHON_BINARY:pypy3}
|
||||
|
||||
synchro37: {env:PYTHON_BINARY:python3.7}
|
||||
synchro312: {env:PYTHON_BINARY:python3.12}
|
||||
|
||||
# Default Python 3 when we don't care about minor version.
|
||||
py3,lint,manifest: {env:PYTHON_BINARY:python3}
|
||||
|
||||
deps =
|
||||
tornado5: tornado>=5,<6
|
||||
tornado6: tornado>=6,<7
|
||||
tornado_git: git+https://github.com/tornadoweb/tornado.git
|
||||
|
||||
{py37,py38,py39,py310,py311}: aiohttp
|
||||
|
||||
py312: setuptools==68.0.0
|
||||
|
||||
sphinx: sphinx
|
||||
sphinx: aiohttp
|
||||
sphinx: tornado
|
||||
|
||||
py3-pymongo-latest: tornado>=5,<6
|
||||
|
||||
synchro37: tornado>=6,<7
|
||||
synchro37: nose
|
||||
synchro37: pytest
|
||||
|
||||
synchro312: tornado>=6,<7
|
||||
synchro312: pynose
|
||||
synchro312: setuptools==68.0.0
|
||||
synchro312: pytest
|
||||
|
||||
pypy37: cryptography<3
|
||||
setenv =
|
||||
PYTHONWARNINGS="error,ignore:The distutils package is deprecated:DeprecationWarning"
|
||||
[testenv:test]
|
||||
# TODO: Remove as part of MOTOR-1163
|
||||
setenv = AIOHTTP_NO_EXTENSIONS=1
|
||||
commands =
|
||||
python --version
|
||||
python setup.py test --xunit-output=xunit-results {posargs}
|
||||
python -m pytest -v {posargs}
|
||||
extras =
|
||||
test
|
||||
|
||||
[testenv:docs]
|
||||
setenv = PYTHONWARNINGS=
|
||||
deps =
|
||||
-rdoc/docs-requirements.txt
|
||||
changedir = doc
|
||||
commands =
|
||||
python -m sphinx -q -E -W -b html . {envtmpdir}/html {posargs}
|
||||
|
||||
[testenv:doctest]
|
||||
setenv = PYTHONHASHSEED=0
|
||||
deps =
|
||||
-rdoc/docs-requirements.txt
|
||||
changedir = doc
|
||||
commands =
|
||||
python -m sphinx -q -E -b doctest . {envtmpdir}/doctest {posargs}
|
||||
|
||||
[testenv:linkcheck]
|
||||
setenv = PYTHONHASHSEED=0
|
||||
deps =
|
||||
-rdoc/docs-requirements.txt
|
||||
changedir = doc
|
||||
commands =
|
||||
python -m sphinx -q -E -b linkcheck . {envtmpdir}/linkcheck {posargs}
|
||||
|
||||
[testenv:test-pymongo-latest]
|
||||
extras =
|
||||
encryption
|
||||
|
||||
[testenv:py3-sphinx-docs]
|
||||
setenv = PYTHONWARNINGS=
|
||||
changedir = doc
|
||||
commands =
|
||||
sphinx-build -q -E -W -b html . {envtmpdir}/html {posargs}
|
||||
|
||||
[testenv:py3-sphinx-doctest]
|
||||
setenv = PYTHONHASHSEED=0
|
||||
changedir = doc
|
||||
commands =
|
||||
sphinx-build -q -E -b doctest . {envtmpdir}/doctest {posargs}
|
||||
|
||||
[testenv:py3-sphinx-linkcheck]
|
||||
setenv = PYTHONHASHSEED=0
|
||||
changedir = doc
|
||||
commands =
|
||||
sphinx-build -q -E -b linkcheck . {envtmpdir}/linkcheck {posargs}
|
||||
|
||||
[testenv:py3-pymongo-latest]
|
||||
test
|
||||
commands =
|
||||
pip install git+https://github.com/mongodb/mongo-python-driver.git@master
|
||||
pip install --pre pymongocrypt
|
||||
python --version
|
||||
python -c "import pymongo; print('PyMongo %s' % (pymongo.version,))"
|
||||
python setup.py test --xunit-output=xunit-results {posargs}
|
||||
python -m pytest -v {posargs}
|
||||
|
||||
[testenv:synchro37]
|
||||
[testenv:synchro]
|
||||
extras =
|
||||
test
|
||||
deps =
|
||||
pynose
|
||||
allowlist_externals =
|
||||
git
|
||||
setenv =
|
||||
PYTHONPATH = {envtmpdir}/mongo-python-driver
|
||||
# TODO: Remove as part of MOTOR-1163
|
||||
AIOHTTP_NO_EXTENSIONS=1
|
||||
commands =
|
||||
git clone --depth 1 --branch master https://github.com/mongodb/mongo-python-driver.git {envtmpdir}/mongo-python-driver
|
||||
python3 -m pip install -e {envtmpdir}/mongo-python-driver
|
||||
python3 -m synchro.synchrotest --with-xunit --xunit-file=xunit-synchro-results -v -w {envtmpdir}/mongo-python-driver {posargs}
|
||||
|
||||
[testenv:synchro312]
|
||||
allowlist_externals =
|
||||
git
|
||||
setenv =
|
||||
PYTHONPATH = {envtmpdir}/mongo-python-driver
|
||||
commands =
|
||||
git clone --depth 1 --branch master https://github.com/mongodb/mongo-python-driver.git {envtmpdir}/mongo-python-driver
|
||||
python3 -m pip install -e {envtmpdir}/mongo-python-driver
|
||||
python3 -m synchro.synchrotest -v -w {envtmpdir}/mongo-python-driver {posargs}
|
||||
|
||||
[testenv:lint]
|
||||
deps =
|
||||
pre-commit
|
||||
commands =
|
||||
pre-commit run --all-files
|
||||
python -m pre_commit run --all-files
|
||||
|
||||
[testenv:lint-manual]
|
||||
deps =
|
||||
pre-commit
|
||||
commands =
|
||||
python -m pre_commit run --all-files --hook-stage=manual
|
||||
|
||||
[testenv:manifest]
|
||||
deps =
|
||||
check-manifest
|
||||
commands =
|
||||
check-manifest -v
|
||||
|
||||
[gh-actions]
|
||||
# Map GitHub Actions python-version to environment using tox-github-actions.
|
||||
python =
|
||||
3.7: py37
|
||||
3.11: py311,manifest
|
||||
|
||||
[flake8]
|
||||
max-line-length = 100
|
||||
enable-extensions = G
|
||||
extend-ignore =
|
||||
G200, G202, G001
|
||||
# black adds spaces around ':'
|
||||
E203,
|
||||
# E501 line too long (let black handle line length)
|
||||
E501
|
||||
# B305 `.next()` is not a thing on Python 3. Use the `next()` builtin. For Python 2 compatibility, use `six.next()`.
|
||||
B305
|
||||
per-file-ignores =
|
||||
# F841 local variable 'foo' is assigned to but never used
|
||||
# E731 do not assign a lambda expression, use a def
|
||||
# F811 redefinition of unused 'foo' from line XXX
|
||||
test/*/test_examples.py: F841,E731,F811
|
||||
|
||||
# F811 redefinition of unused 'foo' from line XXX
|
||||
# B011 Do not call assert False since python -O removes these calls. Instead callers should raise AssertionError().
|
||||
|
||||
test/*: F811,B011
|
||||
|
||||
# E402 module level import not at top of file
|
||||
doc/examples/monitoring_example.py: E402
|
||||
|
||||
# F403 'from foo import *' used; unable to detect undefined names
|
||||
# F401 'foo' imported but unused
|
||||
synchro/__init__.py: F403,F401
|
||||
|
||||
# F401 'foo' imported but unused
|
||||
motor/__init__.py: F401
|
||||
python -m check_manifest -v
|
||||
|
||||
[testenv:typecheck-mypy]
|
||||
description = run mypy to typecheck
|
||||
|
||||
Loading…
Reference in New Issue
Block a user