Beispiel #1
0
def base_pycondition(target,
                     ver,
                     if_lt=None,
                     if_ge=None,
                     indent=None,
                     newline=False,
                     fallback=""):
    """Produce code that depends on the Python version for the given target."""
    internal_assert(isinstance(ver, tuple), "invalid pycondition version")
    internal_assert(if_lt or if_ge, "either if_lt or if_ge must be specified")

    if if_lt:
        if_lt = if_lt.strip()
    if if_ge:
        if_ge = if_ge.strip()

    target_supported_vers = get_vers_for_target(target)

    if all(tar_ver < ver for tar_ver in target_supported_vers):
        if not if_lt:
            return fallback
        out = if_lt

    elif all(tar_ver >= ver for tar_ver in target_supported_vers):
        if not if_ge:
            return fallback
        out = if_ge

    else:
        if if_lt and if_ge:
            out = """if _coconut_sys.version_info < {ver}:
{lt_block}
else:
{ge_block}""".format(
                ver=repr(ver),
                lt_block=_indent(if_lt, by=1),
                ge_block=_indent(if_ge, by=1),
            )
        elif if_lt:
            out = """if _coconut_sys.version_info < {ver}:
{lt_block}""".format(
                ver=repr(ver),
                lt_block=_indent(if_lt, by=1),
            )
        else:
            out = """if _coconut_sys.version_info >= {ver}:
{ge_block}""".format(
                ver=repr(ver),
                ge_block=_indent(if_ge, by=1),
            )

    if indent is not None:
        out = _indent(out, by=indent)
    if newline:
        out += "\n"
    return out
