Compare commits

...

50 Commits

Author SHA1 Message Date
Bastien Gérard
86ad8d119d Merge pull request #2487 from bagerard/prepare_0_23_0
update changelog for 0.23.0 release
2021-03-04 23:03:39 +01:00
Bastien Gerard
34d273015c update changelog for 0.23.0 release 2021-03-04 22:46:29 +01:00
Bastien Gérard
7147043d63 Merge pull request #2483 from bagerard/mongodb44_ci
Add Mongodb 44 ci and fix incompat
2021-03-04 22:42:13 +01:00
Bastien Gerard
b9b536133d fix test incompat for 4.2 2021-03-04 00:10:08 +01:00
Bastien Gerard
f244207168 fix mongo download link for 4.2 4.4 explicitly 2021-03-03 12:26:48 +01:00
Bastien Gerard
0620ac5641 Fix mongo download link as convention changed in official repo with > 4.0 2021-03-03 11:33:36 +01:00
Bastien Gerard
3b9a167022 Add Mongo 4.4 to ci 2021-03-03 10:57:18 +01:00
Bastien Gerard
b479bb7c6b Fix tests for supporting Mongo4.4 for some reason results comes sorted differently in map reduce when no sort is specified 2021-03-03 10:52:46 +01:00
Bastien Gerard
8ef771912d fixing incompatibility with mongoengine aggregation to support mongo 4.4 2021-03-03 10:51:03 +01:00
Bastien Gérard
2d1c9afbb7 Merge pull request #2477 from lukasloetkolben/feature_allow_disk_use
Feature: "allow_disk_use"
2021-02-27 23:05:50 +01:00
Bastien Gerard
9ff5d8426c restrict test on allowDiskUse to mongoDB >= 4.4 in CI + ran black 2021-02-27 21:30:07 +01:00
lukasloetkolben
467e9c3ddf typo wether --> whether 2021-02-26 18:12:58 +01:00
lukasloetkolben
0d5e028c55 - tests for feature allow_disk_use 2021-02-26 18:11:32 +01:00
Bastien Gérard
5858ea1bf0 Merge pull request #2478 from bagerard/add_geonear_aggregation_test
Add $geonear aggregation test
2021-02-24 11:55:46 +01:00
Bastien Gerard
1f220b4eaf update changelog and fix minor typo in docstring 2021-02-23 21:51:41 +01:00
Bastien Gerard
97c99ca40d Add test case for #2473 2021-02-23 21:49:45 +01:00
lukasloetkolben
80a3b1c88c - feature: allow_disk_use 2021-02-22 22:06:10 +01:00
lukasloetkolben
68447af127 - feature: allow_disk_use 2021-02-22 21:42:02 +01:00
Bastien Gérard
d033e3b133 Merge pull request #2475 from bagerard/fix_imprecise_doc_collection_name
Fix for imprecise doc on collection name (CamelCase -> snake_case)
2021-02-22 19:52:28 +01:00
Bastien Gérard
4428842e77 Merge pull request #2476 from bagerard/fix_typo
fix_minor_typo
2021-02-22 19:52:08 +01:00
Bastien Gérard
f38cc6edd3 Merge pull request #2472 from vainu-jussi/master
Check that manually setting Sequence Field in DynamicDocument doesn't increment the counter
2021-02-21 22:39:56 +01:00
Bastien Gerard
aeb4f8f4da fix_minor_typo 2021-02-21 22:04:33 +01:00
Bastien Gerard
1b7c2085c9 Fix for imprecise doc on collection name (CamelCase -> snake_case) 2021-02-21 21:17:49 +01:00
Jussi Kauppila
48b979599f Check that manually setting Sequence Field in DynamicDocument doesn't increment the counter
Fixes #2471
2021-02-16 12:23:29 +02:00
Bastien Gérard
af3d3b7ee6 Merge pull request #2463 from PeterNerlich/patch-2
Fix inconsistency with example
2021-01-12 23:10:53 +01:00
Bastien Gérard
56fe126f3a Merge pull request #2464 from bagerard/fix_coveralls_3_0_0
Fix coveralls in CI
2021-01-12 23:10:17 +01:00
Bastien Gerard
04905d4b37 Add env var to please python-coveralls 3.0.0 2021-01-12 23:07:11 +01:00
Peter Nerlich
460df112f4 Fix inconsistency with example
connection example shows a password of 12345, but text spoke of qwerty
2021-01-10 23:43:46 +01:00
Bastien Gérard
772096ec55 Merge pull request #2454 from bagerard/improve_test_field_coverage
improvements of test coverage in fields
2020-12-24 00:22:39 +01:00
Bastien Gerard
98d64f41c6 improvements of test coverage in fields 2020-12-18 00:05:40 +01:00
Bastien Gérard
9a3bca8ab6 Merge pull request #2453 from bagerard/prepare_0_22_1
Update changelog for 0.22.1
2020-12-16 23:07:18 +01:00
Bastien Gerard
5781753cc8 Update changelog for 0.22.1 2020-12-16 23:03:39 +01:00
Bastien Gérard
fd3699a519 Merge pull request #2452 from bagerard/github_actions_improvements
improve github actions
2020-12-16 22:51:36 +01:00
Bastien Gerard
4f6a24411d remove IRC notif from CI as it doesn't seem to be still valuable these days 2020-12-16 22:47:43 +01:00
Bastien Gerard
de3888a48b improve github actions 2020-12-16 22:45:45 +01:00
Bastien Gérard
700fe80a00 Merge pull request #2421 from bagerard/test_github_actions2
Migrate to GitHub actions
2020-12-16 22:36:19 +01:00
Bastien Gerard
49e33b978d move condition of build-n-publish to job level + disable test-pypi
releasing as there is some limitation on the size
2020-12-16 22:22:03 +01:00
Bastien Gerard
81197d6061 comment out travis file, until next release is fully operational from github actions 2020-12-16 22:07:34 +01:00
Bastien Gerard
aa368be4d3 minor comment improvement 2020-12-16 21:54:55 +01:00
Bastien Gerard
0f1fce4a7b Add separate jobs for test-pypi and pypi in github actions 2020-12-16 21:52:49 +01:00
Bastien Gérard
cc591a634a add coveralls to actions 2020-12-16 21:36:43 +01:00
Bastien Gérard
6e332e782b minor improvement to github actions 2020-12-16 21:21:22 +01:00
Bastien Gérard
0e9920b190 Build sphinx doc as part of ci 2020-12-16 21:21:22 +01:00
Bastien Gérard
fd35df07c4 add regular pypi deploy to github actions 2020-12-16 21:21:22 +01:00
Bastien Gérard
8f3d21c312 improve tag format match 2020-12-16 21:21:22 +01:00
Bastien Gérard
7b772e3a4a publish to test-pypi 2020-12-16 21:21:22 +01:00
Bastien Gérard
59438a4768 add IRC notif to github actions 2020-12-16 21:21:22 +01:00
Bastien Gérard
fe9f7f1f80 test github actions 2020-12-16 21:21:21 +01:00
Bastien Gérard
6b5231265c Merge pull request #2449 from Kyle-Verhoog/drop-35
Drop Python 3.5 support
2020-12-15 09:18:49 +01:00
kyle-verhoog
0014346de1 Drop Python 3.5 support 2020-12-15 02:31:23 -05:00
32 changed files with 625 additions and 257 deletions

