Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Strictly follow PEP3119 for AnyPath __subclasscheck__ implementation #247

Conversation

chbehrens
Copy link
Contributor

The currently implemented subclass check for the AnyPathMeta class results in issubclass(AnyPath, AnyPath) returning False, opposed its expected behavior. With this PR I suggest to switch to the exact implementation shown in PEP 3119. It should resolve this problem while preserving the intended behavior with respect to CloudPath and pathlib.Path.

See #246

@chbehrens chbehrens force-pushed the improve-anypath-subclasscheck branch 2 times, most recently from 13fd5ed to 30b02b0 Compare August 16, 2022 18:39
@chbehrens
Copy link
Contributor Author

Sorry, I tested it before but messed it up during clean-up. Should be complete now.

@codecov-commenter
Copy link

codecov-commenter commented Aug 16, 2022

Codecov Report

Merging #247 (30b02b0) into master (4cc0d33) will decrease coverage by 0.5%.
The diff coverage is 100.0%.

@@           Coverage Diff            @@
##           master    #247     +/-   ##
========================================
- Coverage    95.0%   94.4%   -0.6%     
========================================
  Files          21      21             
  Lines        1324    1326      +2     
========================================
- Hits         1258    1253      -5     
- Misses         66      73      +7     
Impacted Files Coverage Δ
cloudpathlib/anypath.py 100.0% <100.0%> (ø)
cloudpathlib/s3/s3client.py 92.9% <0.0%> (-2.7%) ⬇️
cloudpathlib/gs/gsclient.py 92.8% <0.0%> (-1.8%) ⬇️
cloudpathlib/cloudpath.py 93.5% <0.0%> (-0.5%) ⬇️

@jayqi
Copy link
Member

jayqi commented Aug 16, 2022

I'm wondering if my original decision to use custom __subclasscheck__ and __instancecheck__ is the wrong approach here.

I believe another way of accomplishing what we want (that is also part of PEP 3119) is to have AnyPath subclass abc.ABC and use ABC.register. This would mean getting rid of our AnyPathMeta class since we wouldn't need it, and instead having

AnyPath.register(Path)
AnyPath.register(CloudPath)

I just did a little bit of light testing, and I think it should work equivalently and also resolve the issue of issubclass(AnyPath, AnyPath).


I'm lukewarm on the idea of copying the exact implementation for __subclasscheck__ and __instancecheck__ from PEP 3119. PEP 3119 describes those as "naively simple" from-scratch implementations. According to later in PEP 3119:

The call isinstance(x, C) first checks whether C.instancecheck exists, and if so, calls C.instancecheck(x) instead of its normal implementation. Similarly, the call issubclass(D, C) first checks whether C.subclasscheck exists, and if so, calls C.subclasscheck(D) instead of its normal implementation.

So that means by doing it this way with __subclasscheck__ and __instancecheck__, we're entirely responsible for the logic of isinstance and issubclass rather than leaning on any default logic.

@pjbull
Copy link
Member

pjbull commented Aug 17, 2022

I like the implementation @jayqi laid out. @chbehrens would you be willing to take a hack at that version?

Could you also add a test to the subclass tests to check the bug you filed in #246?

@chbehrens chbehrens force-pushed the improve-anypath-subclasscheck branch from 30b02b0 to c55d7d9 Compare August 17, 2022 11:54
@pjbull
Copy link
Member

pjbull commented Aug 18, 2022

Resolved by #251

@pjbull pjbull closed this Aug 18, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants