[extractor] Use classmethod/property where possible

and refactor lazy extractors accordingly.

This reduces the need to create extractor instances
This commit is contained in:
pukkandan 2022-05-11 21:24:44 +05:30
parent 7ddbf09c25
commit 82d020804d
No known key found for this signature in database
GPG key ID: 7EEE9E1E817D0A39
11 changed files with 188 additions and 167 deletions

View file

@ -1,30 +1,28 @@
import importlib
import random
import re
from ..utils import bug_reports_message, write_string
from ..utils import bug_reports_message, classproperty, write_string
class LazyLoadMetaClass(type):
def __getattr__(cls, name):
if '_real_class' not in cls.__dict__:
# "is_suitable" requires "_TESTS". However, they bloat the lazy_extractors
if '_real_class' not in cls.__dict__ and name not in ('is_suitable', 'get_testcases'):
write_string(
'WARNING: Falling back to normal extractor since lazy extractor '
f'{cls.__name__} does not have attribute {name}{bug_reports_message()}')
return getattr(cls._get_real_class(), name)
f'{cls.__name__} does not have attribute {name}{bug_reports_message()}\n')
return getattr(cls.real_class, name)
class LazyLoadExtractor(metaclass=LazyLoadMetaClass):
_module = None
_WORKING = True
@classmethod
def _get_real_class(cls):
@classproperty
def real_class(cls):
if '_real_class' not in cls.__dict__:
mod = __import__(cls._module, fromlist=(cls.__name__,))
cls._real_class = getattr(mod, cls.__name__)
cls._real_class = getattr(importlib.import_module(cls._module), cls.__name__)
return cls._real_class
def __new__(cls, *args, **kwargs):
real_cls = cls._get_real_class()
instance = real_cls.__new__(real_cls)
instance = cls.real_class.__new__(cls.real_class)
instance.__init__(*args, **kwargs)
return instance