143
.github/workflows/github-actions.yml vendored Normal file
View File

@@ -0,0 +1,143 @@
name: MongoengineCI
on:
# All PR
pull_request:
# master branch merge
push:
branches:
- master
# release tags
create:
tags:
- 'v[0-9]+\.[0-9]+\.[0-9]+*'
env:
MONGODB_3_6: 3.6.14
MONGODB_4_0: 4.0.23
MONGODB_4_2: 4.2
MONGODB_4_4: 4.4
PYMONGO_3_4: 3.4
PYMONGO_3_6: 3.6
PYMONGO_3_9: 3.9
PYMONGO_3_11: 3.11
MAIN_PYTHON_VERSION: 3.7
jobs:
linting:
# Run pre-commit (https://pre-commit.com/)
# which runs pre-configured linter & autoformatter
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python 3.7
uses: actions/setup-python@v2
with:
python-version: 3.7
- run: bash .github/workflows/install_ci_python_dep.sh
- run: pre-commit run -a
test:
# Test suite run against recent python versions
# and against a few combination of MongoDB and pymongo
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: [3.6, 3.7, 3.8, 3.9, pypy3]
MONGODB: [$MONGODB_4_0]
PYMONGO: [$PYMONGO_3_11]
include:
- python-version: 3.7
MONGODB: $MONGODB_3_6
PYMONGO: $PYMONGO_3_9
- python-version: 3.7
MONGODB: $MONGODB_4_2
PYMONGO: $PYMONGO_3_6
- python-version: 3.7
MONGODB: $MONGODB_4_4
PYMONGO: $PYMONGO_3_11
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: install mongo and ci dependencies
run: |
bash .github/workflows/install_mongo.sh ${{ matrix.MONGODB }}
bash .github/workflows/install_ci_python_dep.sh
bash .github/workflows/start_mongo.sh ${{ matrix.MONGODB }}
- name: tox dry-run (to pre-install venv)
run: tox -e $(echo py${{ matrix.python-version }}-mg${{ matrix.PYMONGO }} | tr -d . | sed -e 's/pypypy/pypy/') -- -a "-k=test_ci_placeholder"
- name: Run test suite
run: tox -e $(echo py${{ matrix.python-version }}-mg${{ matrix.PYMONGO }} | tr -d . | sed -e 's/pypypy/pypy/') -- -a "--cov=mongoengine"
- name: Send coverage to Coveralls
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COVERALLS_SERVICE_NAME: github
if: ${{ matrix.python-version == env.MAIN_PYTHON_VERSION }}
run: coveralls
build_doc_dryrun:
# ensures that readthedocs can be built continuously
# to avoid that it breaks when new releases are being created
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: 3.7
- name: install python dep
run: |
pip install -e .
pip install -r docs/requirements.txt
- name: build doc
run: |
cd docs
make html-readthedocs
build-n-publish-dummy:
runs-on: ubuntu-latest
needs: [linting, test, build_doc_dryrun]
if: github.event_name != 'pull_request'
steps:
- uses: actions/checkout@master
- name: Set up Python 3.7
uses: actions/setup-python@v1
with:
python-version: 3.7
- name: build dummy wheel for test-pypi
run: |
pip install wheel
python setup.py egg_info -b ".dev`date '+%Y%m%d%H%M%S'`" build sdist bdist_wheel
# - name: publish test-pypi
# # Although working and recommended, test-pypi has a limit
# # in the size of projects so it's better to avoid publishing
# # until there is a way to garbage collect these dummy releases
# uses: pypa/gh-action-pypi-publish@master
# with:
# password: ${{ secrets.test_pypi_token }}
# repository_url: https://test.pypi.org/legacy/
build-n-publish:
runs-on: ubuntu-latest
needs: [linting, test, build_doc_dryrun, build-n-publish-dummy]
if: github.event_name == 'create' && startsWith(github.ref, 'refs/tags/v')
steps:
- uses: actions/checkout@master
- name: Set up Python 3.7
uses: actions/setup-python@v1
with:
python-version: 3.7
# todo separate build from publish
# https://stackoverflow.com/questions/59349905/which-properties-does-github-event-in-a-github-workflow-have
- name: build dummy wheel for test-pypi
run: |
pip install wheel
python setup.py sdist bdist_wheel
- name: publish pypi
uses: pypa/gh-action-pypi-publish@master
with:
password: ${{ secrets.pypi_token }}

View File

@@ -0,0 +1,5 @@
#!/bin/bash
pip install --upgrade pip
pip install coveralls
pip install pre-commit
pip install tox

18
.github/workflows/install_mongo.sh vendored Normal file
View File

@@ -0,0 +1,18 @@
#!/bin/bash
MONGODB=$1
# Mongo > 4.0 follows different name convention for download links
mongo_build=mongodb-linux-x86_64-${MONGODB}
if [[ "$MONGODB" == *"4.2"* ]]; then
mongo_build=mongodb-linux-x86_64-ubuntu1804-v${MONGODB}-latest
elif [[ "$MONGODB" == *"4.4"* ]]; then
mongo_build=mongodb-linux-x86_64-ubuntu1804-v${MONGODB}-latest
fi
wget http://fastdl.mongodb.org/linux/$mongo_build.tgz
tar xzf $mongo_build.tgz
mongodb_dir=$(find ${PWD}/ -type d -name "mongodb-linux-x86_64*")
$mongodb_dir/bin/mongod --version

9
.github/workflows/start_mongo.sh vendored Normal file
View File

@@ -0,0 +1,9 @@
#!/bin/bash
MONGODB=$1
mongodb_dir=$(find ${PWD}/ -type d -name "mongodb-linux-x86_64*")
mkdir $mongodb_dir/data
$mongodb_dir/bin/mongod --dbpath $mongodb_dir/data --logpath $mongodb_dir/mongodb.log --fork
mongo --eval 'db.version();' # Make sure mongo is awake

View File

