8000 os.environ type signature partially incorrect in python 2 · Issue #872 · python/typeshed · GitHub
[go: up one dir, main page]

Skip to content

os.environ type signature partially incorrect in python 2 #872

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

Closed
lucaswiman opened this issue Jan 27, 2017 · 2 comments
Closed

os.environ type signature partially incorrect in python 2 #872

lucaswiman opened this issue Jan 27, 2017 · 2 comments
Labels
stubs: false positive Type checkers report false errors

Comments

@lucaswiman
Copy link
Contributor
lucaswiman commented Jan 27, 2017

The following code is valid and idiomatic Python 2 code, but does not typecheck under mypy --py2:

from __future__ import unicode_literals
import os

os.environ['key'] = 'value'

It yields the error:

os_environ.py:4: error: Invalid index type "unicode" for "MutableMapping"
os_environ.py:4: error: Incompatible types in assignment (expression has type "unicode", target has type "str")

From a bit of poking at it in the repl, it seems that os.environ is a dict-like object which functions a bit like cStringIO: it accepts either str or unicode objects, but throws a runtime encoding error when passed a unicode object which cannot be encoded to the ascii codec:

>>> os.environ[u'💣'] = u'🔥'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/lucaswiman/.pyenv/versions/2.7/lib/python2.7/os.py", line 473, in __setitem__
    putenv(key, item)
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)

In #869, I suggested replacing the type signature with MutableMapping[Union[str, unicode], Union[str, unicode]], to which @JukkaL replied:

This is potentially problematic, since this may break a lot of existing code using os.environ that assumes that it only has str keys and values (and there are other potential issues as well).

I think the type I suggested there is accurate, since annoyingly, these unicode objects' type information does seem to be retained and actually can break code at runtime that assumes it's only getting str:

>>> import io
>>> os.environ[u'key'] = u'value'
>>> set(map(type, os.environ.values()))
set([<type 'str'>, <type 'unicode'>])
>>> io.BytesIO(os.environ['key'])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'unicode' does not have the buffer interface

That said, if there is interest in something more backwards-compatible with previously annotated code, we could allow assignment of str key/values, but assume the actual contents of the mapping are str. I think the following update to os/__init__.pyi would achieve this effect, and might be a good compromise:

class _Environ(MutableMapping[str, str]):
    def __setitem__(self, key:Union[str, unicode], value:Union[str, unicode]) -> None: ...
    def copy(self) -> Dict[str, str]: ...

environ = ...  # type: _Environ

Please advise, and I'd be happy to submit a pull request once a decision has been reached.

@JelleZijlstra
Copy link
Member

Going to close this since Python 2 support is no longer a priority and there hasn't been much interest in changing this.

@lucaswiman
Copy link
Contributor Author

Going to close this since Python 2 support is no longer a priority and there hasn't been much interest in changing this.

Yup, makes sense. The codebase that prompted this issue was upgraded to Python 3 in 2019.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stubs: false positive Type checkers report false errors
Projects
None yet
Development

No branches or pull requests

4 participants
0