Can `Country.code` be `None` in v8.x?
After the addition of fields.pyi in d6968e3390a15008fa0ecda322b9454379e7ae6b, Country.code can now be None.
Looking at the actual implementation in Country.__init__(), which accepts code: str and then does:
self.code = self.countries.alpha2(code) or code
...it doesn't look like Country.code can actually ever be None?
Reason I'm asking is that we're running into ~20 typing warnings in our codebase when upgrading to django-countries 8.x because we've been under the belief that if we have a Country, we always have a code too.
Is this assumption no longer correct, or is the new Country.code type too wide?
Thanks for the trigger, there's reasoning here with recent changes around making the field nullable (it was either a call of backwards compatibility by always return a country object rather than None, so I decided that maybe returning a None-able country made more sense).
It made typing "interesting" to try and make pyright and mypy do the right thing with overloads depending on the nullable argument if it returned None. I gave up and just did the somewhat cheat way but the argument is still open for just not returning a country object at all in those cases, since the nullable case wasn't a thing before. Still makes typing more likely to choke when you can't rely on a country wheras you could before (unless you can fix the overload!). I'll have another think and look at it soon
I don't think the nullability should be defined in a field variable.
If a CountryField has null=True, that should be defined as follows:
from django.db.models import Field
from django.db.models.base import Model
from django_countries.fields import Country, CountryField
class SomeModel(Model):
country: Field[Country | None, Country | None] = CountryField(null=True, verbose_name=_('Country'))
Which means, SomeModel can have None as a country field, or an actual Country. Same goes for setting the field: either you assign an actual Country or None.