Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
0684a4d
Remove Python 2/3 specific code.
groutr Jul 13, 2019
b052943
Remove compatibility import.
groutr Jul 13, 2019
cf9979a
Drop python 2 support.
groutr Jul 13, 2019
c12d2d7
Drop Python 2 compatibility.
groutr Jul 13, 2019
5f5ca40
Remove Python 2 compatibility.
groutr Jul 13, 2019
bd3f3fe
Remove Python 2 compatibility.
groutr Jul 13, 2019
3560b2b
Remove Python 2 compatibility.
groutr Jul 13, 2019
d567665
Remove errant if statement.
groutr Jul 13, 2019
85326bd
Remove Python 2 compatibility.
groutr Jul 13, 2019
80ae197
Fix missed items call.
groutr Jul 13, 2019
50287b5
Update tests.
groutr Jul 13, 2019
22ba48f
Fix Python specific tests.
groutr Jul 13, 2019
2ddfd0e
Add map and filter to toolz namespace.
groutr Jul 13, 2019
eab69e6
Remove Python 2.7 from test travis.yml.
groutr Jul 13, 2019
9f4ab2f
Fix sandbox tests.
groutr Jul 13, 2019
b281dde
Add missing reduce import.
groutr Jul 13, 2019
aa6d33e
Remove Python 3.4 support.
groutr Jul 13, 2019
e4416e0
"Hardcode" Python 3 support.
groutr Jul 13, 2019
03becaa
Add PyPy3.
groutr Jul 13, 2019
72cf975
Make pycodestyle happy.
groutr Jul 13, 2019
373f620
Address another pycodestyle complaint.
groutr Jul 13, 2019
268501d
Merge branch 'master' into python3
groutr Oct 17, 2019
91edafa
Remove ending line.
groutr Oct 17, 2019
66527cf
Update documentation.
groutr Oct 17, 2019
8c64cca
Add pypy 7.2 to TravisCI.
groutr Oct 17, 2019
1f52206
Pypy3.6 try 2.
groutr Oct 17, 2019
b1aad68
Add Python 3.8 to TravisCI.
groutr Oct 17, 2019
6bfbe7b
Add Python 3.8 try 2.
groutr Oct 17, 2019
62a2470
Revert "Add Python 3.8 try 2."
groutr Oct 17, 2019
72f7972
Merge branch 'master' into python3
groutr Jan 6, 2020
30b5e8e
Fix mapping import for Python 3.
groutr Jan 6, 2020
3b5afe9
Revert "Remove Python 2/3 specific code."
groutr Jul 13, 2019
4dea638
Fix DeprecationWarning.
groutr Mar 16, 2020
dce0edf
Add deprecation warning to compatibility module.
groutr Mar 16, 2020
1517506
Remove compatibility tests
groutr Mar 16, 2020
cb345f7
Support Python >=3.5
groutr Mar 16, 2020
b05665d
Pycodestyle changes.
groutr Mar 16, 2020
cbfc621
Fix formatting of deprecation warning.
groutr Mar 16, 2020
bcddd8b
Update travis.yml
groutr Mar 16, 2020
1e1842d
Update travis ci (pypy)
groutr Mar 16, 2020
aa658ed
Add Python 3.9-dev
groutr Mar 16, 2020
81aafd6
Test with latest versions of pypy for Python 3.5/3.6
groutr Mar 16, 2020
f0aa082
Revert "Test with latest versions of pypy for Python 3.5/3.6"
groutr Mar 16, 2020
f44567d
Update readme for Python support.
groutr Mar 16, 2020
fa0887e
Remove python version specific no cover pragma.
groutr Mar 16, 2020
85579a3
Import filterfalse and zip_longest into global namespace.
groutr Mar 16, 2020
b584395
Clean up __init__
groutr Mar 16, 2020
996ec0c
Revert "Clean up __init__"
groutr Mar 16, 2020
918918a
Fix pragma checks.
groutr Mar 16, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,3 @@ omit =
[report]
exclude_lines =
pragma: no cover
pragma: py$MAJOR_PYTHON_VERSION no cover
16 changes: 5 additions & 11 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,13 @@
sudo: false
language: python
python:
- "2.7"
- "3.4"
- "3.5"
- "3.6"
- "3.7-dev"
- "pypy"

# Enable 3.7 without globally enabling sudo and dist: xenial for other build jobs
matrix:
include:
- python: 3.7
dist: xenial
sudo: true
- "3.7"
- "3.8"
- "3.9-dev"
- "pypy3.5-7.0"
- "pypy3.6-7.1.1"

env:
- PEP8_IGNORE="E731,W503,E402"
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ This builds a standard wordcount function from pieces within ``toolz``:
Dependencies
------------

``toolz`` supports Python 2.7 and Python 3.4+ with a common codebase.
``toolz`` supports Python 3.5+ with a common codebase.
It is pure Python and requires no dependencies beyond the standard
library.

Expand Down
2 changes: 1 addition & 1 deletion doc/source/install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ three ways:

