Skip to content

Commit

Permalink
Add typing_extensions subfolder
Browse files Browse the repository at this point in the history
This pull request adds a 'typing_exensions' subproject to 'typing'. The
'typing_extensions' module backports any new additions to 'typing'
for Python 3.5+ users who are using older versions of 'typing' that were
bundled with their standard library (and so can't update to the latest
versions).

See python#435 for motivation and
additional context.
  • Loading branch information
Michael0x2a committed Jun 27, 2017
1 parent b11fbed commit 0d8bb61
Show file tree
Hide file tree
Showing 50 changed files with 32,286 additions and 0 deletions.
11 changes: 11 additions & 0 deletions typing_extensions/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
MANIFEST
build/
dist/
.tox/
.idea/
.cache/
__pycache__/
.mypy_cache/
tmp/
*.swp
*.pyc
79 changes: 79 additions & 0 deletions typing_extensions/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Typing Extensions

The `typing_extensions` module contains backports of recent changes
to the `typing` module that were not present in older versions of
`typing`.

This module is intended to be used mainly by people who are using
Python 3.5+, where the `typing` module is a part of the standard
library and cannot be updated to the latest version on PyPi.

Users of other Python versions should continue to install and use
use the `typing` module from PyPi instead of using this one, unless
they are specifically writing code intended to be compatible with
multiple versions of Python.

## Backported items

This module contains the following backported items:

### All Python versions:

- `ClassVar`
- `Collection`
- `ContextManager`
- `Counter`
- `DefaultDict`
- `Deque`
- `NewType`
- `NoReturn`
- `overload` (note that older versions of `typing` only let you use `overload` in stubs)
- `Text`
- `Type`
- `TYPE_CHECKING`

### Python 3.3+ only:

- `ChainMap`

### Python 3.5+ only:

- `AsyncIterable`
- `AsyncIterator`
- `AsyncContextManager`
- `Awaitable`
- `Coroutine`

### Python 3.6+ only:

- `AsyncGenerator`

## Other Notes and Limitations

There are a few types who's interface was modified between different
versions of typing. For example, `typing.Sequence` was modified to
subclass `typing.Reversible` as of Python 3.5.3.

These changes are _not_ backported to prevent subtle compatibility
issues when mixing the differing implementations of modified classes.

## Running tests

There are two different ways to test this module. The first is to simply run
each individual Python interpreter against `test_typing_extensions.py` in the
`src_py2` and `src_py3` folders.

However, because multiple versions of Python for each individual release
can be onerous, you can instead run `run_tests.py` using a single Python
interpreter. The `run_tests.py` file will essentially "modify" the standard
library by changing `PYTHONPATH` to point to individual folders in the
`test_data` repo.

Each individual folder contains a snapshot of the source code for the
`collections`, `typing,` and `abc` modules for that given release, letting us
test `typing` against those particular implementations.

`run_tests.py` will assume that you have Python 3.6.1 and a reasonably
modern version of Python 2.7 installed on your system, aliased to
`py -2.7` and `py -3.6` on Windows, and `python` and `python3` on Linux and
Mac.
110 changes: 110 additions & 0 deletions typing_extensions/run_tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#!/usr/bin/env python

from typing import List, Iterator, Tuple
from contextlib import contextmanager
import glob
import os
import os.path
import shutil
import subprocess
import sys
import textwrap

CORE_FILES_2 = [
"./src_py2/typing_extensions.py",
"./src_py2/test_typing_extensions.py"
]
CORE_FILES_3 = [
"./src_py3/typing_extensions.py",
"./src_py3/test_typing_extensions.py"
]
TEST_DIR = "test_data"

if sys.platform.startswith('win32'):
PYTHON2 = "py -2.7"
PYTHON3 = "py -3.6"
else:
PYTHON2 = "python"
PYTHON3 = "python3"


def get_test_dirs() -> List[str]:
"""Get all folders to test inside TEST_DIR."""
return list(glob.glob(os.path.join(TEST_DIR, "*")))


