From 553ed7152727630fedaaaa6afb36ac7a871402a6 Mon Sep 17 00:00:00 2001 From: Sooraj Sivadasan Date: Wed, 12 Nov 2025 22:59:38 +0530 Subject: [PATCH] fix: modify `datetime.datetime.utcnow()` to `datetime.datetime.now(datetime.timezone.utc)` inside test since utcnow() is deprecated from 3.12 onwards fix: change code inside `defining-documents.rst` and `signals.rst` to accommodate `datetime.datetime.utcnow()`` --- docs/guide/defining-documents.rst | 12 +++++------ docs/guide/signals.rst | 6 +++--- tests/document/test_instance.py | 6 +++--- tests/document/test_timeseries_collection.py | 10 ++++----- tests/fields/test_complex_datetime_field.py | 22 +++++++++++++------- tests/fields/test_datetime_field.py | 5 +++-- tests/fields/test_fields.py | 20 ++++++++++++------ tests/queryset/test_queryset.py | 5 +++-- 8 files changed, 51 insertions(+), 35 deletions(-) diff --git a/docs/guide/defining-documents.rst b/docs/guide/defining-documents.rst index c71bc23c1..6448b3fb5 100644 --- a/docs/guide/defining-documents.rst +++ b/docs/guide/defining-documents.rst @@ -22,7 +22,7 @@ objects** as class attributes to the document class:: class Page(Document): title = StringField(max_length=200, required=True) - date_modified = DateTimeField(default=datetime.datetime.utcnow) + date_modified = DateTimeField(default=datetime.datetime.now(datetime.timezone.utc)) As BSON (the binary format for storing data in mongodb) is order dependent, documents are serialized based on their field order. @@ -274,7 +274,7 @@ store; in this situation a :class:`~mongoengine.fields.DictField` is appropriate user = ReferenceField(User) answers = DictField() - survey_response = SurveyResponse(date=datetime.utcnow(), user=request.user) + survey_response = SurveyResponse(date=datetime.datetime.now(datetime.timezone.utc), user=request.user) response_form = ResponseForm(request.POST) survey_response.answers = response_form.cleaned_data() survey_response.save() @@ -689,7 +689,7 @@ collection after a given period. See the official documentation for more information. A common usecase might be session data:: class Session(Document): - created = DateTimeField(default=datetime.utcnow) + created = DateTimeField(default=datetime.datetime.now(datetime.timezone.utc)) meta = { 'indexes': [ {'fields': ['created'], 'expireAfterSeconds': 3600} @@ -717,7 +717,7 @@ A default ordering can be specified for your :class:`~mongoengine.queryset.QuerySet` is created, and can be overridden by subsequent calls to :meth:`~mongoengine.queryset.QuerySet.order_by`. :: - from datetime import datetime + from datetime import datetime,timezone class BlogPost(Document): title = StringField() @@ -812,7 +812,7 @@ the class name in every documents. When a document is loaded, MongoEngine checks it's :attr:`_cls` attribute and use that class to construct the instance.:: Page(title='a funky title').save() - DatedPage(title='another title', date=datetime.utcnow()).save() + DatedPage(title='another title', date=datetime.now(timezone.utc)).save() print(Page.objects().count()) # 2 print(DatedPage.objects().count()) # 1 @@ -823,7 +823,7 @@ it's :attr:`_cls` attribute and use that class to construct the instance.:: print(list(qs)) # [ # {'_cls': u 'Page', 'title': 'a funky title'}, - # {'_cls': u 'Page.DatedPage', 'title': u 'another title', 'date': datetime.datetime(2019, 12, 13, 20, 16, 59, 993000)} + # {'_cls': u 'Page.DatedPage', 'title': u 'another title', 'date': datetime(2019, 12, 13, 20, 16, 59, 993000)} # ] Working with existing data diff --git a/docs/guide/signals.rst b/docs/guide/signals.rst index e52146102..0760bdd4e 100644 --- a/docs/guide/signals.rst +++ b/docs/guide/signals.rst @@ -74,13 +74,13 @@ Attaching Events After writing a handler function like the following:: import logging - from datetime import datetime + from datetime import datetime,timezone from mongoengine import * from mongoengine import signals def update_modified(sender, document): - document.modified = datetime.utcnow() + document.modified = datetime.now(timezone.utc) You attach the event handler to your :class:`~mongoengine.Document` or :class:`~mongoengine.EmbeddedDocument` subclass:: @@ -139,7 +139,7 @@ cleaner looking while still allowing manual execution of the callback:: @handler(signals.pre_save) def update_modified(sender, document): - document.modified = datetime.utcnow() + document.modified = datetime.now(timezone.utc) @update_modified.apply class Record(Document): diff --git a/tests/document/test_instance.py b/tests/document/test_instance.py index c15000726..4d6ae2278 100644 --- a/tests/document/test_instance.py +++ b/tests/document/test_instance.py @@ -4,7 +4,7 @@ import unittest import uuid import weakref -from datetime import datetime +from datetime import datetime, timezone from unittest.mock import Mock import bson @@ -3544,7 +3544,7 @@ class Test(Document): def test_default_values_dont_get_override_upon_save_when_only_is_used(self): class Person(Document): - created_on = DateTimeField(default=lambda: datetime.utcnow()) + created_on = DateTimeField(default=lambda: datetime.now(timezone.utc)) name = StringField() p = Person(name="alon") @@ -3558,7 +3558,7 @@ class Person(Document): assert orig_created_on == p3.created_on class Person(Document): - created_on = DateTimeField(default=lambda: datetime.utcnow()) + created_on = DateTimeField(default=lambda: datetime.now(timezone.utc)) name = StringField() height = IntField(default=189) diff --git a/tests/document/test_timeseries_collection.py b/tests/document/test_timeseries_collection.py index 46d209b6a..6422c5d98 100644 --- a/tests/document/test_timeseries_collection.py +++ b/tests/document/test_timeseries_collection.py @@ -1,6 +1,6 @@ import time import unittest -from datetime import datetime, timedelta +from datetime import datetime, timedelta, timezone from mongoengine import ( DateTimeField, @@ -84,7 +84,7 @@ def test_insert_document_into_timeseries_collection(self): assert collection_name in self.db.list_collection_names() # Insert a document and ensure it was inserted - self.SensorData(timestamp=datetime.utcnow(), temperature=23.4).save() + self.SensorData(timestamp=datetime.now(timezone.utc), temperature=23.4).save() assert collection.count_documents({}) == 1 @requires_mongodb_gte_50 @@ -98,7 +98,7 @@ def test_timeseries_expiration(self): assert options.get("timeseries", {}) is not None assert options["expireAfterSeconds"] == 1 - self.SensorData(timestamp=datetime.utcnow(), temperature=23.4).save() + self.SensorData(timestamp=datetime.now(timezone.utc), temperature=23.4).save() assert collection.count_documents({}) == 1 @@ -144,7 +144,7 @@ def test_timeseries_data_insertion_order(self): self.SensorData._get_collection() # Insert documents out of order - now = datetime.utcnow() + now = datetime.now(timezone.utc) self.SensorData(timestamp=now, temperature=23.4).save() self.SensorData(timestamp=now - timedelta(seconds=5), temperature=22.0).save() self.SensorData(timestamp=now + timedelta(seconds=5), temperature=24.0).save() @@ -164,7 +164,7 @@ def test_timeseries_query_by_time_range(self): self.SensorData._get_collection_name() self.SensorData._get_collection() - now = datetime.utcnow() + now = datetime.now(timezone.utc) self.SensorData(timestamp=now - timedelta(seconds=10), temperature=22.0).save() self.SensorData(timestamp=now - timedelta(seconds=5), temperature=23.0).save() self.SensorData(timestamp=now, temperature=24.0).save() diff --git a/tests/fields/test_complex_datetime_field.py b/tests/fields/test_complex_datetime_field.py index 205fb22f6..b78df1bcd 100644 --- a/tests/fields/test_complex_datetime_field.py +++ b/tests/fields/test_complex_datetime_field.py @@ -163,34 +163,40 @@ class Log(Document): assert fetched_log.timestamp is None def test_default_static_value(self): - NOW = datetime.datetime.utcnow() + NOW_UTC = datetime.datetime.now(datetime.timezone.utc) + NOW_NAIVE = NOW_UTC.replace(tzinfo=None) class Log(Document): - timestamp = ComplexDateTimeField(default=NOW) + timestamp = ComplexDateTimeField(default=NOW_UTC) Log.drop_collection() log = Log() - assert log.timestamp == NOW + assert log.timestamp == NOW_NAIVE log.save() fetched_log = Log.objects.with_id(log.id) - assert fetched_log.timestamp == NOW + assert fetched_log.timestamp == NOW_NAIVE def test_default_callable(self): - NOW = datetime.datetime.utcnow() + NOW_UTC = datetime.datetime.now(datetime.timezone.utc) + NOW_NAIVE = NOW_UTC.replace(tzinfo=None) class Log(Document): - timestamp = ComplexDateTimeField(default=datetime.datetime.utcnow) + timestamp = ComplexDateTimeField( + default=lambda: datetime.datetime.now(datetime.timezone.utc) + ) Log.drop_collection() log = Log() - assert log.timestamp >= NOW + assert ( + log.timestamp >= NOW_NAIVE + ) # since ComplexDateTimeField returns naive timestamp without timezone log.save() fetched_log = Log.objects.with_id(log.id) - assert fetched_log.timestamp >= NOW + assert fetched_log.timestamp >= NOW_NAIVE def test_setting_bad_value_does_not_raise_unless_validate_is_called(self): # test regression of #2253 diff --git a/tests/fields/test_datetime_field.py b/tests/fields/test_datetime_field.py index d04f39b04..767178f63 100644 --- a/tests/fields/test_datetime_field.py +++ b/tests/fields/test_datetime_field.py @@ -1,4 +1,5 @@ import datetime as dt +from datetime import timezone import pytest @@ -45,9 +46,9 @@ def test_default_value_utcnow(self): """ class Person(Document): - created = DateTimeField(default=dt.datetime.utcnow) + created = DateTimeField(default=lambda: dt.datetime.now(dt.timezone.utc)) - utcnow = dt.datetime.utcnow() + utcnow = dt.datetime.now(timezone.utc) person = Person() person.validate() person_created_t0 = person.created diff --git a/tests/fields/test_fields.py b/tests/fields/test_fields.py index c58f8a842..ae413769b 100644 --- a/tests/fields/test_fields.py +++ b/tests/fields/test_fields.py @@ -89,7 +89,9 @@ class Person(Document): name = StringField() age = IntField(default=30, required=False) userid = StringField(default=lambda: "test", required=True) - created = DateTimeField(default=datetime.datetime.utcnow) + created = DateTimeField( + default=lambda: datetime.datetime.now(datetime.timezone.utc) + ) day = DateField(default=datetime.date.today) person = Person(name="Ross") @@ -169,7 +171,9 @@ class Person(Document): name = StringField() age = IntField(default=30, required=False) userid = StringField(default=lambda: "test", required=True) - created = DateTimeField(default=datetime.datetime.utcnow) + created = DateTimeField( + default=lambda: datetime.datetime.now(datetime.timezone.utc) + ) # Trying setting values to None person = Person(name=None, age=None, userid=None, created=None) @@ -203,7 +207,9 @@ class Person(Document): name = StringField() age = IntField(default=30, required=False) userid = StringField(default=lambda: "test", required=True) - created = DateTimeField(default=datetime.datetime.utcnow) + created = DateTimeField( + default=lambda: datetime.datetime.now(datetime.timezone.utc) + ) person = Person() person.name = None @@ -271,7 +277,9 @@ class Person(Document): name = StringField() age = IntField(default=30, required=False) userid = StringField(default=lambda: "test", required=True) - created = DateTimeField(default=datetime.datetime.utcnow) + created = DateTimeField( + default=lambda: datetime.datetime.now(datetime.timezone.utc) + ) person = Person( name="Ross", @@ -336,7 +344,7 @@ class HandleNoneFields(Document): doc.str_fld = "spam ham egg" doc.int_fld = 42 doc.flt_fld = 4.2 - doc.com_dt_fld = datetime.datetime.utcnow() + doc.com_dt_fld = datetime.datetime.now(datetime.timezone.utc) doc.save() res = HandleNoneFields.objects(id=doc.id).update( @@ -372,7 +380,7 @@ class HandleNoneFields(Document): doc.str_fld = "spam ham egg" doc.int_fld = 42 doc.flt_fld = 4.2 - doc.comp_dt_fld = datetime.datetime.utcnow() + doc.comp_dt_fld = datetime.datetime.now(datetime.timezone.utc) doc.save() # Unset all the fields diff --git a/tests/queryset/test_queryset.py b/tests/queryset/test_queryset.py index 8386249f2..44b640156 100644 --- a/tests/queryset/test_queryset.py +++ b/tests/queryset/test_queryset.py @@ -1554,7 +1554,8 @@ class BlogPost(Document): meta = {"ordering": ["-published_date"]} BlogPost.objects.create( - title="whatever", published_date=datetime.datetime.utcnow() + title="whatever", + published_date=datetime.datetime.now(datetime.timezone.utc), ) with db_ops_tracker() as q: @@ -3114,7 +3115,7 @@ class Link(Document): Link.drop_collection() - now = datetime.datetime.utcnow() + now = datetime.datetime.now(datetime.timezone.utc) # Note: Test data taken from a custom Reddit homepage on # Fri, 12 Feb 2010 14:36:00 -0600. Link ordering should