@@ -366,15 +366,15 @@ In this case we want to create a subclass of the ``datetime.datetime`` object th
366
366
`naive ` datetimes.
367
367
368
368
Here 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)
371
371
and the tests are in ``tests/unit/test_c_capsules.py ``.
372
372
373
373
--------------------------------
374
374
Writing the Code for the Object
375
375
--------------------------------
376
376
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 `` :
378
378
379
379
.. code-block :: c
380
380
@@ -421,8 +421,8 @@ Now the code for creating a new instance:
421
421
}
422
422
423
423
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 .
426
426
To do this we call the super class function and then check, and raise, if a ``tzinfo `` is absent.
427
427
This uses the utility function that call Python's ``super() `` function.
428
428
That 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:
473
473
.m_size = -1,
474
474
};
475
475
476
+ Initialise the module, this is when we use the existing capsule:
477
+
478
+ .. code-block :: c
479
+
476
480
PyMODINIT_FUNC
477
481
PyInit_datetimetz(void) {
478
482
PyObject *m = PyModule_Create(&datetimetzmodule);
@@ -635,6 +639,19 @@ The error is handled correctly by the superclass.
635
639
d.tzinfo = None
636
640
assert err.value.args[0 ] == " attribute 'tzinfo' of 'datetime.datetime' objects is not writable"
637
641
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
+
638
655
Some equality tests.
639
656
We want to fail when comparing our ``datetimetz `` with a naive ``datatime `` object.
640
657
@@ -659,7 +676,7 @@ We want to fail when comparing our ``datetimetz`` with a naive ``datatime`` obje
659
676
d_no_tz = datetime.datetime(2024 , 7 , 15 , 10 , 21 , 14 )
660
677
assert d_no_tz != d
661
678
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 ``
663
680
object.
664
681
665
682
.. code-block :: python
@@ -724,16 +741,3 @@ object.
724
741
d_tz - d
725
742
assert err.value.args[0 ] == " can't subtract offset-naive and offset-aware datetimes"
726
743
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