2022-05-11 15:54:44 +00:00
|
|
|
import importlib
|
|
|
|
import random
|
2016-02-10 13:01:31 +00:00
|
|
|
import re
|
|
|
|
|
2022-05-16 14:06:36 +00:00
|
|
|
from ..utils import (
|
|
|
|
age_restricted,
|
|
|
|
bug_reports_message,
|
|
|
|
classproperty,
|
2023-06-21 21:27:00 +00:00
|
|
|
variadic,
|
2022-05-16 14:06:36 +00:00
|
|
|
write_string,
|
|
|
|
)
|
2021-09-17 18:23:55 +00:00
|
|
|
|
2022-08-01 01:22:03 +00:00
|
|
|
# These bloat the lazy_extractors, so allow them to passthrough silently
|
2022-11-16 00:57:43 +00:00
|
|
|
ALLOWED_CLASSMETHODS = {'extract_from_webpage', 'get_testcases', 'get_webpage_testcases'}
|
2022-08-24 09:40:21 +00:00
|
|
|
_WARNED = False
|
2022-08-01 01:22:03 +00:00
|
|
|
|
2016-02-10 13:01:31 +00:00
|
|
|
|
2021-08-22 22:18:26 +00:00
|
|
|
class LazyLoadMetaClass(type):
|
|
|
|
def __getattr__(cls, name):
|
2022-08-24 09:40:21 +00:00
|
|
|
global _WARNED
|
|
|
|
if ('_real_class' not in cls.__dict__
|
|
|
|
and name not in ALLOWED_CLASSMETHODS and not _WARNED):
|
|
|
|
_WARNED = True
|
|
|
|
write_string('WARNING: Falling back to normal extractor since lazy extractor '
|
|
|
|
f'{cls.__name__} does not have attribute {name}{bug_reports_message()}\n')
|
2022-05-11 15:54:44 +00:00
|
|
|
return getattr(cls.real_class, name)
|
2021-08-22 22:18:26 +00:00
|
|
|
|
|
|
|
|
|
|
|
class LazyLoadExtractor(metaclass=LazyLoadMetaClass):
|
2022-05-11 15:54:44 +00:00
|
|
|
@classproperty
|
|
|
|
def real_class(cls):
|
2021-09-17 18:23:55 +00:00
|
|
|
if '_real_class' not in cls.__dict__:
|
2022-05-11 15:54:44 +00:00
|
|
|
cls._real_class = getattr(importlib.import_module(cls._module), cls.__name__)
|
2021-09-17 18:23:55 +00:00
|
|
|
return cls._real_class
|
2021-08-22 22:18:26 +00:00
|
|
|
|
2016-02-21 11:46:14 +00:00
|
|
|
def __new__(cls, *args, **kwargs):
|
2022-05-11 15:54:44 +00:00
|
|
|
instance = cls.real_class.__new__(cls.real_class)
|
2016-02-21 11:46:14 +00:00
|
|
|
instance.__init__(*args, **kwargs)
|
|
|
|
return instance
|