@@ -366,15 +366,15 @@ In this case we want to create a subclass of the ``datetime.datetime`` object th
366366`naive ` datetimes.
367367
368368Here is the C Extension code to create a ``datetimetz `` module and a ``datetimetz.datetimetz `` object.
369- This code is lightly edited for clarity and works with Python 3.10+.
370- The actual code is in ``src/cpy/Capsules/datetimetz.c `` (which works with Python 3.9 as well)
369+ This code is lightly edited for clarity and works with Python 3.10+ (using the modern API) .
370+ The actual code is in ``src/cpy/Capsules/datetimetz.c `` (which works with the Python 3.9 API as well)
371371and the tests are in ``tests/unit/test_c_capsules.py ``.
372372
373373--------------------------------
374374Writing the Code for the Object
375375--------------------------------
376376
377- Firstly the declaration of the timezone aware datetime, it just inherits from ``datetime.datetime ``:
377+ Firstly the declaration of the timezone aware datetime, it just inherits from ``datetime.datetime `` :
378378
379379.. code-block :: c
380380
@@ -421,8 +421,8 @@ Now the code for creating a new instance:
421421 }
422422
423423 So far a new ``datetimetz `` object must be created with a ``tzinfo `` but the ``datetime.datetime `` has an API
424- ``replace `` that creates a new datetime with different properties, including ``tzinfo ``.
425- We need to guard against the user trying to change the timezone.
424+ ``replace() `` that creates a new datetime with different properties, including ``tzinfo ``.
425+ We need to guard against the user trying to change the timezone to None .
426426To do this we call the super class function and then check, and raise, if a ``tzinfo `` is absent.
427427This uses the utility function that call Python's ``super() `` function.
428428That code is in ``src/cpy/Util/py_call_super.h `` and ``src/cpy/Util/py_call_super.c ``:
@@ -473,6 +473,10 @@ Finally the module code:
473473 .m_size = -1,
474474 };
475475
476+ Initialise the module, this is when we use the existing capsule:
477+
478+ .. code-block :: c
479+
476480 PyMODINIT_FUNC
477481 PyInit_datetimetz(void) {
478482 PyObject *m = PyModule_Create(&datetimetzmodule);
@@ -635,6 +639,19 @@ The error is handled correctly by the superclass.
635639 d.tzinfo = None
636640 assert err.value.args[0 ] == " attribute 'tzinfo' of 'datetime.datetime' objects is not writable"
637641
642+ Check that ``.replace() `` works as expected with ``tzinfo ``:
643+
644+ .. code-block :: python
645+
646+ def test_datetimetz_datetimetz_replace_raises_tzinfo ():
647+ d = datetimetz.datetimetz(
648+ 2024 , 7 , 15 , 10 , 21 , 14 ,
649+ tzinfo = zoneinfo.ZoneInfo(' Europe/London' )
650+ )
651+ with pytest.raises(TypeError ) as err:
652+ d.replace(tzinfo = None )
653+ assert err.value.args[0 ] == ' No time zone provided.'
654+
638655 Some equality tests.
639656We want to fail when comparing our ``datetimetz `` with a naive ``datatime `` object.
640657
@@ -659,7 +676,7 @@ We want to fail when comparing our ``datetimetz`` with a naive ``datatime`` obje
659676 d_no_tz = datetime.datetime(2024 , 7 , 15 , 10 , 21 , 14 )
660677 assert d_no_tz != d
661678
662- Some datetime comparison tests that show our ``datetimetz `` inter-operates correctly with itself and a ``datetime ``
679+ Some datetime subtraction tests that show our ``datetimetz `` inter-operates correctly with itself and a ``datetime ``
663680object.
664681
665682.. code-block :: python
@@ -724,16 +741,3 @@ object.
724741 d_tz - d
725742 assert err.value.args[0 ] == " can't subtract offset-naive and offset-aware datetimes"
726743
727- Check that ``.replace() `` works as expected with ``tzinfo ``:
728-
729- .. code-block :: python
730-
731- def test_datetimetz_datetimetz_replace_raises_tzinfo ():
732- d = datetimetz.datetimetz(
733- 2024 , 7 , 15 , 10 , 21 , 14 ,
734- tzinfo = zoneinfo.ZoneInfo(' Europe/London' )
735- )
736- with pytest.raises(TypeError ) as err:
737- d.replace(tzinfo = None )
738- assert err.value.args[0 ] == ' No time zone provided.'
739-
0 commit comments