Beispiel #2
0
def process_header_args(which, target, use_hash, no_tco, strict):
    """Create the dictionary passed to str.format in the header, target_startswith, and target_info."""
    target_startswith = one_num_ver(target)
    target_info = get_target_info(target)

    try_backport_lru_cache = r'''try:
    from backports.functools_lru_cache import lru_cache
    functools.lru_cache = lru_cache
except ImportError: pass
'''
    try_import_trollius = r'''try:
    import trollius as asyncio
except ImportError:
    class you_need_to_install_trollius: pass
    asyncio = you_need_to_install_trollius()
'''

    format_dict = dict(
        comment=comment(),
        empty_dict="{}",
        target_startswith=target_startswith,
        default_encoding=default_encoding,
        hash_line=hash_prefix + use_hash +
        "\n" if use_hash is not None else "",
        typing_line="# type: ignore\n" if which == "__coconut__" else "",
        VERSION_STR=VERSION_STR,
        module_docstring='"""Built-in Coconut utilities."""\n\n'
        if which == "__coconut__" else "",
        object="(object)" if target_startswith != "3" else "",
        import_asyncio=_indent(
            "" if not target or target_info >=
            (3, 5) else "import asyncio\n" if target_info >=
            (3, 4) else r'''if _coconut_sys.version_info >= (3, 4):
    import asyncio
else:
''' + _indent(try_import_trollius) if target_info >=
            (3, ) else try_import_trollius, ),
        import_pickle=_indent(r'''if _coconut_sys.version_info < (3,):
    import cPickle as pickle
else:
    import pickle''' if not target else "import cPickle as pickle"
                              if target_info < (3, ) else "import pickle"),
        import_OrderedDict=_indent(
            r'''if _coconut_sys.version_info >= (2, 7):
    OrderedDict = collections.OrderedDict
else:
    OrderedDict = dict''' if not target else
            "OrderedDict = collections.OrderedDict" if target_info >= (
                2, 7) else "OrderedDict = dict"),
        import_collections_abc=_indent(
            r'''if _coconut_sys.version_info < (3, 3):
    abc = collections
else:
    import collections.abc as abc'''
            if target_startswith != "2" else "abc = collections"),
        bind_lru_cache=_indent(r'''if _coconut_sys.version_info < (3, 2):
''' + _indent(try_backport_lru_cache) if not target else try_backport_lru_cache
                               if target_startswith == "2" else ""),
        comma_bytearray=", bytearray" if target_startswith != "3" else "",
        static_repr="staticmethod(repr)"
        if target_startswith != "3" else "repr",
        with_ThreadPoolExecutor=
        (r'''from multiprocessing import cpu_count  # cpu_count() * 5 is the default Python 3.5 thread count
        with ThreadPoolExecutor(cpu_count() * 5)''' if target_info <
         (3, 5) else '''with ThreadPoolExecutor()'''),
        def_tco_func=r'''def _coconut_tco_func(self, *args, **kwargs):
        for func in self.patterns[:-1]:
            try:
                with _coconut_FunctionMatchErrorContext(self.FunctionMatchError):
                    return func(*args, **kwargs)
            except self.FunctionMatchError:
                pass
        return _coconut_tail_call(self.patterns[-1], *args, **kwargs)
    ''',
        def_prepattern=(r'''def prepattern(base_func, **kwargs):
    """DEPRECATED: Use addpattern instead."""
    def pattern_prepender(func):
        return addpattern(func, **kwargs)(base_func)
    return pattern_prepender
''' if not strict else ""),
        def_datamaker=(r'''def datamaker(data_type):
    """DEPRECATED: Use makedata instead."""
    return _coconut.functools.partial(makedata, data_type)
''' if not strict else ""),
        comma_tco=", _coconut_tail_call, _coconut_tco" if not no_tco else "",
    )

    # when anything is added to this list it must also be added to the stub file
    format_dict[
        "underscore_imports"] = "_coconut, _coconut_MatchError{comma_tco}, _coconut_igetitem, _coconut_base_compose, _coconut_forward_compose, _coconut_back_compose, _coconut_forward_star_compose, _coconut_back_star_compose, _coconut_forward_dubstar_compose, _coconut_back_dubstar_compose, _coconut_pipe, _coconut_back_pipe, _coconut_star_pipe, _coconut_back_star_pipe, _coconut_dubstar_pipe, _coconut_back_dubstar_pipe, _coconut_bool_and, _coconut_bool_or, _coconut_none_coalesce, _coconut_minus, _coconut_map, _coconut_partial, _coconut_get_function_match_error, _coconut_base_pattern_func, _coconut_addpattern, _coconut_sentinel, _coconut_assert, _coconut_mark_as_match".format(
            **format_dict)

    format_dict["import_typing_NamedTuple"] = _indent(
        "import typing" if target_info >= (3, 6) else '''class typing{object}:
    @staticmethod
    def NamedTuple(name, fields):
        return _coconut.collections.namedtuple(name, [x for x, t in fields])'''
        .format(**format_dict), )

    # ._coconut_tco_func is used in main.coco, so don't remove it
    #  here without replacing its usage there
    format_dict[
        "def_tco"] = "" if no_tco else '''class _coconut_tail_call{object}:
    __slots__ = ("func", "args", "kwargs")
    def __init__(self, func, *args, **kwargs):
        self.func, self.args, self.kwargs = func, args, kwargs
_coconut_tco_func_dict = {empty_dict}
def _coconut_tco(func):
    @_coconut.functools.wraps(func)
    def tail_call_optimized_func(*args, **kwargs):
        call_func = func
        while True:{comment.weakrefs_necessary_for_ignoring_bound_methods}
            wkref = _coconut_tco_func_dict.get(_coconut.id(call_func))
            if (wkref is not None and wkref() is call_func) or _coconut.isinstance(call_func, _coconut_base_pattern_func):
                call_func = call_func._coconut_tco_func
            result = call_func(*args, **kwargs)  # pass --no-tco to clean up your traceback
            if not isinstance(result, _coconut_tail_call):
                return result
            call_func, args, kwargs = result.func, result.args, result.kwargs
    tail_call_optimized_func._coconut_tco_func = func
    tail_call_optimized_func.__module__ = _coconut.getattr(func, "__module__", None)
    tail_call_optimized_func.__name__ = _coconut.getattr(func, "__name__", "<coconut tco function (pass --no-tco to remove)>")
    tail_call_optimized_func.__qualname__ = _coconut.getattr(func, "__qualname__", tail_call_optimized_func.__name__)
    _coconut_tco_func_dict[_coconut.id(tail_call_optimized_func)] = _coconut.weakref.ref(tail_call_optimized_func)
    return tail_call_optimized_func
'''.format(**format_dict)

    return format_dict, target_startswith, target_info