@@ -1,107 +0,0 @@
# For full coverage, we'd have to test all supported Python, MongoDB, and
# PyMongo combinations. However, that would result in an overly long build
# with a very large number of jobs, hence we only test a subset of all the
# combinations.
# * Python3.7, MongoDB v3.4 & the latest PyMongo v3.x is currently the "main" setup,
# Other combinations are tested. See below for the details or check the travis jobs
# We should periodically check MongoDB Server versions supported by MongoDB
# Inc., add newly released versions to the test matrix, and remove versions
# which have reached their End of Life. See:
# 1. https://www.mongodb.com/support-policy.
# 2. https://docs.mongodb.com/ecosystem/drivers/driver-compatibility-reference/#python-driver-compatibility
#
# Reminder: Update README.rst if you change MongoDB versions we test.
language: python
dist: xenial
python:
- 3.6
- 3.7
- 3.8
- 3.9
- pypy3
env:
global:
- MONGODB_3_4=3.4.19
- MONGODB_3_6=3.6.13
- MONGODB_4_0=4.0.13
- PYMONGO_3_4=3.4
- PYMONGO_3_6=3.6
- PYMONGO_3_9=3.9
- PYMONGO_3_11=3.11
- MAIN_PYTHON_VERSION=3.7
matrix:
- MONGODB=${MONGODB_3_4} PYMONGO=${PYMONGO_3_11}
matrix:
# Finish the build as soon as one job fails
fast_finish: true
include:
- python: 3.7
env: MONGODB=${MONGODB_3_6} PYMONGO=${PYMONGO_3_6}
- python: 3.7
env: MONGODB=${MONGODB_3_6} PYMONGO=${PYMONGO_3_9}
- python: 3.7
env: MONGODB=${MONGODB_3_6} PYMONGO=${PYMONGO_3_11}
- python: 3.8
env: MONGODB=${MONGODB_4_0} PYMONGO=${PYMONGO_3_11}
install:
# Install Mongo
- wget http://fastdl.mongodb.org/linux/mongodb-linux-x86_64-${MONGODB}.tgz
- tar xzf mongodb-linux-x86_64-${MONGODB}.tgz
- ${PWD}/mongodb-linux-x86_64-${MONGODB}/bin/mongod --version
# Install Python dependencies.
- pip install --upgrade pip
- pip install coveralls
- pip install pre-commit
- pip install tox
# tox dryrun to setup the tox venv (we run a mock test).
- tox -e $(echo py$TRAVIS_PYTHON_VERSION-mg$PYMONGO | tr -d . | sed -e 's/pypypy/pypy/') -- -a "-k=test_ci_placeholder"
before_script:
- mkdir ${PWD}/mongodb-linux-x86_64-${MONGODB}/data
- ${PWD}/mongodb-linux-x86_64-${MONGODB}/bin/mongod --dbpath ${PWD}/mongodb-linux-x86_64-${MONGODB}/data --logpath ${PWD}/mongodb-linux-x86_64-${MONGODB}/mongodb.log --fork
# Run pre-commit hooks (black, flake8, etc) on entire codebase
- if [[ $TRAVIS_PYTHON_VERSION == $MAIN_PYTHON_VERSION ]]; then pre-commit run -a; else echo "pre-commit checks only runs on py37"; fi
- mongo --eval 'db.version();' # Make sure mongo is awake
script:
- tox -e $(echo py$TRAVIS_PYTHON_VERSION-mg$PYMONGO | tr -d . | sed -e 's/pypypy/pypy/') -- -a "--cov=mongoengine"
after_success:
- if [[ $TRAVIS_PYTHON_VERSION == $MAIN_PYTHON_VERSION ]]; then coveralls --verbose; else echo "coveralls only sent for py37"; fi
notifications:
irc: irc.freenode.org#mongoengine
# Only run builds on the master branch and GitHub releases (tagged as vX.Y.Z)
branches:
only:
- master
- /^v.*$/
# Whenever a new release is created via GitHub, publish it on PyPI.
deploy:
provider: pypi
user: the_drow
password:
secure: QMyatmWBnC6ZN3XLW2+fTBDU4LQcp1m/LjR2/0uamyeUzWKdlOoh/Wx5elOgLwt/8N9ppdPeG83ose1jOz69l5G0MUMjv8n/RIcMFSpCT59tGYqn3kh55b0cIZXFT9ar+5cxlif6a5rS72IHm5li7QQyxexJIII6Uxp0kpvUmek=
# Create a source distribution and a pure python wheel for faster installs.
distributions: "sdist bdist_wheel"
# Only deploy on tagged commits (aka GitHub releases) and only for the parent
# repo's builds running Python v3.7 along with PyMongo v3.x and MongoDB v3.4.
# We run Travis against many different Python, PyMongo, and MongoDB versions
# and we don't want the deploy to occur multiple times).
on:
tags: true
repo: MongoEngine/mongoengine
condition: ($PYMONGO = ${PYMONGO_3_11}) && ($MONGODB = ${MONGODB_3_4})
python: 3.7

108
.travis_.yml Normal file
View File

