Skip to content

Commit d63469c

Browse files
committed
fix(auth): resolve LazyBasesMeta subclassing, thread safety, and recursion bugs
1 parent 1681884 commit d63469c

3 files changed

Lines changed: 38 additions & 3 deletions

File tree

packages/google-auth/google/auth/_helpers.py

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import json
2323
import logging
2424
import sys
25+
import threading
2526
from typing import Any, Dict, Mapping, Optional, Union
2627
import urllib
2728

@@ -545,15 +546,49 @@ class LazyBasesMeta(type):
545546
class is first instantiated, subclassed, or has its attributes inspected.
546547
"""
547548

549+
_lock = threading.RLock()
550+
551+
def __new__(mcls, name, bases, attrs):
552+
# Automatically resolve lazy bases of any base classes at subclass definition time.
553+
for base in bases:
554+
if isinstance(base, LazyBasesMeta):
555+
type(base)._resolve_bases(base)
556+
557+
cls = super(LazyBasesMeta, mcls).__new__(mcls, name, bases, attrs)
558+
type.__setattr__(cls, "_lazy_bases_resolved", False)
559+
return cls
560+
548561
def __call__(cls, *args, **kwargs):
549562
type(cls)._resolve_bases(cls)
550563
return super(LazyBasesMeta, cls).__call__(*args, **kwargs)
551564

552565
def __getattribute__(cls, name):
553-
type(cls)._resolve_bases(cls)
566+
if name not in (
567+
"_lazy_bases_resolved",
568+
"_resolve_bases",
569+
"_perform_resolve_bases",
570+
):
571+
type(cls)._resolve_bases(cls)
554572
return super(LazyBasesMeta, cls).__getattribute__(name)
555573

556574
def _resolve_bases(cls):
575+
try:
576+
resolved = type.__getattribute__(cls, "_lazy_bases_resolved")
577+
except AttributeError:
578+
resolved = False
579+
580+
if not resolved:
581+
with type(cls)._lock:
582+
try:
583+
resolved = type.__getattribute__(cls, "_lazy_bases_resolved")
584+
except AttributeError:
585+
resolved = False
586+
587+
if not resolved:
588+
type(cls)._perform_resolve_bases(cls)
589+
type.__setattr__(cls, "_lazy_bases_resolved", True)
590+
591+
def _perform_resolve_bases(cls):
557592
pass
558593

559594

packages/google-auth/google/auth/transport/requests.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363

6464

6565
class _LazyBasesMeta(_helpers.LazyBasesMeta):
66-
def _resolve_bases(cls):
66+
def _perform_resolve_bases(cls):
6767
current_bases = type.__getattribute__(cls, "__bases__")
6868
if current_bases == (_helpers.HeapDummy,):
6969
cls_name = type.__getattribute__(cls, "__name__")

packages/google-auth/google/auth/transport/urllib3.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474

7575

7676
class _LazyBasesMeta(_helpers.LazyBasesMeta):
77-
def _resolve_bases(cls):
77+
def _perform_resolve_bases(cls):
7878
current_bases = type.__getattribute__(cls, "__bases__")
7979
if current_bases == (_helpers.HeapDummy,):
8080
if version.parse(urllib3.__version__) >= version.parse("2.0.0"):

0 commit comments

Comments
 (0)