88
99def _load_jellyfin_module ():
1010 module_name = "_test_jellyfin_module"
11- if module_name in sys .modules :
12- return sys .modules [module_name ]
13-
14- if "app.log" not in sys .modules :
15- log_module = types .ModuleType ("app.log" )
16-
17- class _Logger :
18- def info (self , * _args , ** _kwargs ):
19- pass
20-
21- def warning (self , * _args , ** _kwargs ):
22- pass
23-
24- def error (self , * _args , ** _kwargs ):
25- pass
26-
27- def debug (self , * _args , ** _kwargs ):
28- pass
29-
30- log_module .logger = _Logger ()
31- sys .modules ["app.log" ] = log_module
32-
33- if "app.core.config" not in sys .modules :
34- config_module = types .ModuleType ("app.core.config" )
35- config_module .settings = types .SimpleNamespace (SUPERUSER = "admin" , USER_AGENT = "MoviePilot" )
36- sys .modules ["app.core.config" ] = config_module
37-
38- if "app.schemas" not in sys .modules :
39- schemas_module = types .ModuleType ("app.schemas" )
40- schemas_module .MediaType = types .SimpleNamespace (MOVIE = types .SimpleNamespace (value = "movie" ))
41- schemas_module .MediaServerItem = object
42- schemas_module .MediaServerLibrary = object
43- schemas_module .Statistic = object
44- schemas_module .WebhookEventInfo = object
45- schemas_module .MediaServerItemUserState = object
46- schemas_module .MediaServerPlayItem = object
47- sys .modules ["app.schemas" ] = schemas_module
48-
49- if "app.utils.http" not in sys .modules :
50- http_module = types .ModuleType ("app.utils.http" )
51-
52- class _RequestUtils :
53- def __init__ (self , * args , ** kwargs ):
54- pass
55-
56- def get_res (self , * args , ** kwargs ):
57- return None
58-
59- http_module .RequestUtils = _RequestUtils
60- sys .modules ["app.utils.http" ] = http_module
61-
62- if "app.utils.url" not in sys .modules :
63- url_module = types .ModuleType ("app.utils.url" )
64-
65- class _UrlUtils :
66- @staticmethod
67- def standardize_base_url (host ):
68- if not host :
69- return host
70- if not host .endswith ("/" ):
71- host += "/"
72- if not host .startswith ("http://" ) and not host .startswith ("https://" ):
73- host = "http://" + host
11+ app_module = types .ModuleType ("app" )
12+ core_module = types .ModuleType ("app.core" )
13+ utils_module = types .ModuleType ("app.utils" )
14+ log_module = types .ModuleType ("app.log" )
15+ config_module = types .ModuleType ("app.core.config" )
16+ schemas_module = types .ModuleType ("app.schemas" )
17+ http_module = types .ModuleType ("app.utils.http" )
18+ url_module = types .ModuleType ("app.utils.url" )
19+
20+ class _Logger :
21+ def info (self , * _args , ** _kwargs ):
22+ pass
23+
24+ def warning (self , * _args , ** _kwargs ):
25+ pass
26+
27+ def error (self , * _args , ** _kwargs ):
28+ pass
29+
30+ def debug (self , * _args , ** _kwargs ):
31+ pass
32+
33+ class _RequestUtils :
34+ def __init__ (self , * args , ** kwargs ):
35+ pass
36+
37+ def get_res (self , * args , ** kwargs ):
38+ return None
39+
40+ class _UrlUtils :
41+ @staticmethod
42+ def standardize_base_url (host ):
43+ if not host :
7444 return host
75-
76- @staticmethod
77- def combine_url (host , path = None , query = None ):
78- from urllib .parse import urljoin
79-
80- if path is None :
81- path = "/"
82- host = _UrlUtils .standardize_base_url (host )
83- return urljoin (host , path )
84-
85- url_module .UrlUtils = _UrlUtils
86- sys .modules ["app.utils.url" ] = url_module
45+ if not host .endswith ("/" ):
46+ host += "/"
47+ if not host .startswith ("http://" ) and not host .startswith ("https://" ):
48+ host = "http://" + host
49+ return host
50+
51+ @staticmethod
52+ def combine_url (host , path = None , query = None ):
53+ from urllib .parse import urljoin
54+
55+ if path is None :
56+ path = "/"
57+ host = _UrlUtils .standardize_base_url (host )
58+ return urljoin (host , path )
59+
60+ log_module .logger = _Logger ()
61+ config_module .settings = types .SimpleNamespace (SUPERUSER = "admin" , USER_AGENT = "MoviePilot" )
62+ schemas_module .MediaType = types .SimpleNamespace (MOVIE = types .SimpleNamespace (value = "movie" ))
63+ schemas_module .MediaServerItem = object
64+ schemas_module .MediaServerLibrary = object
65+ schemas_module .Statistic = object
66+ schemas_module .WebhookEventInfo = object
67+ schemas_module .MediaServerItemUserState = object
68+ schemas_module .MediaServerPlayItem = object
69+ http_module .RequestUtils = _RequestUtils
70+ url_module .UrlUtils = _UrlUtils
71+
72+ app_module .schemas = schemas_module
73+ app_module .log = log_module
74+ app_module .core = core_module
75+ app_module .utils = utils_module
76+ core_module .config = config_module
77+ utils_module .http = http_module
78+ utils_module .url = url_module
79+
80+ stub_modules = {
81+ "app" : app_module ,
82+ "app.log" : log_module ,
83+ "app.core" : core_module ,
84+ "app.core.config" : config_module ,
85+ "app.schemas" : schemas_module ,
86+ "app.utils" : utils_module ,
87+ "app.utils.http" : http_module ,
88+ "app.utils.url" : url_module ,
89+ }
90+ for stub_module in stub_modules .values ():
91+ stub_module ._jellyfin_test_stub = True
8792
8893 jellyfin_path = Path (__file__ ).resolve ().parents [1 ] / "app" / "modules" / "jellyfin" / "jellyfin.py"
8994 spec = importlib .util .spec_from_file_location (module_name , jellyfin_path )
9095 module = importlib .util .module_from_spec (spec )
91- sys .modules [module_name ] = module
9296 assert spec and spec .loader
93- spec .loader .exec_module (module )
97+ with patch .dict (sys .modules , stub_modules ):
98+ spec .loader .exec_module (module )
9499 return module
95100
96101
@@ -107,6 +112,12 @@ def json(self):
107112
108113
109114class JellyfinUserResolutionTest (unittest .TestCase ):
115+ def test_loader_does_not_leave_stub_modules_in_sys_modules (self ):
116+ self .assertNotIn ("_test_jellyfin_module" , sys .modules )
117+ self .assertFalse (getattr (sys .modules .get ("app.log" ), "_jellyfin_test_stub" , False ))
118+ self .assertFalse (getattr (sys .modules .get ("app.core.config" ), "_jellyfin_test_stub" , False ))
119+ self .assertFalse (getattr (sys .modules .get ("app.utils.http" ), "_jellyfin_test_stub" , False ))
120+
110121 def _build_client (self ) -> Jellyfin :
111122 client = Jellyfin .__new__ (Jellyfin )
112123 client ._host = "http://jellyfin.local:8096"
0 commit comments