@@ -0,0 +1,108 @@
## For full coverage, we'd have to test all supported Python, MongoDB, and
## PyMongo combinations. However, that would result in an overly long build
## with a very large number of jobs, hence we only test a subset of all the
## combinations.
## * Python3.7, MongoDB v3.4 & the latest PyMongo v3.x is currently the "main" setup,
## Other combinations are tested. See below for the details or check the travis jobs
#
## We should periodically check MongoDB Server versions supported by MongoDB
## Inc., add newly released versions to the test matrix, and remove versions
## which have reached their End of Life. See:
## 1. https://www.mongodb.com/support-policy.
## 2. https://docs.mongodb.com/ecosystem/drivers/driver-compatibility-reference/#python-driver-compatibility
##
## Reminder: Update README.rst if you change MongoDB versions we test.
#
#language: python
#dist: xenial
#python:
# - 3.6
# - 3.7
# - 3.8
# - 3.9
# - pypy3
#
#env:
# global:
# - MONGODB_3_4=3.4.19
# - MONGODB_3_6=3.6.13
# - MONGODB_4_0=4.0.13
#
# - PYMONGO_3_4=3.4
# - PYMONGO_3_6=3.6
# - PYMONGO_3_9=3.9
# - PYMONGO_3_11=3.11
#
# - MAIN_PYTHON_VERSION=3.7
# matrix:
# - MONGODB=${MONGODB_3_4} PYMONGO=${PYMONGO_3_11}
#
#matrix:
# # Finish the build as soon as one job fails
# fast_finish: true
#
# include:
# - python: 3.7
# env: MONGODB=${MONGODB_3_6} PYMONGO=${PYMONGO_3_6}
# - python: 3.7
# env: MONGODB=${MONGODB_3_6} PYMONGO=${PYMONGO_3_9}
# - python: 3.7
# env: MONGODB=${MONGODB_3_6} PYMONGO=${PYMONGO_3_11}
# - python: 3.8
# env: MONGODB=${MONGODB_4_0} PYMONGO=${PYMONGO_3_11}
#
#install:
# # Install Mongo
# - wget http://fastdl.mongodb.org/linux/mongodb-linux-x86_64-${MONGODB}.tgz
# - tar xzf mongodb-linux-x86_64-${MONGODB}.tgz
# - ${PWD}/mongodb-linux-x86_64-${MONGODB}/bin/mongod --version
# # Install Python dependencies.
# - pip install --upgrade pip
# - pip install coveralls
# - pip install pre-commit
# - pip install tox
# # tox dryrun to setup the tox venv (we run a mock test).
# - tox -e $(echo py$TRAVIS_PYTHON_VERSION-mg$PYMONGO | tr -d . | sed -e 's/pypypy/pypy/') -- -a "-k=test_ci_placeholder"
#
#before_script:
# - mkdir ${PWD}/mongodb-linux-x86_64-${MONGODB}/data
# - ${PWD}/mongodb-linux-x86_64-${MONGODB}/bin/mongod --dbpath ${PWD}/mongodb-linux-x86_64-${MONGODB}/data --logpath ${PWD}/mongodb-linux-x86_64-${MONGODB}/mongodb.log --fork
# # Run pre-commit hooks (black, flake8, etc) on entire codebase
# - if [[ $TRAVIS_PYTHON_VERSION == $MAIN_PYTHON_VERSION ]]; then pre-commit run -a; else echo "pre-commit checks only runs on py37"; fi
# - mongo --eval 'db.version();' # Make sure mongo is awake
#
#script:
# - tox -e $(echo py$TRAVIS_PYTHON_VERSION-mg$PYMONGO | tr -d . | sed -e 's/pypypy/pypy/') -- -a "--cov=mongoengine"
#
#after_success:
# - if [[ $TRAVIS_PYTHON_VERSION == $MAIN_PYTHON_VERSION ]]; then coveralls --verbose; else echo "coveralls only sent for py37"; fi
#
#notifications:
# irc: irc.freenode.org#mongoengine
#
## Only run builds on the master branch and GitHub releases (tagged as vX.Y.Z)
#branches:
# # Only run builds on the master branch and GitHub releases (tagged as vX.Y.Z)
# only:
# - master
# - /^v.*$/
#
## Whenever a new release is created via GitHub, publish it on PyPI.
#deploy:
# provider: pypi
# user: the_drow
# password:
# secure: QMyatmWBnC6ZN3XLW2+fTBDU4LQcp1m/LjR2/0uamyeUzWKdlOoh/Wx5elOgLwt/8N9ppdPeG83ose1jOz69l5G0MUMjv8n/RIcMFSpCT59tGYqn3kh55b0cIZXFT9ar+5cxlif6a5rS72IHm5li7QQyxexJIII6Uxp0kpvUmek=
#
# # Create a source distribution and a pure python wheel for faster installs.
# distributions: "sdist bdist_wheel"
#
# # Only deploy on tagged commits (aka GitHub releases) and only for the parent
# # repo's builds running Python v3.7 along with PyMongo v3.x and MongoDB v3.4.
# # We run Travis against many different Python, PyMongo, and MongoDB versions
# # and we don't want the deploy to occur multiple times).
# on:
# tags: true
# repo: MongoEngine/mongoengine
# condition: ($PYMONGO = ${PYMONGO_3_11}) && ($MONGODB = ${MONGODB_3_4})
# python: 3.7

View File

@@ -35,6 +35,12 @@ html:
@echo
@echo "Build finished. Check $(BUILDDIR)/html/index.html"
html-readthedocs:
$(SPHINXBUILD) -T -E -b readthedocs $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo

View File

@@ -1,4 +1,5 @@
=========
Changelog
=========
@@ -7,6 +8,17 @@ Development
===========
- (Fill this out as you fix issues and develop your features).
Changes in 0.23.0
===========
- Bugfix: manually setting SequenceField in DynamicDocument doesn't increment the counter #2471
- Add MongoDB 4.2 and 4.4 to CI
- Add support for allowDiskUse on querysets #2468
Changes in 0.22.1
=================
- Declare that Py3.5 is not supported in package metadata #2449
- Moved CI from Travis to Github-Actions
Changes in 0.22.0
=================
- Fix LazyReferenceField dereferencing in embedded documents #2426

View File

@@ -26,7 +26,7 @@ sys.path.insert(0, os.path.abspath(".."))
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ["sphinx.ext.autodoc", "sphinx.ext.todo"]
extensions = ["sphinx.ext.autodoc", "sphinx.ext.todo", "readthedocs_ext.readthedocs"]
# Add any paths that contain templates here, relative to this directory.
templates_path = ["_templates"]

View File

@@ -44,7 +44,7 @@ the :attr:`host` to
)
will establish connection to ``production`` database using
``admin`` username and ``qwerty`` password.
``admin`` username and ``12345`` password.
.. note:: Calling :func:`~mongoengine.connect` without argument will establish
a connection to the "test" database by default

View File

@@ -432,10 +432,10 @@ Document collections
====================
Document classes that inherit **directly** from :class:`~mongoengine.Document`
will have their own **collection** in the database. The name of the collection
is by default the name of the class, converted to lowercase (so in the example
above, the collection would be called `page`). If you need to change the name
of the collection (e.g. to use MongoEngine with an existing database), then
create a class dictionary attribute called :attr:`meta` on your document, and
is by default the name of the class converted to snake_case (e.g if your Document class
is named `CompanyUser`, the corresponding collection would be `company_user`). If you need
to change the name of the collection (e.g. to use MongoEngine with an existing database),
then create a class dictionary attribute called :attr:`meta` on your document, and
set :attr:`collection` to the name of the collection that you want your
document class to use::

View File

@@ -1,3 +1,3 @@
pymongo>=3.11
Sphinx==3.2.1
Sphinx==3.3.0
sphinx-rtd-theme==0.5.0
readthedocs-sphinx-ext==2.1.1

View File

@@ -28,7 +28,7 @@ __all__ = (
)
VERSION = (0, 22, 0)
VERSION = (0, 23, 0)
def get_version():

View File

@@ -156,7 +156,7 @@ class BaseDocument:
# Handle dynamic data only if an initialised dynamic document
if self._dynamic and not self._dynamic_lock:
if not hasattr(self, name) and not name.startswith("_"):
if name not in self._fields_ordered and not name.startswith("_"):
DynamicField = _import_class("DynamicField")
field = DynamicField(db_field=name, null=True)
field.name = name

