pycapnp icon indicating copy to clipboard operation
pycapnp copied to clipboard

Accept pathlike objects as paths

Open aldanor opened this issue 8 years ago • 1 comments

Currently, capnp.load(pathlib.Path(...)) (in Python 3) will fail with an obscure error like

AttributeError: _nodeSchema

Given that most of the standard library dealing with paths now accepts pathlike objects, it would be nice if pycapnp accepted them as well.

aldanor avatar Oct 13 '17 18:10 aldanor

It looks as though this may be a simple fix – I think if one were to change line 3981 in lib/capnp.pyx to read:

    self.path = os.fspath(path)

… that would enable support for pathlib.Path instances – as well as any other implementors of the __fspath__(…) method.

This unassumingly uncomplicated protocol is laid out in PEP 519. I’ve had nothing but success, myself, on either the producer- or consumer-end of the API.

Only two caveats. One, os.fspath(…) will raise if you call it with a None value. That’s not such a big deal.

Two, however, is that this function seems to have inherited the design parameters of many other long-lived denizens of os and os.path – in that it’s expected to reasonably and deterministically handle both byte-string and Unicode operands. Which this can be a bigger deal than it might seem.

To wit: if called with something that is determined to be bytes-y in nature, os.fspath(…) returns a byte-string; if called with a Unicode-ish strain of operand it comes back with Unicode data (known affectionately amongst Python 3.x fans like myself as “strings”). Since the entire raison d'être of this function is the normalization of heterogenous non-string path formats into predictably-arranged string data, the distinctions made in this mechanism can lead to subtleties in its operation at runtime that, like a lot of bytes-vs.-Unicode stuff, can be confounding to debug.

Case in point, if a byte-string instance enters a code path in which a call to os.fspath(…) is made, and that code path has only been tested with Unicode instances, the os.fspath(…) call will return a byte-string, per the expectations of its protocol. The code path is now operating in an untested state, which may or may not be correct; likewise, static type hints may or may not catch this condition.

I’m just sayin’. I learned this the hard way, so yeah. I specifically am pointing out the byte-string stuff because the way(s) Cython handles std::string conversion goes through the bytes builtin type, IIRC.

fish2000 avatar Feb 26 '20 03:02 fish2000