Skip to content

Commit

Permalink
Fix py2 pickling
Browse files Browse the repository at this point in the history
  • Loading branch information
evhub committed Nov 26, 2023
1 parent 7a1169f commit 4c50275
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 15 deletions.
2 changes: 2 additions & 0 deletions coconut/command/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,8 @@ def set_mypy_path():

def is_empty_pipe(pipe, default=None):
"""Determine if the given pipe file object is empty."""
if pipe.closed:
return True
if not WINDOWS:
try:
return not select([pipe], [], [], 0)[0]
Expand Down
6 changes: 4 additions & 2 deletions coconut/compiler/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -1210,9 +1210,11 @@ def make_err(self, errtype, message, original, loc=0, ln=None, extra=None, refor
self.internal_assert(extra is None, original, loc, "make_err cannot include causes with extra")
causes = dictset()
for cause, _, _ in all_matches(self.parse_err_msg, snippet[loc_in_snip:]):
causes.add(cause)
if cause:
causes.add(cause)
for cause, _, _ in all_matches(self.parse_err_msg, snippet[endpt_in_snip:]):
causes.add(cause)
if cause:
causes.add(cause)
if causes:
extra = "possible cause{s}: {causes}".format(
s="s" if len(causes) > 1 else "",
Expand Down
2 changes: 1 addition & 1 deletion coconut/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -1009,7 +1009,7 @@ def get_path_env_var(env_var, default):

# min versions are inclusive
unpinned_min_versions = {
"cPyparsing": (2, 4, 7, 2, 3, 0),
"cPyparsing": (2, 4, 7, 2, 3, 1),
("pre-commit", "py3"): (3,),
("psutil", "py>=27"): (5,),
"jupyter": (1, 0),
Expand Down
52 changes: 50 additions & 2 deletions coconut/root.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
VERSION = "3.0.4"
VERSION_NAME = None
# False for release, int >= 1 for develop
DEVELOP = False
ALPHA = False # for pre releases rather than post releases
DEVELOP = 1
ALPHA = True # for pre releases rather than post releases

assert DEVELOP is False or DEVELOP >= 1, "DEVELOP must be False or an int >= 1"
assert DEVELOP or not ALPHA, "alpha releases are only for develop"
Expand Down Expand Up @@ -208,6 +208,54 @@ def _coconut_exec(obj, globals=None, locals=None):
if globals is None:
globals = _coconut_sys._getframe(1).f_globals
exec(obj, globals, locals)
import operator as _coconut_operator
class _coconut_attrgetter(object):
__slots__ = ("attrs",)
def __init__(self, *attrs):
self.attrs = attrs
def __reduce_ex__(self, _):
return self.__reduce__()
def __reduce__(self):
return (self.__class__, self.attrs)
@staticmethod
def _getattr(obj, attr):
for name in attr.split("."):
obj = _coconut.getattr(obj, name)
return obj
def __call__(self, obj):
if len(self.attrs) == 1:
return self._getattr(obj, self.attrs[0])
return _coconut.tuple(self._getattr(obj, attr) for attr in self.attrs)
_coconut_operator.attrgetter = _coconut_attrgetter
class _coconut_itemgetter(object):
__slots__ = ("items",)
def __init__(self, *items):
self.items = items
def __reduce_ex__(self, _):
return self.__reduce__()
def __reduce__(self):
return (self.__class__, self.items)
def __call__(self, obj):
if len(self.items) == 1:
return obj[self.items[0]]
return _coconut.tuple(obj[item] for item in self.items)
_coconut_operator.itemgetter = _coconut_itemgetter
class _coconut_methodcaller(object):
__slots__ = ("name", "args", "kwargs")
def __init__(self, name, *args, **kwargs):
self.name = name
self.args = args
self.kwargs = kwargs
def __reduce_ex__(self, _):
return self.__reduce__()
def __reduce__(self):
return (self.__class__, (self.name,) + self.args, {"kwargs": self.kwargs})
def __setstate__(self, setvars):
for k, v in setvars.items():
_coconut.setattr(self, k, v)
def __call__(self, obj):
return _coconut.getattr(obj, self.name)(*self.args, **self.kwargs)
_coconut_operator.methodcaller = _coconut_methodcaller
'''

_non_py37_extras = r'''def _coconut_default_breakpointhook(*args, **kwargs):
Expand Down
18 changes: 10 additions & 8 deletions coconut/tests/src/cocotest/agnostic/main.coco
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,11 @@ def run_main(outer_MatchError, test_easter_eggs=False) -> bool:

print_dot() # ..
assert primary_test_1() is True
assert primary_test_2() is True

print_dot() # ...
assert primary_test_2() is True

print_dot() # ....
from .specific import (
non_py26_test,
non_py32_test,
Expand All @@ -79,19 +81,19 @@ def run_main(outer_MatchError, test_easter_eggs=False) -> bool:
if sys.version_info >= (3, 8):
assert py38_spec_test() is True

print_dot() # ....
print_dot() # .....
from .suite import suite_test, tco_test
assert suite_test() is True

print_dot() # .....
print_dot() # ......
assert mypy_test() is True
if using_tco:
assert hasattr(tco_func, "_coconut_tco_func")
assert tco_test() is True
if outer_MatchError.__module__ != "__main__":
assert package_test(outer_MatchError) is True

print_dot() # ......
print_dot() # .......
if sys.version_info < (3,):
from .py2_test import py2_test
assert py2_test() is True
Expand All @@ -111,21 +113,21 @@ def run_main(outer_MatchError, test_easter_eggs=False) -> bool:
from .py311_test import py311_test
assert py311_test() is True

print_dot() # .......
print_dot() # ........
from .target_sys_test import TEST_ASYNCIO, target_sys_test
if TEST_ASYNCIO:
assert test_asyncio() is True
assert target_sys_test() is True

print_dot() # ........
print_dot() # .........
from .non_strict_test import non_strict_test
assert non_strict_test() is True

print_dot() # .........
print_dot() # ..........
from . import tutorial # noQA

if test_easter_eggs:
print(".", end="") # ..........
print_dot() # ...........
assert easter_egg_test() is True

print("\n<success>")
Expand Down
5 changes: 5 additions & 0 deletions coconut/tests/src/cocotest/agnostic/suite.coco
Original file line number Diff line number Diff line change
Expand Up @@ -1070,6 +1070,11 @@ forward 2""") == 900
assert DerivedWithMeths().static_meth()
assert Fibs()[100] == 354224848179261915075
assert tree_depth(Node(Leaf 5, Node(Node(Leaf 10)))) == 3
assert pickle_round_trip(.name) <| (name=10) == 10
assert pickle_round_trip(.[0])([10]) == 10
assert pickle_round_trip(.loc[0]) <| (loc=[10]) == 10
assert pickle_round_trip(.method(0)) <| (method=const 10) == 10
assert pickle_round_trip(.method(x=10)) <| (method=x -> x) == 10

with process_map.multiple_sequential_calls(): # type: ignore
assert process_map(tuple <.. (|>)$(to_sort), qsorts) |> list == [to_sort |> sorted |> tuple] * len(qsorts)
Expand Down
4 changes: 2 additions & 2 deletions coconut/tests/src/extras.coco
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ cannot reassign type variable 'T' (use explicit '\T' syntax if intended) (line 1
)

assert_raises(-> parse("$"), CoconutParseError)
assert_raises(-> parse("@"), CoconutParseError, err_has=("\n ~^", "\n ^"))
assert_raises(-> parse("@"), CoconutParseError)
assert_raises(-> parse("range(1,10) |> reduce$(*, initializer = 1000) |> print"), CoconutParseError, err_has=" \\~~~~~~~~~~~~~~~~~~~~~~~^")
assert_raises(-> parse("a := b"), CoconutParseError, err_has=" \\~^")
assert_raises(-> parse("1 + return"), CoconutParseError, err_has=" \\~~~~^")
Expand Down Expand Up @@ -362,7 +362,7 @@ else:
assert_raises(-> parse("obj."), CoconutStyleError, err_has="getattr")
assert_raises(-> parse("def x -> pass, 1"), CoconutStyleError, err_has="statement lambda")
assert_raises(-> parse("abc = f'abc'"), CoconutStyleError, err_has="\n ^")
assert_raises(-> parse('f"{f"{f"infinite"}"}"'), CoconutStyleError, err_has=" ^~~~~~~~~~~|")
assert_raises(-> parse('f"{f"{f"infinite"}"}"'), CoconutStyleError, err_has="f-string with no expressions")
try:
parse("""
import abc
Expand Down
3 changes: 3 additions & 0 deletions coconut/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,9 @@ def __missing__(self, key):
class dictset(dict, object):
"""A set implemented using a dictionary to get ordering benefits."""

def __bool__(self):
return len(self) > 0 # fixes py2 issue

def add(self, item):
self[item] = True

Expand Down

0 comments on commit 4c50275

Please sign in to comment.