Repository: antonagestam/phantom-types (language: python)

Issue:
Add tests for bound erasure for shipped types
Make sure access to methods of the bound type doesn't raise mypy errors.

[This fix](https://github.com/antonagestam/phantom-types/pull/82) solves that for the TZ types, there should be mypy tests asserting that `cast(TZAware, object()).isoformat()` doesn't raise a attr-doesn't-exist error.


Discussion / hints:

Fix patch:
diff --git a/src/phantom/datetime.py b/src/phantom/datetime.py
index 1417b96..150dbea 100644
--- a/src/phantom/datetime.py
+++ b/src/phantom/datetime.py
@@ -20,6 +20,10 @@ class TZAware(datetime.datetime, Phantom, predicate=is_tz_aware):
     True
     """
 
+    # A property of being aware is (dt.tzinfo != None), so we can safely narrow this
+    # attribute to not include None.
+    tzinfo: datetime.tzinfo
+
     @classmethod
     def __schema__(cls) -> Schema:
         return {


Test patch:
diff --git a/tests/test_datetime.yaml b/tests/test_datetime.yaml
index bd0404f..dfd203d 100644
--- a/tests/test_datetime.yaml
+++ b/tests/test_datetime.yaml
@@ -19,3 +19,23 @@
       TZAware.parse(datetime.datetime.now(tz=datetime.timezone.utc))
     )
     reveal_type(b) # N: Revealed type is "phantom.datetime.TZAware"
+- case: narrowing_to_tz_aware_makes_tzinfo_non_optional
+  main: |
+    import datetime
+    from phantom.datetime import TZAware
+
+    dt: datetime.datetime
+    reveal_type(dt.tzinfo) # N: Revealed type is "Union[datetime.tzinfo, None]"
+    assert isinstance(dt, TZAware)
+    reveal_type(dt.tzinfo) # N: Revealed type is "datetime.tzinfo"
+- case: bound_is_not_erased
+  main: |
+    import datetime
+    from phantom.datetime import TZAware, TZNaive
+
+    o: datetime.datetime
+    aware = TZAware.parse(o)
+    naive = TZNaive.parse(o)
+
+    reveal_type(aware.month) # N: Revealed type is "builtins.int"
+    reveal_type(naive.month) # N: Revealed type is "builtins.int"