Implementation Notes

Using the Accessor

The standard library’s pathlib module already includes the notion of an accessor, but it is bypassed in certain cases, such as:

  • str(self) called to get a local filesystem path
  • os.close() called to close file descriptors
  • os.getcwd() called to get the working directory
  • os.fsencode() called to get a bytes representation of a path
  • os.environ accessed to expand ~
  • pwd and grp used to retrieve user and group names

Pathlab fixes these instances by subclassing pathlib.Path as pathlab.Path and re-implementing the problematic methods. This includes a few additions and changes to the accessor interface.

Flavouring the Accessor

The standard library’s pathlib module uses a flavour object to handle pure path semantics. As before, this abstraction is leaky. Pathlab makes no distinction between the path accessor and flavour, and so allows methods like casefold() to be re-implemented.

Binding the Accessor

The standard library’s pathlib module provides limited means of storing state. A path instance may have its _accessor attribute customized, and in some cases derived path instances are initialized with path._init(template=self) to make the new path use the same accessor. However, this mechanism is used inconsistently.

Pathlab solves this by creating a new path type per accessor instance. The accessor instance is bound to the new type as a class attribute. Therefore the inheritance chain of an accessor’s path type is as follows:

Path inheritance chain
Abstract Pure Class
pathlib.PurePath
  pathlib.Path
pathlab.Path
mylib.MyPath
  mylib.MyAccessor(...).MyPath