ionelmc / python-lazy-object-proxy

A fast and thorough lazy object proxy.
BSD 2-Clause "Simplified" License
247 stars 36 forks source link

Interaction of LOP with builtins is badly broken #31

Open KOLANICH opened 5 years ago

KOLANICH commented 5 years ago
from lazy_object_proxy import Proxy
import os

def a():
    return "."

c = Proxy(a)
os.path.exists(c)
ionelmc commented 5 years ago

Oooof ... looks like python2 os.stat will raise TypeError: coercing to Unicode: need string or buffer, Proxy found while on python3 you get a TypeError: 'str' object cannot be interpreted as an integer.

It would look like it fails at the argument parsing.

The problem is that the proxies (cext, simple and slots) all implement __index__ and it looks like stat tries to parse it as a fd (by converting to a number through __index__()).

Something like this would work with the pure python implementations but it's destructive you see ...

import os
from lazy_object_proxy.slots import Proxy

del Proxy.__index__  # DESTRUCTIVE

class PathProxy(Proxy):
    def __fspath__(self):
        return str(self)

os.stat(PathProxy(lambda: '.'))
KOLANICH commented 5 years ago

Thank you for the info. Can it be solved by

ionelmc commented 5 years ago

Annotations wouldn't help at all.

os.stat's checks basically do this:

Python is pretty broken with regard to capability checking (iow: checking if an object can do something or has a certain special method). While you can have a descriptor as a special method, and make it raise AttributeError most of the python code written in C will happily only check the existence of a slot for special method and forget about that silly descriptor stuff.

ionelmc commented 4 years ago

FYI v1.5.0 adds support for __fspath__. Perhaps this is no longer a problem on latest Python?

KOLANICH commented 4 years ago

Will try, thank you for getting me know. Though I am not sure if it will work for the versions of python not checking __fspath__ (i.e. 3.4 that is the latest version supporting Win XP).