Skip to content

Commit

Permalink
Universalize bytes
Browse files Browse the repository at this point in the history
  • Loading branch information
evhub committed Jan 27, 2024
1 parent 4be1bb5 commit 5ba3d1a
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 4 deletions.
1 change: 1 addition & 0 deletions DOCS.md
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ While Coconut syntax is based off of the latest Python 3, Coconut code compiled

To make Coconut built-ins universal across Python versions, Coconut makes available on any Python version built-ins that only exist in later versions, including **automatically overwriting Python 2 built-ins with their Python 3 counterparts.** Additionally, Coconut also [overwrites some Python 3 built-ins for optimization and enhancement purposes](#enhanced-built-ins). If access to the original Python versions of any overwritten built-ins is desired, the old built-ins can be retrieved by prefixing them with `py_`. Specifically, the overwritten built-ins are:

- `py_bytes`
- `py_chr`
- `py_dict`
- `py_hex`
Expand Down
1 change: 1 addition & 0 deletions __coconut__/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ if sys.version_info < (3, 7):
...


py_bytes = bytes
py_chr = chr
py_dict = dict
py_hex = hex
Expand Down
1 change: 1 addition & 0 deletions _coconut/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ ValueError = _builtins.ValueError
StopIteration = _builtins.StopIteration
RuntimeError = _builtins.RuntimeError
callable = _builtins.callable
chr = _builtins.chr
classmethod = _builtins.classmethod
complex = _builtins.complex
all = _builtins.all
Expand Down
4 changes: 3 additions & 1 deletion coconut/compiler/templates/header.py_template
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class _coconut{object}:{COMMENT.EVERYTHING_HERE_MUST_BE_COPIED_TO_STUB_FILE}
reiterables = abc.Sequence, abc.Mapping, abc.Set
fmappables = list, tuple, dict, set, frozenset
abc.Sequence.register(collections.deque)
Ellipsis, NotImplemented, NotImplementedError, Exception, AttributeError, ImportError, IndexError, KeyError, NameError, TypeError, ValueError, StopIteration, RuntimeError, all, any, bool, bytes, callable, classmethod, complex, dict, enumerate, filter, float, frozenset, getattr, hasattr, hash, id, int, isinstance, issubclass, iter, len, list, locals, globals, map, min, max, next, object, property, range, reversed, set, setattr, slice, str, sum, super, tuple, type, vars, zip, repr, print{comma_bytearray} = Ellipsis, NotImplemented, NotImplementedError, Exception, AttributeError, ImportError, IndexError, KeyError, NameError, TypeError, ValueError, StopIteration, RuntimeError, all, any, bool, bytes, callable, classmethod, complex, dict, enumerate, filter, float, frozenset, getattr, hasattr, hash, id, int, isinstance, issubclass, iter, len, list, locals, globals, map, min, max, next, object, property, range, reversed, set, setattr, slice, str, sum, {lstatic}super{rstatic}, tuple, type, vars, zip, {lstatic}repr{rstatic}, {lstatic}print{rstatic}{comma_bytearray}
Ellipsis, NotImplemented, NotImplementedError, Exception, AttributeError, ImportError, IndexError, KeyError, NameError, TypeError, ValueError, StopIteration, RuntimeError, all, any, bool, bytes, callable, chr, classmethod, complex, dict, enumerate, filter, float, frozenset, getattr, hasattr, hash, id, int, isinstance, issubclass, iter, len, list, locals, globals, map, min, max, next, object, property, range, reversed, set, setattr, slice, str, sum, super, tuple, type, vars, zip, repr, print{comma_bytearray} = Ellipsis, NotImplemented, NotImplementedError, Exception, AttributeError, ImportError, IndexError, KeyError, NameError, TypeError, ValueError, StopIteration, RuntimeError, all, any, bool, bytes, callable, chr, classmethod, complex, dict, enumerate, filter, float, frozenset, getattr, hasattr, hash, id, int, isinstance, issubclass, iter, len, list, locals, globals, map, min, max, next, object, property, range, reversed, set, setattr, slice, str, sum, {lstatic}super{rstatic}, tuple, type, vars, zip, {lstatic}repr{rstatic}, {lstatic}print{rstatic}{comma_bytearray}
@_coconut.functools.wraps(_coconut.functools.partial)
def _coconut_partial(_coconut_func, *args, **kwargs):
partial_func = _coconut.functools.partial(_coconut_func, *args, **kwargs)
Expand Down Expand Up @@ -1583,6 +1583,8 @@ def _coconut_base_makedata(data_type, args, from_fmap=False, fallback_to_init=Fa
return args
if _coconut.issubclass(data_type, _coconut.str):
return "".join(args)
if _coconut.issubclass(data_type, _coconut.bytes):
return b"".join(args)
if fallback_to_init or _coconut.issubclass(data_type, _coconut.fmappables):
return data_type(args)
if from_fmap:
Expand Down
26 changes: 23 additions & 3 deletions coconut/root.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,16 @@ def _get_target_info(target):

# if a new assignment is added below, a new builtins import should be added alongside it
_base_py3_header = r'''from builtins import chr, dict, hex, input, int, map, object, oct, open, print, range, str, super, zip, filter, reversed, enumerate, repr
py_chr, py_dict, py_hex, py_input, py_int, py_map, py_object, py_oct, py_open, py_print, py_range, py_str, py_super, py_zip, py_filter, py_reversed, py_enumerate, py_repr = chr, dict, hex, input, int, map, object, oct, open, print, range, str, super, zip, filter, reversed, enumerate, repr
py_bytes, py_chr, py_dict, py_hex, py_input, py_int, py_map, py_object, py_oct, py_open, py_print, py_range, py_str, py_super, py_zip, py_filter, py_reversed, py_enumerate, py_repr = bytes, chr, dict, hex, input, int, map, object, oct, open, print, range, str, super, zip, filter, reversed, enumerate, repr
_coconut_py_str, _coconut_py_super, _coconut_py_dict = str, super, dict
from functools import wraps as _coconut_wraps
exec("_coconut_exec = exec")
'''

# if a new assignment is added below, a new builtins import should be added alongside it
_base_py2_header = r'''from __builtin__ import chr, dict, hex, input, int, map, object, oct, open, print, range, str, super, zip, filter, reversed, enumerate, raw_input, xrange, repr, long
py_chr, py_dict, py_hex, py_input, py_int, py_map, py_object, py_oct, py_open, py_print, py_range, py_str, py_super, py_zip, py_filter, py_reversed, py_enumerate, py_raw_input, py_xrange, py_repr = chr, dict, hex, input, int, map, object, oct, open, print, range, str, super, zip, filter, reversed, enumerate, raw_input, xrange, repr
_coconut_py_raw_input, _coconut_py_xrange, _coconut_py_int, _coconut_py_long, _coconut_py_print, _coconut_py_str, _coconut_py_super, _coconut_py_unicode, _coconut_py_repr, _coconut_py_dict = raw_input, xrange, int, long, print, str, super, unicode, repr, dict
py_bytes, py_chr, py_dict, py_hex, py_input, py_int, py_map, py_object, py_oct, py_open, py_print, py_range, py_str, py_super, py_zip, py_filter, py_reversed, py_enumerate, py_raw_input, py_xrange, py_repr = bytes, chr, dict, hex, input, int, map, object, oct, open, print, range, str, super, zip, filter, reversed, enumerate, raw_input, xrange, repr
_coconut_py_raw_input, _coconut_py_xrange, _coconut_py_int, _coconut_py_long, _coconut_py_print, _coconut_py_str, _coconut_py_super, _coconut_py_unicode, _coconut_py_repr, _coconut_py_dict, _coconut_py_bytes = raw_input, xrange, int, long, print, str, super, unicode, repr, dict, bytes
from functools import wraps as _coconut_wraps
from collections import Sequence as _coconut_Sequence
from future_builtins import *
Expand All @@ -96,6 +96,26 @@ def __instancecheck__(cls, inst):
return _coconut.isinstance(inst, (_coconut_py_int, _coconut_py_long))
def __subclasscheck__(cls, subcls):
return _coconut.issubclass(subcls, (_coconut_py_int, _coconut_py_long))
class bytes(_coconut_py_bytes):
__slots__ = ()
__doc__ = getattr(_coconut_py_bytes, "__doc__", "<see help(py_bytes)>")
class __metaclass__(type):
def __instancecheck__(cls, inst):
return _coconut.isinstance(inst, _coconut_py_bytes)
def __subclasscheck__(cls, subcls):
return _coconut.issubclass(subcls, _coconut_py_bytes)
def __new__(self, *args):
if not args:
return b""
elif _coconut.len(args) == 1:
if _coconut.isinstance(args[0], _coconut.int):
return b"\x00" * args[0]
elif _coconut.isinstance(args[0], _coconut.bytes):
return _coconut_py_bytes(args[0])
else:
return b"".join(_coconut.chr(x) for x in args[0])
else:
return args[0].encode(*args[1:])
class range(object):
__slots__ = ("_xrange",)
__doc__ = getattr(_coconut_py_xrange, "__doc__", "<see help(py_xrange)>")
Expand Down
6 changes: 6 additions & 0 deletions coconut/tests/src/cocotest/agnostic/primary_2.coco
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,12 @@ def primary_test_2() -> bool:
assert (,) ↤? None is None
assert (,) ↤*? None is None # type: ignore
assert '''\u2029'''!='''\n'''
assert b"a" `isinstance` bytes
assert b"a" `isinstance` py_bytes
assert bytes() == b""
assert bytes(10) == b"\x00" * 10
assert bytes([35, 40]) == b'#('
assert bytes(b"abc") == b"abc" == bytes("abc", "utf-8")

with process_map.multiple_sequential_calls(): # type: ignore
assert map((+), range(3), range(4)$[:-1], strict=True) |> list == [0, 2, 4] == process_map((+), range(3), range(4)$[:-1], strict=True) |> list # type: ignore
Expand Down

0 comments on commit 5ba3d1a

Please sign in to comment.