1. Toolz is pure Python
2. Toolz relies only on the standard library
3. Toolz simultaneously supports Python versions 2.7, 3.4+, PyPy
3. Toolz simultaneously supports Python versions 3.4+ and PyPy
4 changes: 2 additions & 2 deletions doc/source/references.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ References
similar library for Ruby
- `Clojure <http://clojure.org>`__: A functional language whose
standard library has several counterparts in ``toolz``
- `itertools <http://docs.python.org/2/library/itertools.html>`__: The
- `itertools <http://docs.python.org/3/library/itertools.html>`__: The
Python standard library for iterator tools
- `functools <http://docs.python.org/2/library/functools.html>`__: The
- `functools <http://docs.python.org/3/library/functools.html>`__: The
Python standard library for function tools
- `Functional Programming HOWTO <http://docs.python.org/dev/howto/functional.html>`__:
The description of functional programming features from the official
Expand Down
6 changes: 2 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,15 @@
long_description=(open('README.rst').read() if exists('README.rst')
else ''),
zip_safe=False,
python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
python_requires=">=3.5",
classifiers=[
"Development Status :: 5 - Production/Stable",
"License :: OSI Approved :: BSD License",
"Programming Language :: Python",
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy"])
6 changes: 4 additions & 2 deletions toolz/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@

from .recipes import *

from .compatibility import map, filter

from functools import partial, reduce

sorted = sorted

map = map

filter = filter

# Aliases
comp = compose

Expand Down
168 changes: 59 additions & 109 deletions toolz/_signatures.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,10 @@
import operator
from importlib import import_module

from .compatibility import PY3
from .functoolz import (is_partial_args, is_arity, has_varargs,
has_keywords, num_required_args)

if PY3: # pragma: py2 no cover
import builtins
else: # pragma: py3 no cover
import __builtin__ as builtins
import builtins

# We mock builtin callables using lists of tuples with lambda functions.
#
Expand Down Expand Up @@ -235,54 +231,33 @@
lambda source, globals: None,
lambda source, globals, locals: None]

if PY3: # pragma: py2 no cover
module_info[builtins].update(
breakpoint=[
lambda *args, **kws: None],
bytes=[
lambda: None,
lambda int: None,
lambda string, encoding='utf8', errors='strict': None],
compile=[
(0, lambda source, filename, mode, flags=0,
dont_inherit=False, optimize=-1: None)],
max=[
(1, lambda iterable: None, ('default', 'key',)),
(1, lambda arg1, arg2, *args: None, ('key',))],
min=[
(1, lambda iterable: None, ('default', 'key',)),
(1, lambda arg1, arg2, *args: None, ('key',))],
open=[
(0, lambda file, mode='r', buffering=-1, encoding=None,
errors=None, newline=None, closefd=True, opener=None: None)],
sorted=[
(1, lambda iterable: None, ('key', 'reverse'))],
str=[
lambda object='', encoding='utf', errors='strict': None],
)
module_info[builtins]['print'] = [
(0, lambda *args: None, ('sep', 'end', 'file', 'flush',))]

else: # pragma: py3 no cover
module_info[builtins].update(
bytes=[
lambda object='': None],
compile=[
(0, lambda source, filename, mode, flags=0,
dont_inherit=False: None)],
max=[
(1, lambda iterable, *args: None, ('key',))],
min=[
(1, lambda iterable, *args: None, ('key',))],
open=[
(0, lambda file, mode='r', buffering=-1: None)],
sorted=[
lambda iterable, cmp=None, key=None, reverse=False: None],
str=[
lambda object='': None],
)
module_info[builtins]['print'] = [
(0, lambda *args: None, ('sep', 'end', 'file',))]
module_info[builtins].update(
breakpoint=[
lambda *args, **kws: None],
bytes=[
lambda: None,
lambda int: None,
lambda string, encoding='utf8', errors='strict': None],
compile=[
(0, lambda source, filename, mode, flags=0,
dont_inherit=False, optimize=-1: None)],
max=[
(1, lambda iterable: None, ('default', 'key',)),
(1, lambda arg1, arg2, *args: None, ('key',))],
min=[
(1, lambda iterable: None, ('default', 'key',)),
(1, lambda arg1, arg2, *args: None, ('key',))],
open=[
(0, lambda file, mode='r', buffering=-1, encoding=None,
errors=None, newline=None, closefd=True, opener=None: None)],
sorted=[
(1, lambda iterable: None, ('key', 'reverse'))],
str=[
lambda object='', encoding='utf', errors='strict': None],
)
module_info[builtins]['print'] = [
(0, lambda *args: None, ('sep', 'end', 'file', 'flush',))]


module_info[functools] = dict(
cmp_to_key=[
Expand Down Expand Up @@ -346,16 +321,11 @@
(0, lambda *iterables: None, ('fillvalue',))],
)

