Skip to content

Commit

Permalink
Use abc.ABC as baseclass for AnyPath to fix issubclass behavior (#251)
Browse files Browse the repository at this point in the history
* Use abc.ABC as baseclass for AnyPath

* add type ignore for ABC.register
  • Loading branch information
chbehrens authored Aug 18, 2022
1 parent 1f28327 commit b5cdc3f
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 13 deletions.
19 changes: 6 additions & 13 deletions cloudpathlib/anypath.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,13 @@
import os
from abc import ABC
from pathlib import Path
from typing import Union

from .cloudpath import InvalidPrefixError, CloudPath
from .exceptions import AnyPathTypeError


class AnyPathMeta(type):
"""Metaclass for AnyPath that implements special methods so that AnyPath works as a virtual
superclass when using isinstance or issubclass checks on CloudPath or Path inputs. See
[PEP 3119](https://www.python.org/dev/peps/pep-3119/#overloading-isinstance-and-issubclass)."""

def __instancecheck__(cls, inst):
return isinstance(inst, CloudPath) or isinstance(inst, Path)

def __subclasscheck__(cls, sub):
return issubclass(sub, CloudPath) or issubclass(sub, Path)


class AnyPath(metaclass=AnyPathMeta):
class AnyPath(ABC):
"""Polymorphic virtual superclass for CloudPath and pathlib.Path. Constructing an instance will
automatically dispatch to CloudPath or Path based on the input. It also supports both
isinstance and issubclass checks.
Expand Down Expand Up @@ -55,6 +44,10 @@ def _validate(cls, value) -> Union[CloudPath, Path]:
return cls.__new__(cls, value)


AnyPath.register(CloudPath) # type: ignore
AnyPath.register(Path)


def to_anypath(s: Union[str, os.PathLike]) -> Union[CloudPath, Path]:
"""Convenience method to convert a str or os.PathLike to the
proper Path or CloudPath object using AnyPath.
Expand Down
4 changes: 4 additions & 0 deletions tests/test_anypath.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,7 @@ def test_anypath_cloudpath(rig):
def test_anypath_bad_input():
with pytest.raises(AnyPathTypeError):
AnyPath(0)


def test_anypath_subclass_anypath():
assert issubclass(AnyPath, AnyPath)

0 comments on commit b5cdc3f

Please sign in to comment.