View File

@@ -109,7 +109,7 @@ class Document(BaseDocument, metaclass=TopLevelDocumentMetaclass):
By default, the MongoDB collection used to store documents created using a
:class:`~mongoengine.Document` subclass will be the name of the subclass
converted to lowercase. A different collection may be specified by
converted to snake_case. A different collection may be specified by
providing :attr:`collection` to the :attr:`meta` dictionary in the class
definition.

View File

@@ -1,5 +1,6 @@
import datetime
import decimal
import inspect
import itertools
import re
import socket
@@ -514,7 +515,7 @@ class BooleanField(BaseField):
def to_python(self, value):
try:
value = bool(value)
except ValueError:
except (ValueError, TypeError):
pass
return value
@@ -1028,17 +1029,6 @@ def key_not_string(d):
return True
def key_has_dot_or_dollar(d):
"""Helper function to recursively determine if any key in a
dictionary contains a dot or a dollar sign.
"""
for k, v in d.items():
if ("." in k or k.startswith("$")) or (
isinstance(v, dict) and key_has_dot_or_dollar(v)
):
return True
def key_starts_with_dollar(d):
"""Helper function to recursively determine if any key in a
dictionary starts with a dollar
@@ -1172,7 +1162,7 @@ class ReferenceField(BaseField):
:param document_type: The type of Document that will be referenced
:param dbref: Store the reference as :class:`~pymongo.dbref.DBRef`
or as the :class:`~pymongo.objectid.ObjectId`.id .
or as the :class:`~pymongo.objectid.ObjectId`.
:param reverse_delete_rule: Determines what to do when the referring
object is deleted
:param kwargs: Keyword arguments passed into the parent :class:`~mongoengine.BaseField`
@@ -1311,8 +1301,8 @@ class CachedReferenceField(BaseField):
fields = []
# XXX ValidationError raised outside of the "validate" method.
if not isinstance(document_type, str) and not issubclass(
document_type, Document
if not isinstance(document_type, str) and not (
inspect.isclass(document_type) and issubclass(document_type, Document)
):
self.error(
"Argument to CachedReferenceField constructor must be a"
@@ -1642,7 +1632,7 @@ class EnumField(BaseField):
"'choices' can't be set on EnumField, "
"it is implicitly set as the enum class"
)
kwargs["choices"] = list(self._enum_cls)
kwargs["choices"] = list(self._enum_cls) # Implicit validator
super().__init__(**kwargs)
def __set__(self, instance, value):
@@ -1659,13 +1649,6 @@ class EnumField(BaseField):
return value.value
return value
def validate(self, value):
if value and not isinstance(value, self._enum_cls):
try:
self._enum_cls(value)
except Exception as e:
self.error(str(e))
def prepare_query_value(self, op, value):
if value is None:
return value
@@ -2431,7 +2414,7 @@ class LazyReferenceField(BaseField):
object is deleted
:param passthrough: When trying to access unknown fields, the
:class:`~mongoengine.base.datastructure.LazyReference` instance will
automatically call `fetch()` and try to retrive the field on the fetched
automatically call `fetch()` and try to retrieve the field on the fetched
document. Note this only work getting field (not setting or deleting).
"""
# XXX ValidationError raised outside of the "validate" method.

View File

@@ -8,6 +8,8 @@ from mongoengine.connection import get_connection
# get_mongodb_version()
MONGODB_34 = (3, 4)
MONGODB_36 = (3, 6)
MONGODB_42 = (4, 2)
MONGODB_44 = (4, 4)
def get_mongodb_version():

View File

@@ -64,6 +64,7 @@ class BaseQuerySet:
self._ordering = None
self._snapshot = False
self._timeout = True
self._allow_disk_use = False
self._read_preference = None
self._read_concern = None
self._iter = False
@@ -799,6 +800,7 @@ class BaseQuerySet:
"_ordering",
"_snapshot",
"_timeout",
"_allow_disk_use",
"_read_preference",
"_read_concern",
"_iter",
@@ -1165,6 +1167,16 @@ class BaseQuerySet:
queryset._snapshot = enabled
return queryset
def allow_disk_use(self, enabled):
"""Enable or disable the use of temporary files on disk while processing a blocking sort operation.
(To store data exceeding the 100 megabyte system memory limit)
:param enabled: whether or not temporary files on disk are used
"""
queryset = self.clone()
queryset._allow_disk_use = enabled
return queryset
def timeout(self, enabled):
"""Enable or disable the default mongod timeout when querying. (no_cursor_timeout option)
@@ -1343,21 +1355,18 @@ class BaseQuerySet:
MapReduceDocument = _import_class("MapReduceDocument")
if not hasattr(self._collection, "map_reduce"):
raise NotImplementedError("Requires MongoDB >= 1.7.1")
map_f_scope = {}
if isinstance(map_f, Code):
map_f_scope = map_f.scope
map_f = str(map_f)
map_f = Code(queryset._sub_js_fields(map_f), map_f_scope)
map_f = Code(queryset._sub_js_fields(map_f), map_f_scope or None)
reduce_f_scope = {}
if isinstance(reduce_f, Code):
reduce_f_scope = reduce_f.scope
reduce_f = str(reduce_f)
reduce_f_code = queryset._sub_js_fields(reduce_f)
reduce_f = Code(reduce_f_code, reduce_f_scope)
reduce_f = Code(reduce_f_code, reduce_f_scope or None)
mr_args = {"query": queryset._query}
@@ -1367,7 +1376,7 @@ class BaseQuerySet:
finalize_f_scope = finalize_f.scope
finalize_f = str(finalize_f)
finalize_f_code = queryset._sub_js_fields(finalize_f)
finalize_f = Code(finalize_f_code, finalize_f_scope)
finalize_f = Code(finalize_f_code, finalize_f_scope or None)
mr_args["finalize"] = finalize_f
if scope:
@@ -1604,6 +1613,9 @@ class BaseQuerySet:
if not self._timeout:
cursor_args["no_cursor_timeout"] = True
if self._allow_disk_use:
cursor_args["allow_disk_use"] = True
if self._loaded_fields:
cursor_args[fields_name] = self._loaded_fields.as_dict()

View File

@@ -98,7 +98,6 @@ CLASSIFIERS = [
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
@@ -113,7 +112,7 @@ extra_opts = {
"tests_require": [
"pytest<5.0",
"pytest-cov",
"coverage<5.0", # recent coverage switched to sqlite format for the .coverage file which isn't handled properly by coveralls
"coverage",
"blinker",
"Pillow>=7.0.0",
],
@@ -140,7 +139,7 @@ setup(
long_description=LONG_DESCRIPTION,
platforms=["any"],
classifiers=CLASSIFIERS,
python_requires=">=3.5",
python_requires=">=3.6",
install_requires=["pymongo>=3.4, <4.0"],
cmdclass={"test": PyTest},
**extra_opts

View File

@@ -7,6 +7,7 @@ import pytest
from mongoengine import *
from mongoengine.connection import get_db
from mongoengine.mongodb_support import MONGODB_42, get_mongodb_version
class TestIndexes(unittest.TestCase):
@@ -452,9 +453,11 @@ class TestIndexes(unittest.TestCase):
.get("stage")
== "IXSCAN"
)
mongo_db = get_mongodb_version()
PROJECTION_STR = "PROJECTION" if mongo_db < MONGODB_42 else "PROJECTION_COVERED"
assert (
query_plan.get("queryPlanner").get("winningPlan").get("stage")
== "PROJECTION"
== PROJECTION_STR
)
query_plan = Test.objects(a=1).explain()

View File

@@ -13,6 +13,17 @@ class TestBooleanField(MongoDBTestCase):
person.save()
assert get_as_pymongo(person) == {"_id": person.id, "admin": True}
def test_construction_does_not_fail_uncastable_value(self):
class BoolFail:
def __bool__(self):
return "bogus"
class Person(Document):
admin = BooleanField()
person = Person(admin=BoolFail())
person.admin == "bogus"
def test_validation(self):
"""Ensure that invalid values cannot be assigned to boolean
fields.