if PY3: # pragma: py2 no cover
module_info[itertools].update(
product=[
(0, lambda *iterables: None, ('repeat',))],
)
else: # pragma: py3 no cover
module_info[itertools].update(
product=[
lambda *iterables: None],
)
module_info[itertools].update(
product=[
(0, lambda *iterables: None, ('repeat',))],
)


module_info[operator] = dict(
__abs__=[
Expand Down Expand Up @@ -622,51 +592,31 @@
classval=None: None)],
)

if PY3: # pragma: py2 no cover
def num_pos_args(sigspec):
""" Return the number of positional arguments. ``f(x, y=1)`` has 1"""
return sum(1 for x in sigspec.parameters.values()
if x.kind == x.POSITIONAL_OR_KEYWORD
and x.default is x.empty)

def get_exclude_keywords(num_pos_only, sigspec):
""" Return the names of position-only arguments if func has **kwargs"""
if num_pos_only == 0:
return ()
has_kwargs = any(x.kind == x.VAR_KEYWORD
for x in sigspec.parameters.values())
if not has_kwargs:
return ()
pos_args = list(sigspec.parameters.values())[:num_pos_only]
return tuple(x.name for x in pos_args)

def signature_or_spec(func):
try:
return inspect.signature(func)
except (ValueError, TypeError):
return None

else: # pragma: py3 no cover
def num_pos_args(sigspec):
""" Return the number of positional arguments. ``f(x, y=1)`` has 1"""
if sigspec.defaults:
return len(sigspec.args) - len(sigspec.defaults)
return len(sigspec.args)

def get_exclude_keywords(num_pos_only, sigspec):
""" Return the names of position-only arguments if func has **kwargs"""
if num_pos_only == 0:
return ()
has_kwargs = sigspec.keywords is not None
if not has_kwargs:
return ()
return tuple(sigspec.args[:num_pos_only])

def signature_or_spec(func):
try:
return inspect.getargspec(func)
except TypeError:
return None

def num_pos_args(sigspec):
""" Return the number of positional arguments. ``f(x, y=1)`` has 1"""
return sum(1 for x in sigspec.parameters.values()
if x.kind == x.POSITIONAL_OR_KEYWORD
and x.default is x.empty)


def get_exclude_keywords(num_pos_only, sigspec):
""" Return the names of position-only arguments if func has **kwargs"""
if num_pos_only == 0:
return ()
has_kwargs = any(x.kind == x.VAR_KEYWORD
for x in sigspec.parameters.values())
if not has_kwargs:
return ()
pos_args = list(sigspec.parameters.values())[:num_pos_only]
return tuple(x.name for x in pos_args)


def signature_or_spec(func):
try:
return inspect.signature(func)
except (ValueError, TypeError):
return None


def expand_sig(sig):
Expand Down Expand Up @@ -792,7 +742,7 @@ def _has_varargs(func):
checks = [check_varargs(sig) for sig in sigs]
if all(checks):
return True
elif any(checks): # pragma: py2 no cover
elif any(checks):
return None
return False

Expand Down
46 changes: 21 additions & 25 deletions toolz/compatibility.py
Original file line number Diff line number Diff line change
@@ -1,34 +1,30 @@
import warnings
warnings.warn("The toolz.compatibility module is no longer "
"needed in Python 3 and has been deprecated. Please "
"import these utilities directly from the standard library. "
"This module will be removed in a future release.",
category=DeprecationWarning)

import operator
import sys

PY3 = sys.version_info[0] > 2
PY34 = sys.version_info[0] == 3 and sys.version_info[1] == 4
PYPY = hasattr(sys, 'pypy_version_info')
PYPY = hasattr(sys, 'pypy_version_info') and PY3

__all__ = ('map', 'filter', 'range', 'zip', 'reduce', 'zip_longest',
'iteritems', 'iterkeys', 'itervalues', 'filterfalse',
'PY3', 'PY34', 'PYPY')

if PY3:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we keep all of these definitions instead of deleting them? Other packages may refer to toolz.compatibility. Note that we don't need to use these in toolz, so no need to revert other modules that you've changed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I'll restore them. Maybe a deprecation warning should be added to the module.

map = map
filter = filter
range = range
zip = zip
from functools import reduce
from itertools import zip_longest
from itertools import filterfalse
iteritems = operator.methodcaller('items')
iterkeys = operator.methodcaller('keys')
itervalues = operator.methodcaller('values')
from collections.abc import Sequence, Mapping
else:
range = xrange
reduce = reduce
from itertools import imap as map
from itertools import ifilter as filter
from itertools import ifilterfalse as filterfalse
from itertools import izip as zip
from itertools import izip_longest as zip_longest
iteritems = operator.methodcaller('iteritems')
iterkeys = operator.methodcaller('iterkeys')
itervalues = operator.methodcaller('itervalues')
from collections import Sequence, Mapping

map = map
filter = filter
range = range
zip = zip
from functools import reduce
from itertools import zip_longest
from itertools import filterfalse
iteritems = operator.methodcaller('items')
iterkeys = operator.methodcaller('keys')
itervalues = operator.methodcaller('values')
from collections.abc import Sequence
Loading