Skip to content

Commit 3cf968e

Browse files
authored
Merge branch 'mongodb-labs:main' into INTPYTHON-348
2 parents ce2138b + 221a282 commit 3cf968e

File tree

10 files changed

+164
-21
lines changed

10 files changed

+164
-21
lines changed

.github/workflows/test-python.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ jobs:
6363
dates
6464
datetimes
6565
db_functions
66+
dbshell_
6667
delete
6768
delete_regress
6869
empty

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ You can create a new project that's configured based on these steps using a
1919
project template:
2020

2121
```bash
22-
$ django-admin startproject mysite --template https://github.com/aclark4life/django-mongodb-project/archive/refs/heads/5.0.x.zip
22+
$ django-admin startproject mysite --template https://github.com/mongodb-labs/django-mongodb-project/archive/refs/heads/5.0.x.zip
2323
```
2424
(where "5.0" matches the version of Django that you're using.)
2525

@@ -97,7 +97,7 @@ Alternatively, you can use the following `startapp` template which includes
9797
this change:
9898

9999
```bash
100-
$ python manage.py startapp myapp --template https://github.com/aclark4life/django-mongodb-app/archive/refs/heads/5.0.x.zip
100+
$ python manage.py startapp myapp --template https://github.com/mongodb-labs/django-mongodb-app/archive/refs/heads/5.0.x.zip
101101
```
102102
(where "5.0" matches the version of Django that you're using.)
103103

django_mongodb/fields/auto.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ def get_prep_value(self, value):
3434
def db_type(self, connection):
3535
return "objectId"
3636

37+
def rel_db_type(self, connection):
38+
return "objectId"
39+
3740
def to_python(self, value):
3841
if value is None or isinstance(value, int):
3942
return value

pyproject.toml

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ dependencies = [
3737
]
3838

3939
[project.optional-dependencies]
40-
test = ["pytest>=7"]
4140
docs = [ "sphinx>=7"]
4241

4342
[project.urls]
@@ -49,18 +48,6 @@ Tracker = "https://github.com/mongodb-labs/django-mongodb/issues"
4948
[tool.setuptools.dynamic]
5049
version = {attr = "django_mongodb.__version__"}
5150

52-
[tool.pytest.ini_options]
53-
minversion = "7"
54-
addopts = ["-ra", "--strict-config", "--strict-markers", "--junitxml=xunit-results/TEST-results.xml"]
55-
testpaths = ["test"]
56-
log_cli_level = "INFO"
57-
norecursedirs = ["test/*"]
58-
faulthandler_timeout = 1500
59-
xfail_strict = true
60-
filterwarnings = [
61-
"error"
62-
]
63-
6451
[tool.mypy]
6552
strict = true
6653
show_error_codes = true
@@ -87,7 +74,6 @@ select = [
8774
"PGH", # pygrep-hooks
8875
"PIE", # flake8-pie
8976
"PL", # pylint
90-
"PT", # flake8-pytest-style
9177
"PTH", # flake8-use-pathlib
9278
"RET", # flake8-return
9379
"RUF", # Ruff-specific

test/test_basic.py

Lines changed: 0 additions & 5 deletions
This file was deleted.

tests/dbshell_/__init__.py

Whitespace-only changes.

tests/dbshell_/tests.py

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import signal
2+
from unittest import mock
3+
4+
from django.db import connection
5+
from django.test import SimpleTestCase
6+
7+
from django_mongodb.client import DatabaseClient
8+
9+
10+
class MongoDbshellTests(SimpleTestCase):
11+
def settings_to_cmd_args_env(self, settings_dict, parameters=None):
12+
if parameters is None:
13+
parameters = []
14+
return DatabaseClient.settings_to_cmd_args_env(settings_dict, parameters)
15+
16+
def test_fails_with_keyerror_on_incomplete_config(self):
17+
with self.assertRaises(KeyError):
18+
self.settings_to_cmd_args_env({})
19+
20+
def test_basic_params_specified_in_settings(self):
21+
for options_parameters in [(None, None, None), ("value1", "value2", True)]:
22+
with self.subTest(keys=options_parameters):
23+
authentication_database, authentication_mechanism, retry_writes = options_parameters
24+
if authentication_database is not None:
25+
expected_args = [
26+
"mongosh",
27+
"--host",
28+
"somehost",
29+
"--port",
30+
444,
31+
"--username",
32+
"someuser",
33+
"--password",
34+
"somepassword",
35+
"--retryWrites",
36+
"true",
37+
"somedbname",
38+
]
39+
else:
40+
expected_args = [
41+
"mongosh",
42+
"--host",
43+
"somehost",
44+
"--port",
45+
444,
46+
"--username",
47+
"someuser",
48+
"--password",
49+
"somepassword",
50+
"somedbname",
51+
]
52+
53+
self.assertEqual(
54+
self.settings_to_cmd_args_env(
55+
{
56+
"NAME": "somedbname",
57+
"USER": "someuser",
58+
"PASSWORD": "somepassword",
59+
"HOST": "somehost",
60+
"PORT": 444,
61+
"OPTIONS": {
62+
"authenticationDatabase": authentication_database,
63+
"authenticationMechanism": authentication_mechanism,
64+
"retryWrites": retry_writes,
65+
},
66+
}
67+
),
68+
(expected_args, None),
69+
)
70+
71+
def test_options_override_settings_proper_values(self):
72+
settings_port = 444
73+
options_port = 555
74+
self.assertNotEqual(settings_port, options_port, "test pre-req")
75+
expected_args = [
76+
"mongosh",
77+
"--host",
78+
"settinghost",
79+
"--port",
80+
444,
81+
"--username",
82+
"settinguser",
83+
"--password",
84+
"settingpassword",
85+
"settingdbname",
86+
]
87+
expected_env = None
88+
89+
self.assertEqual(
90+
self.settings_to_cmd_args_env(
91+
{
92+
"NAME": "settingdbname",
93+
"USER": "settinguser",
94+
"PASSWORD": "settingpassword",
95+
"HOST": "settinghost",
96+
"PORT": settings_port,
97+
"OPTIONS": {"port": options_port},
98+
}
99+
),
100+
(expected_args, expected_env),
101+
)
102+
103+
def test_sigint_handler(self):
104+
"""SIGINT is ignored in Python and passed to Mongodb to abort queries."""
105+
106+
def _mock_subprocess_run(*args, **kwargs): # noqa: ARG001
107+
handler = signal.getsignal(signal.SIGINT)
108+
self.assertEqual(handler, signal.SIG_IGN)
109+
110+
sigint_handler = signal.getsignal(signal.SIGINT)
111+
# The default handler isn't SIG_IGN.
112+
self.assertNotEqual(sigint_handler, signal.SIG_IGN)
113+
with mock.patch("subprocess.run", new=_mock_subprocess_run):
114+
connection.client.runshell([])
115+
# dbshell restores the original handler.
116+
self.assertEqual(sigint_handler, signal.getsignal(signal.SIGINT))

tests/queries_/__init__.py

Whitespace-only changes.

tests/queries_/models.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from django.db import models
2+
3+
4+
class Author(models.Model):
5+
name = models.CharField(max_length=10)
6+
7+
def __str__(self):
8+
return self.name
9+
10+
11+
class Book(models.Model):
12+
title = models.CharField(max_length=10)
13+
author = models.ForeignKey(Author, models.CASCADE)
14+
15+
def __str__(self):
16+
return self.title

tests/queries_/test_mql.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
from django.test import TestCase
2+
3+
from .models import Author, Book
4+
5+
6+
class MQLTests(TestCase):
7+
def test_all(self):
8+
with self.assertNumQueries(1) as ctx:
9+
list(Author.objects.all())
10+
query = ctx.captured_queries[0]["sql"]
11+
self.assertEqual(query, "db.queries__author.aggregate([{'$match': {'$expr': {}}}])")
12+
13+
def test_join(self):
14+
with self.assertNumQueries(1) as ctx:
15+
list(Book.objects.filter(author__name="Bob"))
16+
query = ctx.captured_queries[0]["sql"]
17+
self.assertEqual(
18+
query,
19+
"db.queries__book.aggregate(["
20+
"{'$lookup': {'from': 'queries__author', "
21+
"'let': {'parent__field__0': '$author_id'}, "
22+
"'pipeline': [{'$match': {'$expr': "
23+
"{'$and': [{'$eq': ['$$parent__field__0', '$_id']}]}}}], 'as': 'queries__author'}}, "
24+
"{'$unwind': '$queries__author'}, "
25+
"{'$match': {'$expr': {'$eq': ['$queries__author.name', 'Bob']}}}])",
26+
)

0 commit comments

Comments
 (0)