View File

@@ -2,11 +2,28 @@ from decimal import Decimal
import pytest
from mongoengine import *
from mongoengine import (
CachedReferenceField,
DecimalField,
Document,
EmbeddedDocument,
EmbeddedDocumentField,
InvalidDocumentError,
ListField,
ReferenceField,
StringField,
ValidationError,
)
from tests.utils import MongoDBTestCase
class TestCachedReferenceField(MongoDBTestCase):
def test_constructor_fail_bad_document_type(self):
with pytest.raises(
ValidationError, match="must be a document class or a string"
):
CachedReferenceField(document_type=0)
def test_get_and_save(self):
"""
Tests #1047: CachedReferenceField creates DBRefs on to_python,

View File

@@ -2,59 +2,11 @@ from decimal import Decimal
import pytest
from mongoengine import *
from mongoengine import DecimalField, Document, ValidationError
from tests.utils import MongoDBTestCase
class TestDecimalField(MongoDBTestCase):
def test_validation(self):
"""Ensure that invalid values cannot be assigned to decimal fields."""
class Person(Document):
height = DecimalField(min_value=Decimal("0.1"), max_value=Decimal("3.5"))
Person.drop_collection()
Person(height=Decimal("1.89")).save()
person = Person.objects.first()
assert person.height == Decimal("1.89")
person.height = "2.0"
person.save()
person.height = 0.01
with pytest.raises(ValidationError):
person.validate()
person.height = Decimal("0.01")
with pytest.raises(ValidationError):
person.validate()
person.height = Decimal("4.0")
with pytest.raises(ValidationError):
person.validate()
person.height = "something invalid"
with pytest.raises(ValidationError):
person.validate()
person_2 = Person(height="something invalid")
with pytest.raises(ValidationError):
person_2.validate()
def test_comparison(self):
class Person(Document):
money = DecimalField()
Person.drop_collection()
Person(money=6).save()
Person(money=7).save()
Person(money=8).save()
Person(money=10).save()
assert 2 == Person.objects(money__gt=Decimal("7")).count()
assert 2 == Person.objects(money__gt=7).count()
assert 2 == Person.objects(money__gt="7").count()
assert 3 == Person.objects(money__gte="7").count()
def test_storage(self):
class Person(Document):
float_value = DecimalField(precision=4)
@@ -106,3 +58,63 @@ class TestDecimalField(MongoDBTestCase):
for field_name in ["float_value", "string_value"]:
actual = list(Person.objects().scalar(field_name))
assert expected == actual
def test_save_none(self):
class Person(Document):
value = DecimalField()
Person.drop_collection()
person = Person(value=None)
assert person.value is None
person.save()
fetched_person = Person.objects.first()
fetched_person.value is None
def test_validation(self):
"""Ensure that invalid values cannot be assigned to decimal fields."""
class Person(Document):
height = DecimalField(min_value=Decimal("0.1"), max_value=Decimal("3.5"))
Person.drop_collection()
Person(height=Decimal("1.89")).save()
person = Person.objects.first()
assert person.height == Decimal("1.89")
person.height = "2.0"
person.save()
person.height = 0.01
with pytest.raises(ValidationError):
person.validate()
person.height = Decimal("0.01")
with pytest.raises(ValidationError):
person.validate()
person.height = Decimal("4.0")
with pytest.raises(ValidationError):
person.validate()
person.height = "something invalid"
with pytest.raises(ValidationError):
person.validate()
person_2 = Person(height="something invalid")
with pytest.raises(ValidationError):
person_2.validate()
def test_comparison(self):
class Person(Document):
money = DecimalField()
Person.drop_collection()
Person(money=6).save()
Person(money=7).save()
Person(money=8).save()
Person(money=10).save()
assert 2 == Person.objects(money__gt=Decimal("7")).count()
assert 2 == Person.objects(money__gt=7).count()
assert 2 == Person.objects(money__gt="7").count()
assert 3 == Person.objects(money__gte="7").count()

View File

@@ -3,7 +3,7 @@ from enum import Enum
from bson import InvalidDocument
import pytest
from mongoengine import *
from mongoengine import Document, EnumField, ValidationError
from tests.utils import MongoDBTestCase, get_as_pymongo
@@ -45,6 +45,11 @@ class TestStringEnumField(MongoDBTestCase):
m.save()
assert m.status == Status.DONE
m.status = "wrong"
assert m.status == "wrong"
with pytest.raises(ValidationError):
m.validate()
def test_set_default(self):
class ModelWithDefault(Document):
status = EnumField(Status, default=Status.DONE)

View File

@@ -306,7 +306,7 @@ class TestField(MongoDBTestCase):
)
assert res == 1
# Retrive data from db and verify it.
# Retrieve data from db and verify it.
ret = HandleNoneFields.objects.all()[0]
assert ret.str_fld is None
assert ret.int_fld is None
@@ -340,7 +340,7 @@ class TestField(MongoDBTestCase):
{"$unset": {"str_fld": 1, "int_fld": 1, "flt_fld": 1, "comp_dt_fld": 1}},
)
# Retrive data from db and verify it.
# Retrieve data from db and verify it.
ret = HandleNoneFields.objects.first()
assert ret.str_fld is None
assert ret.int_fld is None
@@ -374,34 +374,6 @@ class TestField(MongoDBTestCase):
person.id = str(ObjectId())
person.validate()
def test_string_validation(self):
"""Ensure that invalid values cannot be assigned to string fields."""
class Person(Document):
name = StringField(max_length=20)
userid = StringField(r"[0-9a-z_]+$")
person = Person(name=34)
with pytest.raises(ValidationError):
person.validate()
# Test regex validation on userid
person = Person(userid="test.User")
with pytest.raises(ValidationError):
person.validate()
person.userid = "test_user"
assert person.userid == "test_user"
person.validate()
# Test max length validation on name
person = Person(name="Name that is more than twenty characters")
with pytest.raises(ValidationError):
person.validate()
person.name = "Shorter name"
person.validate()
def test_db_field_validation(self):
"""Ensure that db_field doesn't accept invalid values."""