Beispiel #3
0
def process_header_args(which, target, use_hash, no_tco, strict):
    """Create the dictionary passed to str.format in the header, target_startswith, and target_info."""
    target_startswith = one_num_ver(target)
    target_info = get_target_info(target)

    try_backport_lru_cache = r'''try:
    from backports.functools_lru_cache import lru_cache
    functools.lru_cache = lru_cache
except ImportError: pass
'''
    try_import_trollius = r'''try:
    import trollius as asyncio
except ImportError:
    class you_need_to_install_trollius: pass
    asyncio = you_need_to_install_trollius()
'''

    format_dict = dict(
        comment=comment(),
        empty_dict="{}",
        target_startswith=target_startswith,
        default_encoding=default_encoding,
        hash_line=hash_prefix + use_hash + "\n" if use_hash is not None else "",
        typing_line="# type: ignore\n" if which == "__coconut__" else "",
        VERSION_STR=VERSION_STR,
        module_docstring='"""Built-in Coconut utilities."""\n\n' if which == "__coconut__" else "",
        object="(object)" if target_startswith != "3" else "",
        import_asyncio=_indent(
            "" if not target or target_info >= (3, 5)
            else "import asyncio\n" if target_info >= (3, 4)
            else r'''if _coconut_sys.version_info >= (3, 4):
    import asyncio
else:
''' + _indent(try_import_trollius) if target_info >= (3,)
            else try_import_trollius,
        ),
        import_pickle=_indent(
            r'''if _coconut_sys.version_info < (3,):
    import cPickle as pickle
else:
    import pickle''' if not target
            else "import cPickle as pickle" if target_info < (3,)
            else "import pickle"
        ),
        import_OrderedDict=_indent(
            r'''if _coconut_sys.version_info >= (2, 7):
    OrderedDict = collections.OrderedDict
else:
    OrderedDict = dict'''
            if not target
            else "OrderedDict = collections.OrderedDict" if target_info >= (2, 7)
            else "OrderedDict = dict"
        ),
        import_collections_abc=_indent(
            r'''if _coconut_sys.version_info < (3, 3):
    abc = collections
else:
    import collections.abc as abc'''
            if target_startswith != "2"
            else "abc = collections"
        ),
        bind_lru_cache=_indent(
            r'''if _coconut_sys.version_info < (3, 2):
''' + _indent(try_backport_lru_cache)
            if not target
            else try_backport_lru_cache if target_startswith == "2"
            else ""
        ),
        comma_bytearray=", bytearray" if target_startswith != "3" else "",
        static_repr="staticmethod(repr)" if target_startswith != "3" else "repr",
        with_ThreadPoolExecutor=(
            r'''from multiprocessing import cpu_count  # cpu_count() * 5 is the default Python 3.5 thread count
        with ThreadPoolExecutor(cpu_count() * 5)''' if target_info < (3, 5)
            else '''with ThreadPoolExecutor()'''
        ),
        tco_decorator="@_coconut_tco\n" + " " * 8 if not no_tco else "",
        tail_call_func_args_kwargs="func(*args, **kwargs)" if no_tco else "_coconut_tail_call(func, *args, **kwargs)",
        comma_tco=", _coconut_tail_call, _coconut_tco" if not no_tco else "",
        def_coconut_NamedTuple=(
            r'''def _coconut_NamedTuple(name, fields):
    return _coconut.collections.namedtuple(name, [x for x, t in fields])'''
            if target_info < (3, 6)
            else "from typing import NamedTuple as _coconut_NamedTuple"
        ),
        def_prepattern=(
            r'''def prepattern(base_func):
    """DEPRECATED: Use addpattern instead."""
    def pattern_prepender(func):
        return addpattern(func)(base_func)
    return pattern_prepender
''' if not strict else ""
        ),
        def_datamaker=(
            r'''def datamaker(data_type):
    """DEPRECATED: Use makedata instead."""
    return _coconut.functools.partial(makedata, data_type)
''' if not strict else ""
        ),
        __coconut__=(
            '"__coconut__"' if target_startswith == "3"
            else 'b"__coconut__"' if target_startswith == "2"
            else 'str("__coconut__")'
        ),
    )

    format_dict["underscore_imports"] = "_coconut, _coconut_NamedTuple, _coconut_MatchError{comma_tco}, _coconut_igetitem, _coconut_base_compose, _coconut_forward_compose, _coconut_back_compose, _coconut_forward_star_compose, _coconut_back_star_compose, _coconut_pipe, _coconut_star_pipe, _coconut_back_pipe, _coconut_back_star_pipe, _coconut_bool_and, _coconut_bool_or, _coconut_none_coalesce, _coconut_minus, _coconut_map, _coconut_partial".format(**format_dict)

    # ._coconut_tco_func is used in main.coco, so don't remove it
    #  here without replacing its usage there
    format_dict["def_tco"] = "" if no_tco else '''class _coconut_tail_call{object}:
    __slots__ = ("func", "args", "kwargs")
    def __init__(self, func, *args, **kwargs):
        self.func, self.args, self.kwargs = func, args, kwargs
_coconut_tco_func_dict = {empty_dict}
def _coconut_tco(func):
    @_coconut.functools.wraps(func)
    def tail_call_optimized_func(*args, **kwargs):
        call_func = func
        while True:
            wkref = _coconut_tco_func_dict.get(_coconut.id(call_func))
            if wkref is not None and wkref() is call_func:
                call_func = call_func._coconut_tco_func
            result = call_func(*args, **kwargs)  # pass --no-tco to clean up your traceback
            if not isinstance(result, _coconut_tail_call):
                return result
            call_func, args, kwargs = result.func, result.args, result.kwargs
    tail_call_optimized_func._coconut_tco_func = func
    _coconut_tco_func_dict[_coconut.id(tail_call_optimized_func)] = _coconut.weakref.ref(tail_call_optimized_func)
    return tail_call_optimized_func
'''.format(**format_dict)

    return format_dict, target_startswith, target_info
