On Jan 21, 2020, at 09:13, Christopher Barker <[email protected]> wrote:
> 
> For (2) — see above— I want the relevant Python object, not just the string 
> or bytes. A good example of this is the utilities (img2py I think) that come 
> with wxPython: They bundle up a set of images into a Python module that 
> creates wxImages on the fly. So you can import the module, and have a set of 
> wxImages ready to go. That is pretty nice. 
> 
> I do think there could be some utilities to make that kind of thing easier, 
> but making it easy, with a built in, to simply get the bytes or text from a 
> file wouldn’t buy us much.

I just had a thought on this.

What if you had an importhooker module that allowed you to do this in your 
top-level script or module:

    from importhooker import hook

    import json
    from PIL import Image
    import mything 

    @hook(text=True)
    def json(f):
        return json.load(f)

    @hook(names="png jpg jpeg gif".split())
    def image(f):
        return Image.load(f)

    hook(mything.import, text=True, names=["my”])

Note that the last one could actually be a custom Python dialect that adds some 
new DSL or macro system or whatever; you’d still have to write the hard part of 
the code that duplicates the normal py importer but adds in a 
text/token/ast/bytecode transformer or whatever in the middle, but you’d get 
all the boilerplate (the part that’s very hard to figure out how to write the 
first time, and uninteresting after that) for free. But the other ones are the 
real point; they make it trivial to load image resources, etc., because there 
is no hard part beyond the boilerplate.

The import hook effectively does this pseudo code:

    packagename, basename = split(name)
    package = load_package(packagename)
    for hook in registry:
        filename = f"{basename}.{hook.ext}"
        try:
            f = importlib.resources.open_file(hook.text)
        except ?:
            continue
        with f:
            return hook.callback(f)

And now, in any of your other modules, you could do this:

    # load cheese.png as a Pillow image named cheese
    from spam.images import cheese

    # load devconfig.json as a dict named config
    from spam import devconfig as config

    # load thing.my as a module named thing
    from spam import thing

The API is just off the top of my head. You could add more arguments to control 
encoding (otherwise it does the normal importlib thing of looking for a coding 
declaration and falling back to UTF-8, which could be very wrong for some file 
types), .pyc caching, sys.modules caching, etc.; I haven’t thought of what 
might be useful and doable.

Anyway, this would still have all the limitations of import hooks. For example, 
you can’t have a cheese.png and cheese.py or cheese.json in the same package. 
And using it would have a performance cost (e.g., with all the hooks I added, a 
failed import is going to take at least 3x as long to fail…). It just means 
that you don’t have to write and install an import hook, figure out how to use 
the normal machinery for the parts you’re not trying to change, worry about the 
annoying error handling stuff (last I checked you have to manually construct 
the ImportError out of the inner exception while doing some clunky stuff to 
make it skip over irrelevant machinery in the callstack), etc.

Obviously you’d have to require importhooker off PyPI (and it would require 
3.7+ or 3.4+ with a resources backport), which isn’t a problem for things 
you’re distributing on PyPI or packaging up with py2exe or whatever but might 
be limiting for people who want to create complicated packages and use them 
right out of the build tree. But if this were useful enough, it could be added 
into importlib in some future Python version.

Anyway, I think this would be a lot more useful than anything that just gives 
you the raw bytes or text of a resource file. I’m not sure it’s useful enough 
to be worth building. But it might be fun enough to try even if I can’t think 
of a good use. :)

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

Reply via email to