View File

@@ -4,10 +4,26 @@ import pytest
from mongoengine import *
from mongoengine.connection import get_db
from tests.utils import MongoDBTestCase
from tests.utils import MongoDBTestCase, get_as_pymongo
class TestLongField(MongoDBTestCase):
def test_storage(self):
class Person(Document):
value = LongField()
Person.drop_collection()
person = Person(value=5000)
person.save()
assert get_as_pymongo(person) == {"_id": person.id, "value": 5000}
def test_construction_does_not_fail_with_invalid_value(self):
class Person(Document):
value = LongField()
person = Person(value="not_an_int")
assert person.value == "not_an_int"
def test_long_field_is_considered_as_int64(self):
"""
Tests that long fields are stored as long in mongo, even if long
@@ -30,19 +46,16 @@ class TestLongField(MongoDBTestCase):
class TestDocument(Document):
value = LongField(min_value=0, max_value=110)
doc = TestDocument()
doc.value = 50
doc.validate()
TestDocument(value=50).validate()
doc.value = -1
with pytest.raises(ValidationError):
doc.validate()
doc.value = 120
TestDocument(value=-1).validate()
with pytest.raises(ValidationError):
doc.validate()
doc.value = "ten"
TestDocument(value=120).validate()
with pytest.raises(ValidationError):
doc.validate()
TestDocument(value="ten").validate()
def test_long_ne_operator(self):
class TestDocument(Document):
@@ -53,4 +66,5 @@ class TestLongField(MongoDBTestCase):
TestDocument(long_fld=None).save()
TestDocument(long_fld=1).save()
assert 1 == TestDocument.objects(long_fld__ne=None).count()
assert TestDocument.objects(long_fld__ne=None).count() == 1
assert TestDocument.objects(long_fld__ne=1).count() == 1

View File

@@ -274,3 +274,25 @@ class TestSequenceField(MongoDBTestCase):
assert foo.counter == bar.counter
assert foo._fields["counter"].owner_document == Foo
assert bar._fields["counter"].owner_document == Bar
def test_sequence_setattr_not_incrementing_counter(self):
class Person(DynamicDocument):
id = SequenceField(primary_key=True)
name = StringField()
self.db["mongoengine.counters"].drop()
Person.drop_collection()
for x in range(10):
Person(name="Person %s" % x).save()
c = self.db["mongoengine.counters"].find_one({"_id": "person.id"})
assert c["next"] == 10
# Setting SequenceField field value should not increment counter:
new_person = Person()
new_person.id = 1100
# Counter should still be at 10
c = self.db["mongoengine.counters"].find_one({"_id": "person.id"})
assert c["next"] == 10

View File

@@ -0,0 +1,43 @@
import pytest
from mongoengine import *
from tests.utils import MongoDBTestCase, get_as_pymongo
class TestStringField(MongoDBTestCase):
def test_storage(self):
class Person(Document):
name = StringField()
Person.drop_collection()
person = Person(name="test123")
person.save()
assert get_as_pymongo(person) == {"_id": person.id, "name": "test123"}
def test_validation(self):
class Person(Document):
name = StringField(max_length=20, min_length=2)
userid = StringField(r"[0-9a-z_]+$")
with pytest.raises(ValidationError, match="only accepts string values"):
Person(name=34).validate()
with pytest.raises(ValidationError, match="value is too short"):
Person(name="s").validate()
# Test regex validation on userid
person = Person(userid="test.User")
with pytest.raises(ValidationError):
person.validate()
person.userid = "test_user"
assert person.userid == "test_user"
person.validate()
# Test max length validation on name
person = Person(name="Name that is more than twenty characters")
with pytest.raises(ValidationError):
person.validate()
person = Person(name="a friendl name", userid="7a757668sqjdkqlsdkq")
person.validate()

View File

@@ -21,6 +21,10 @@ from mongoengine.queryset import (
QuerySetManager,
queryset_manager,
)
from tests.utils import (
requires_mongodb_gte_44,
requires_mongodb_lt_42,
)
class db_ops_tracker(query_counter):
@@ -1489,6 +1493,7 @@ class TestQueryset(unittest.TestCase):
BlogPost.drop_collection()
@requires_mongodb_lt_42
def test_exec_js_query(self):
"""Ensure that queries are properly formed for use in exec_js."""
@@ -1526,6 +1531,7 @@ class TestQueryset(unittest.TestCase):
BlogPost.drop_collection()
@requires_mongodb_lt_42
def test_exec_js_field_sub(self):
"""Ensure that field substitutions occur properly in exec_js functions."""
@@ -2659,6 +2665,8 @@ class TestQueryset(unittest.TestCase):
title = StringField(primary_key=True)
tags = ListField(StringField())
BlogPost.drop_collection()
post1 = BlogPost(title="Post #1", tags=["mongodb", "mongoengine"])
post2 = BlogPost(title="Post #2", tags=["django", "mongodb"])
post3 = BlogPost(title="Post #3", tags=["hitchcock films"])
@@ -2687,12 +2695,15 @@ class TestQueryset(unittest.TestCase):
}
"""
results = BlogPost.objects.map_reduce(map_f, reduce_f, "myresults")
results = BlogPost.objects.order_by("_id").map_reduce(
map_f, reduce_f, "myresults2"
)
results = list(results)
assert results[0].object == post1
assert results[1].object == post2
assert results[2].object == post3
assert len(results) == 3
assert results[0].object.id == post1.id
assert results[1].object.id == post2.id
assert results[2].object.id == post3.id
BlogPost.drop_collection()
@@ -2700,7 +2711,6 @@ class TestQueryset(unittest.TestCase):
"""
Test map/reduce custom output
"""
register_connection("test2", "mongoenginetest2")
class Family(Document):
id = IntField(primary_key=True)
@@ -2773,6 +2783,7 @@ class TestQueryset(unittest.TestCase):
family.persons.push(person);
family.totalAge += person.age;
});
family.persons.sort((a, b) => (a.age > b.age))
}
});
@@ -2801,10 +2812,10 @@ class TestQueryset(unittest.TestCase):
"_id": 1,
"value": {
"persons": [
{"age": 21, "name": "Wilson Jr"},
{"age": 45, "name": "Wilson Father"},
{"age": 40, "name": "Eliana Costa"},
{"age": 17, "name": "Tayza Mariana"},
{"age": 21, "name": "Wilson Jr"},
{"age": 40, "name": "Eliana Costa"},
{"age": 45, "name": "Wilson Father"},
],
"totalAge": 123,
},
@@ -2814,9 +2825,9 @@ class TestQueryset(unittest.TestCase):
"_id": 2,
"value": {
"persons": [
{"age": 10, "name": "Igor Gabriel"},
{"age": 16, "name": "Isabella Luanna"},
{"age": 36, "name": "Sandra Mara"},
{"age": 10, "name": "Igor Gabriel"},
],
"totalAge": 62,
},
@@ -2826,8 +2837,8 @@ class TestQueryset(unittest.TestCase):
"_id": 3,
"value": {
"persons": [
{"age": 30, "name": "Arthur WA"},
{"age": 25, "name": "Paula Leonel"},
{"age": 30, "name": "Arthur WA"},
],
"totalAge": 55,
},
@@ -3108,6 +3119,7 @@ class TestQueryset(unittest.TestCase):
freq = Person.objects.item_frequencies("city", normalize=True, map_reduce=True)
assert freq == {"CRB": 0.5, None: 0.5}
@requires_mongodb_lt_42
def test_item_frequencies_with_null_embedded(self):
class Data(EmbeddedDocument):
name = StringField()
@@ -3136,6 +3148,7 @@ class TestQueryset(unittest.TestCase):
ot = Person.objects.item_frequencies("extra.tag", map_reduce=True)
assert ot == {None: 1.0, "friend": 1.0}
@requires_mongodb_lt_42
def test_item_frequencies_with_0_values(self):
class Test(Document):
val = IntField()
@@ -3150,6 +3163,7 @@ class TestQueryset(unittest.TestCase):
ot = Test.objects.item_frequencies("val", map_reduce=False)
assert ot == {0: 1}
@requires_mongodb_lt_42
def test_item_frequencies_with_False_values(self):
class Test(Document):
val = BooleanField()
@@ -3164,6 +3178,7 @@ class TestQueryset(unittest.TestCase):
ot = Test.objects.item_frequencies("val", map_reduce=False)
assert ot == {False: 1}
@requires_mongodb_lt_42
def test_item_frequencies_normalize(self):
class Test(Document):
val = IntField()
@@ -3550,7 +3565,8 @@ class TestQueryset(unittest.TestCase):
Book.objects.create(title="The Stories", authors=[mark_twain, john_tolkien])
authors = Book.objects.distinct("authors")
assert authors == [mark_twain, john_tolkien]
authors_names = {author.name for author in authors}
assert authors_names == {mark_twain.name, john_tolkien.name}
def test_distinct_ListField_EmbeddedDocumentField_EmbeddedDocumentField(self):
class Continent(EmbeddedDocument):
@@ -3587,7 +3603,8 @@ class TestQueryset(unittest.TestCase):
assert country_list == [scotland, tibet]
continent_list = Book.objects.distinct("authors.country.continent")
assert continent_list == [europe, asia]
continent_list_names = {c.continent_name for c in continent_list}
assert continent_list_names == {europe.continent_name, asia.continent_name}
def test_distinct_ListField_ReferenceField(self):
class Bar(Document):
@@ -5656,6 +5673,31 @@ class TestQueryset(unittest.TestCase):
qs = self.Person.objects().timeout(False)
assert qs._cursor_args == {"no_cursor_timeout": True}
@requires_mongodb_gte_44
def test_allow_disk_use(self):
qs = self.Person.objects()
assert qs._cursor_args == {}
qs = self.Person.objects().allow_disk_use(False)
assert qs._cursor_args == {}
qs = self.Person.objects().allow_disk_use(True)
assert qs._cursor_args == {"allow_disk_use": True}
# Test if allow_disk_use changes the results
self.Person.drop_collection()
self.Person.objects.create(name="Foo", age=12)
self.Person.objects.create(name="Baz", age=17)
self.Person.objects.create(name="Bar", age=13)
qs_disk = self.Person.objects().order_by("age").allow_disk_use(True)
qs = self.Person.objects().order_by("age")
assert qs_disk.count() == qs.count()
for index in range(qs_disk.count()):
assert qs_disk[index] == qs[index]
if __name__ == "__main__":
unittest.main()