@contextmanager
def temp_copy(src_files: List[str], dest_dir: str) -> Iterator[None]:
"""
A context manager that temporarily copies the given files to the
given destination directory, and deletes those temp files upon
exiting.
"""
# Copy
for src_path in src_files:
shutil.copy(src_path, dest_dir)

yield

# Delete
for src_path in src_files:
dst_path = os.path.join(dest_dir, os.path.basename(src_path))
os.remove(dst_path)


@contextmanager
def change_directory(dir_path: str) -> Iterator[None]:
"""
A context manager that temporarily changes the working directory
to the specified directory, and changes back to the original
upon exiting.
"""
original = os.getcwd()
os.chdir(dir_path)

yield

os.chdir(original)


def run_shell(command: str) -> Tuple[bool, str]:
env = os.environ.copy()
env["PYTHONPATH"] = ":".join([os.getcwd(), env["PYTHONPATH"], env["PATH"]])
out = subprocess.run(
command,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
shell=True,
env=env)
success = out.returncode == 0
stdout = '' if out.stdout is None else out.stdout.decode('utf-8')
return (success, stdout)


def main() -> int:
test_dirs = get_test_dirs()
exit_code = 0
for test_dir in test_dirs:
_, version_number = test_dir.split('-')
py2 = version_number.startswith("2")
print("Testing Python {}".format(version_number))

core_files = CORE_FILES_2 if py2 else CORE_FILES_3
python_exe = PYTHON2 if py2 else PYTHON3

with temp_copy(core_files, test_dir), change_directory(test_dir):
success, output = run_shell("{} {} {}".format(
python_exe,
"test_typing_extensions.py",
version_number))
if success:
print(" All tests passed!")
else:
print(textwrap.indent(output, " "))
exit_code = 1
return exit_code


if __name__ == '__main__':
sys.exit(main())

71 changes: 71 additions & 0 deletions typing_extensions/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#!/usr/bin/env python
# coding: utf-8

import sys
from distutils.core import setup

if sys.version_info < (2, 7, 0) or (3, 0, 0) <= sys.version_info < (3, 3, 0):
sys.stderr.write('ERROR: You need Python 2.7 or 3.3+ '
'to install the typing package.\n')
exit(1)

version = '3.6.1'
description = 'Type Hint backports for Python 3.5+'
long_description = '''\
Typing -- Type Hints for Python
This is a backport of the standard library typing module to Python
versions 3.5+. The typing module has seen several changes since it was
first added in Python 3.5.0, which means people who are using 3.5.0+
but are unable to upgrade to the latest version of Python are unable
to take advantage of some new features of the typing library, such as
typing.Type or typing.Coroutine.
This module allows those users to use the latest additions to the typing
module without worrying about naming conflicts with the standard library.
Users of Python 2.7, 3.3, and 3.4 should install the typing module
from pypi and use that directly, except when writing code that needs to
be compatible across multiple versions of Python.
'''

classifiers = [
'Development Status :: 5 - Production/Stable',
'Environment :: Console',
'Intended Audience :: Developers',
'License :: OSI Approved :: Python Software Foundation License',
'Operating System :: OS Independent',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Topic :: Software Development',
]

if sys.version_info.major == 2:
package_dir = 'src_py2'
elif sys.version_info.major == 3:
package_dir = 'src_py3'
else:
raise AssertionError()

install_requires = []
if sys.version_info < (3, 5):
install_requires.append('typing >= 3.6.1')

setup(name='typing_extensions',
version=version,
description=description,
long_description=long_description,
author='Guido van Rossum, Jukka Lehtosalo, Lukasz Langa, Michael Lee',
author_email='jukka.lehtosalo@iki.fi',
# TODO: Change URL
url='https://github.com/michael0x2a/typing_extensions',
license='PSF',
keywords='typing function annotations type hints hinting checking '
'checker typehints typehinting typechecking backport',
package_dir={'': package_dir},
py_modules=['typing_extensions'],
classifiers=classifiers,
install_requires=install_requires,
)
Loading

0 comments on commit 0d8bb61

Please sign in to comment.