On 12.04.20 02:20, Soni L. wrote:

I figured something better instead. you can have a class ESpace, but you use it like so:

    espace = ESpace()

    try:
        foo(espace=espace)
    except espace.module.submodule.Exception:
        ...

e.g. for builtins:

    espace = ESpace()

    try:
        raise espace.ValueError
    except espace.ValueError:
        ...

and it dynamically creates subclasses of whatever you give it. I'm not sure how doable this is in current python, but it's super close to what I want. so hey if it works well, we can promote it to the stdlib? just need to encourage ppl not to check the type of their espace argument so you can silently swap the external one for the stdlib one and nothing breaks.

(still need a better way to pass it into operators but eh)

This is possible for example by defining ESpace as a class which returns the corresponding exception subclasses via `__getattr__` and stores them in a cache. In order to work with a default (i.e. if no espace is provided) some base class which delegates attribute lookups directly to `builtins` would be required. Something like the following should do:

    import builtins
    import inspect


    class BaseESpace:
        def __getattr__(self, name):
            obj = getattr(builtins, name, None)
            if inspect.isclass(obj) and issubclass(obj, Exception):
                return obj
            else:
                raise AttributeError(name)


    class ESpace(BaseESpace):
        def __init__(self):
            self.cache = {}

        def __getattr__(self, name):
            try:
                return self.cache[name]
            except KeyError:
                custom = type(name, (super().__getattr__(name),), {})
                self.cache[name] = custom
                return custom


    def func_works(espace=BaseESpace()):
        raise espace.ValueError('foo')


    def func_bug(espace=BaseESpace()):
        int('xyz')


    espace = ESpace()

    try:
        func_works(espace=espace)
    except espace.ValueError:
        print('custom exception raised')
    except ValueError:
        print('builtin exception raised')

    try:
        func_works()
    except espace.ValueError:
        print('custom exception raised')
    except ValueError:
        print('builtin exception raised')

    try:
        func_bug()
    except espace.ValueError:
        print('custom exception raised')
    except ValueError:
        print('builtin exception raised')


So it seems there are plenty of options to realize this in custom projects without a change to the syntax. In any way, these approaches require the API developers to add the extra `espace` parameter to their functions, so all of this can only work based on mutual agreement.

Regarding operators, you can always `try / except` and then re-raise a similar exception from `espace`.


_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-leave@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/44WBWPOA36S2H5ZLUEFIZXUHG2AZGYHS/
Code of Conduct: http://python.org/psf/codeofconduct/