View File

@@ -248,6 +248,34 @@ class TestQuerysetAggregate(MongoDBTestCase):
assert list(data) == [{"_id": p1.pk, "name": "ISABELLA LUANNA"}]
def test_queryset_aggregation_geonear_aggregation_on_pointfield(self):
"""test ensures that $geonear can be used as a 1-stage pipeline and that
MongoEngine does not interfer with such pipeline (#2473)
"""
class Aggr(Document):
name = StringField()
c = PointField()
Aggr.drop_collection()
agg1 = Aggr(name="X", c=[10.634584, 35.8245029]).save()
agg2 = Aggr(name="Y", c=[10.634584, 35.8245029]).save()
pipeline = [
{
"$geoNear": {
"near": {"type": "Point", "coordinates": [10.634584, 35.8245029]},
"distanceField": "c",
"spherical": True,
}
}
]
assert list(Aggr.objects.aggregate(*pipeline)) == [
{"_id": agg1.id, "c": 0.0, "name": "X"},
{"_id": agg2.id, "c": 0.0, "name": "Y"},
]
if __name__ == "__main__":
unittest.main()

View File

@@ -1,3 +1,4 @@
import operator
import unittest
import pytest
@@ -33,6 +34,14 @@ def get_as_pymongo(doc):
return doc.__class__.objects.as_pymongo().get(id=doc.id)
def requires_mongodb_lt_42(func):
return _decorated_with_ver_requirement(func, (4, 2), oper=operator.lt)
def requires_mongodb_gte_44(func):
return _decorated_with_ver_requirement(func, (4, 4), oper=operator.ge)
def _decorated_with_ver_requirement(func, mongo_version_req, oper):
"""Return a MongoDB version requirement decorator.

View File

@@ -1,5 +1,5 @@
[tox]
envlist = {py35,pypy3}-{mg34,mg36,mg39,mg311}
envlist = pypy3-{mg34,mg36,mg39,mg311}
[testenv]
commands =