Beispiel #4
0
def process_header_args(which, target, use_hash, no_tco, strict, no_wrap):
    """Create the dictionary passed to str.format in the header."""
    target_startswith = one_num_ver(target)
    target_info = get_target_info(target)
    pycondition = partial(base_pycondition, target)

    format_dict = dict(
        COMMENT=COMMENT,
        empty_dict="{}",
        lbrace="{",
        rbrace="}",
        target_startswith=target_startswith,
        default_encoding=default_encoding,
        hash_line=hash_prefix + use_hash +
        "\n" if use_hash is not None else "",
        typing_line="# type: ignore\n" if which == "__coconut__" else "",
        VERSION_STR=VERSION_STR,
        module_docstring='"""Built-in Coconut utilities."""\n\n'
        if which == "__coconut__" else "",
        object="" if target_startswith == "3" else "(object)",
        report_this_text=report_this_text,
        import_pickle=pycondition(
            (3, ),
            if_lt=r'''
import cPickle as pickle
            ''',
            if_ge=r'''
import pickle
            ''',
            indent=1,
        ),
        import_OrderedDict=_indent(
            r'''OrderedDict = collections.OrderedDict if _coconut_sys.version_info >= (2, 7) else dict'''
            if not target else
            "OrderedDict = collections.OrderedDict" if target_info >=
            (2, 7) else "OrderedDict = dict",
            by=1,
        ),
        import_collections_abc=pycondition(
            (3, 3),
            if_lt=r'''
abc = collections
            ''',
            if_ge=r'''
import collections.abc as abc
            ''',
            indent=1,
        ),
        set_zip_longest=_indent(
            r'''zip_longest = itertools.zip_longest if _coconut_sys.version_info >= (3,) else itertools.izip_longest'''
            if not target else
            "zip_longest = itertools.zip_longest" if target_info >=
            (3, ) else "zip_longest = itertools.izip_longest",
            by=1,
        ),
        comma_bytearray=", bytearray" if target_startswith != "3" else "",
        lstatic="staticmethod(" if target_startswith != "3" else "",
        rstatic=")" if target_startswith != "3" else "",
        zip_iter=_indent(
            r'''for items in _coconut.iter(_coconut.zip(*self.iters, strict=self.strict) if _coconut_sys.version_info >= (3, 10) else _coconut.zip_longest(*self.iters, fillvalue=_coconut_sentinel) if self.strict else _coconut.zip(*self.iters)):
    if self.strict and _coconut_sys.version_info < (3, 10) and _coconut.any(x is _coconut_sentinel for x in items):
        raise _coconut.ValueError("zip(..., strict=True) arguments have mismatched lengths")
    yield items''' if not target else
            r'''for items in _coconut.iter(_coconut.zip(*self.iters, strict=self.strict)):
    yield items''' if target_info >= (3, 10) else
            r'''for items in _coconut.iter(_coconut.zip_longest(*self.iters, fillvalue=_coconut_sentinel) if self.strict else _coconut.zip(*self.iters)):
    if self.strict and _coconut.any(x is _coconut_sentinel for x in items):
        raise _coconut.ValueError("zip(..., strict=True) arguments have mismatched lengths")
    yield items''',
            by=2,
        ),
        # disabled mocks must have different docstrings so the
        #  interpreter can tell them apart from the real thing
        def_prepattern=(r'''def prepattern(base_func, **kwargs):
    """DEPRECATED: use addpattern instead."""
    def pattern_prepender(func):
        return addpattern(func, **kwargs)(base_func)
    return pattern_prepender'''
                        if not strict else r'''def prepattern(*args, **kwargs):
    """Deprecated feature 'prepattern' disabled by --strict compilation; use 'addpattern' instead."""
    raise _coconut.NameError("deprecated feature 'prepattern' disabled by --strict compilation; use 'addpattern' instead")'''
                        ),
        def_datamaker=(r'''def datamaker(data_type):
    """DEPRECATED: use makedata instead."""
    return _coconut.functools.partial(makedata, data_type)'''
                       if not strict else r'''def datamaker(*args, **kwargs):
    """Deprecated feature 'datamaker' disabled by --strict compilation; use 'makedata' instead."""
    raise _coconut.NameError("deprecated feature 'datamaker' disabled by --strict compilation; use 'makedata' instead")'''
                       ),
        return_method_of_self=pycondition(
            (3, ),
            if_lt=r'''
return _coconut.types.MethodType(self, obj, objtype)
            ''',
            if_ge=r'''
return _coconut.types.MethodType(self, obj)
            ''',
            indent=2,
        ),
        return_method_of_self_func=pycondition(
            (3, ),
            if_lt=r'''
return _coconut.types.MethodType(self.func, obj, objtype)
            ''',
            if_ge=r'''
return _coconut.types.MethodType(self.func, obj)
            ''',
            indent=2,
        ),
        def_call_set_names=(
            r'''def _coconut_call_set_names(cls):
    for k, v in _coconut.vars(cls).items():
        set_name = _coconut.getattr(v, "__set_name__", None)
        if set_name is not None:
            set_name(cls, k)''' if target_startswith == "2" else
            r'''def _coconut_call_set_names(cls): pass''' if target_info >=
            (3, 6) else r'''def _coconut_call_set_names(cls):
    if _coconut_sys.version_info < (3, 6):
        for k, v in _coconut.vars(cls).items():
            set_name = _coconut.getattr(v, "__set_name__", None)
            if set_name is not None:
                set_name(cls, k)'''),
        pattern_func_slots=pycondition(
            (3, 7),
            if_lt=r'''
__slots__ = ("FunctionMatchError", "patterns", "__doc__", "__name__")
            ''',
            if_ge=r'''
__slots__ = ("FunctionMatchError", "patterns", "__doc__", "__name__", "__qualname__")
            ''',
            indent=1,
        ),
        set_qualname_none=pycondition(
            (3, 7),
            if_ge=r'''
self.__qualname__ = None
            ''',
            indent=2,
        ),
        set_qualname_func=pycondition(
            (3, 7),
            if_ge=r'''
self.__qualname__ = _coconut.getattr(func, "__qualname__", self.__qualname__)
            ''',
            indent=2,
        ),
        tco_comma="_coconut_tail_call, _coconut_tco, " if not no_tco else "",
        call_set_names_comma="_coconut_call_set_names, " if target_info <
        (3, 6) else "",
        handle_cls_args_comma=
        "_coconut_handle_cls_kwargs, _coconut_handle_cls_stargs, "
        if target_startswith != "3" else "",
    )

    # second round for format dict elements that use the format dict
    format_dict.update(
        dict(
            # when anything is added to this list it must also be added to *both* __coconut__.pyi stub files
            underscore_imports=
            "{tco_comma}{call_set_names_comma}{handle_cls_args_comma}_coconut, _coconut_MatchError, _coconut_igetitem, _coconut_base_compose, _coconut_forward_compose, _coconut_back_compose, _coconut_forward_star_compose, _coconut_back_star_compose, _coconut_forward_dubstar_compose, _coconut_back_dubstar_compose, _coconut_pipe, _coconut_star_pipe, _coconut_dubstar_pipe, _coconut_back_pipe, _coconut_back_star_pipe, _coconut_back_dubstar_pipe, _coconut_none_pipe, _coconut_none_star_pipe, _coconut_none_dubstar_pipe, _coconut_bool_and, _coconut_bool_or, _coconut_none_coalesce, _coconut_minus, _coconut_map, _coconut_partial, _coconut_get_function_match_error, _coconut_base_pattern_func, _coconut_addpattern, _coconut_sentinel, _coconut_assert, _coconut_mark_as_match, _coconut_reiterable, _coconut_self_match_types, _coconut_dict_merge, _coconut_exec"
            .format(**format_dict),
            import_typing_NamedTuple=pycondition(
                (3, 6),
                if_lt='''
class typing{object}:
    @staticmethod
    def NamedTuple(name, fields):
        return _coconut.collections.namedtuple(name, [x for x, t in fields])
            '''.format(**format_dict),
                if_ge='''
import typing
            ''',
                indent=1,
            ),
            import_asyncio=pycondition(
                (3, 4),
                if_lt='''
try:
    import trollius as asyncio
except ImportError:
    class you_need_to_install_trollius{object}: pass
    asyncio = you_need_to_install_trollius()
            '''.format(**format_dict),
                if_ge='''
import asyncio
            ''',
                indent=1,
            ),
            maybe_bind_lru_cache=pycondition(
                (3, 2),
                if_lt='''
try:
    from backports.functools_lru_cache import lru_cache
    functools.lru_cache = lru_cache
except ImportError:
    class you_need_to_install_backports_functools_lru_cache{object}: pass
    functools.lru_cache = you_need_to_install_backports_functools_lru_cache()
            '''.format(**format_dict),
                if_ge=None,
                indent=1,
                newline=True,
            ),
        ), )

    return format_dict