-
Notifications
You must be signed in to change notification settings - Fork 437
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Typing python-dotenv: may I submit this to typeshed? #172
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for this work, it's great!
I like typeshed, so I'm OK with adding stubs there, but I think it's better to put type hints in the code itself. Could you follow the recommendation in https://www.python.org/dev/peps/pep-0561/#packaging-type-information so that users of Python-dotenv don't need typeshed stubs to benefit from type checking? It consists in adding a py.typed
marker so that Mypy knows it can use inline type hints from this package.
Your concern about private APIs is legitimate. I think that type hints should not interfere with the development of this library too much and we can refine them incrementally. Therefore, when in doubt, it's definitely OK to omit type hints, ignore some type warnings or use Any
types. In particular, it's better than writing complicated type hints that will be hard for other developers to understand, or triggering type warnings when everything is fine (a false positive).
I've done a first pass of review (see inline comments). Other comments:
- Since the inline hints should be enough, I think you can remove the stubs (.pyi).
- The type hints need to be checked in CI. Could you add a mypy check to the
lint
tox env? I guess there should be two checks: one with--py2
and the other without.
src/dotenv/main.py
Outdated
("value", Optional[Text]), | ||
("original", Text)]) | ||
else: | ||
Binding = namedtuple("Binding", "key value original") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can remove this "else" branch because what you did in the "if" branch looks fine for both typing and execution.
src/dotenv/main.py
Outdated
if isinstance(self.dotenv_path, StringIO): | ||
yield self.dotenv_path | ||
elif os.path.isfile(self.dotenv_path): | ||
with io.open(self.dotenv_path) as stream: | ||
yield stream | ||
yield stream # type: ignore |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this type: ignore
necessary? I didn't get any errors if I removed it.
src/dotenv/main.py
Outdated
@@ -226,14 +273,17 @@ def unset_key(dotenv_path, key_to_unset, quote_mode="always"): | |||
dest.write(mapping.original) | |||
|
|||
if not removed: | |||
warnings.warn("key %s not removed from %s - key doesn't exist." % (key_to_unset, dotenv_path)) | |||
if not TYPE_CHECKING or sys.version_info >= (3, 0): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this obscures the code too much. I would probably just ignore the type warning for the line below. This applies to other uses of warnings.warn
.
src/dotenv/version.py
Outdated
@@ -1 +1 @@ | |||
__version__ = "0.10.1" | |||
__version__ = "0.10.1" # type: str |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mypy should infer the type of __version__
so it shouldn't be necessary to add a type hint for it.
src/dotenv/main.py
Outdated
if TYPE_CHECKING: | ||
dotenv_path = None # type: Union[Text,_PathLike, _StringIO] | ||
_dict = None # type: Optional[Dict[Text, Text]] | ||
verbose = None # type: bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can move these type hints to the assignments below in __init__
. This removes the need for if TYPE_CHECKING
and is probably more accurate since those aren't class variables.
src/dotenv/main.py
Outdated
@@ -135,11 +171,13 @@ def set_as_environment_variables(self, override=False): | |||
if isinstance(k, text_type) or isinstance(v, text_type): | |||
k = k.encode('ascii') | |||
v = v.encode('ascii') | |||
os.environ[k] = v | |||
if not TYPE_CHECKING or sys.version_info >= (3, 0): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this obscures the code too much. I would probably just ignore the type warning for the line below.
src/dotenv/main.py
Outdated
if not TYPE_CHECKING or sys.version_info >= (3, 0): | ||
warnings.warn("key %s not found in %s." % (key, self.dotenv_path)) | ||
|
||
return None # NOTE: PEP8 compliance required by mypy |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's OK to not have a comment here. PEP 8 compliance is implicit in the whole code base and removing this return None
shouldn't trigger a lint error (if linting is done in CI).
In short: I'm asking for permission to write type annotations for
python-dotenv
and include in the centralized repository called typeshed. In this case, this PR is just for a reference and can be closed. There's another option that I refine the quality of this PR and we start typecheckingpython-dotenv
itself.I wrote type annotations for
python-dotenv
which will be useful forpython-dotenv
users who also use mypy to typecheck their apps.I'd like to contribute this either:
I do not intend to have this PR merged as-is, rather I've included the changes for reference. In the contribution guide of typeshed, it states:
I was mainly interested in annotating public interfaces, so including this in typeshed is sufficient for me. I also annotated private interfaces but it may be unsatisfactory. However, there's still an option to include the type annotation in
python-dotenv
and use it for typecheckingpython-dotenv
itself.Quality of the current type annotation