8
8
9
9
from __future__ import annotations
10
10
11
- import http .client
12
11
import json
12
+ import os
13
13
import sys
14
- import urllib .error
15
- import urllib .request
14
+ import time
16
15
from argparse import Namespace
17
16
from pathlib import Path
18
17
from typing import TYPE_CHECKING , Any , cast
@@ -100,8 +99,8 @@ def render(**kwargs: Any) -> ClickArgs | dict[str, Any]:
100
99
return click_args
101
100
102
101
config .digest_args (click_args )
103
- file = Path ( config . input_file )
104
- scenes = solve_rendrered_scenes (file )
102
+
103
+ scenes = solve_rendrered_scenes (config . input_file )
105
104
106
105
if config .renderer == RendererType .OPENGL :
107
106
from manim .renderer .opengl_renderer import OpenGLRenderer
@@ -143,41 +142,53 @@ def render(**kwargs: Any) -> ClickArgs | dict[str, Any]:
143
142
144
143
145
144
def version_notification () -> None :
146
- ### NOTE TODO This has fundamental problem of connecting every time into internet
147
- ### As many times Renders are executed during a day.
148
- ### There should be a caching mechanisim that will safe simple timecode and result in
149
- ### Cached file to be fetched in most of times.
145
+ """Fetch version from Internet or use cache"""
146
+ file = Path (os .path .dirname (__file__ )) / ".version_cache.log"
147
+ stable = None
148
+
149
+ if file .exists ():
150
+ with file .open () as f :
151
+ last_time = f .readline ()
152
+ if not time .time () - int (last_time ) > 86_400 :
153
+ stable = f .readline ()
154
+
155
+ if stable is None :
156
+ new_stable = fetch_version ()
157
+ if new_stable :
158
+ with file .open (mode = "w" ) as f :
159
+ f .write (str (int (time .time ())) + "\n " + str (new_stable ))
160
+ stable = new_stable
161
+
162
+ if stable != __version__ :
163
+ console .print (
164
+ f"You are using manim version [red]v{ __version__ } [/red], but version [green]v{ stable } [/green] is available." ,
165
+ )
166
+ console .print (
167
+ "You should consider upgrading via [yellow]pip install -U manim[/yellow]" ,
168
+ )
169
+
170
+
171
+ def fetch_version () -> str | None :
172
+ import http .client
173
+ import urllib .error
174
+ import urllib .request
150
175
151
176
manim_info_url = "https://pypi.org/pypi/manim/json"
152
177
warn_prompt = "Cannot check if latest release of manim is installed"
153
-
178
+ request = urllib . request . Request ( manim_info_url )
154
179
try :
155
- with urllib .request .urlopen (
156
- urllib .request .Request (manim_info_url ),
157
- timeout = 10 ,
158
- ) as response :
180
+ with urllib .request .urlopen (request , timeout = 10 ) as response :
159
181
response = cast (http .client .HTTPResponse , response )
160
182
json_data = json .loads (response .read ())
161
- except urllib . error . HTTPError :
162
- logger . debug ( "HTTP Error: %s" , warn_prompt )
163
- except urllib . error . URLError :
164
- logger . debug ( "URL Error: %s" , warn_prompt )
183
+
184
+ except ( Exception , urllib . error . HTTPError , urllib . error . URLError ) as e :
185
+ logger . debug ( f" { e } : { warn_prompt } " )
186
+ return None
165
187
except json .JSONDecodeError :
166
- logger .debug (
167
- "Error while decoding JSON from %r: %s" , manim_info_url , warn_prompt
168
- )
169
- except Exception :
170
- logger .debug ("Something went wrong: %s" , warn_prompt )
188
+ logger .debug (f"Error while decoding JSON from [{ manim_info_url } ]: warn_prompt" )
189
+ return None
171
190
else :
172
- stable = json_data ["info" ]["version" ]
173
-
174
- if stable != __version__ :
175
- console .print (
176
- f"You are using manim version [red]v{ __version__ } [/red], but version [green]v{ stable } [/green] is available." ,
177
- )
178
- console .print (
179
- "You should consider upgrading via [yellow]pip install -U manim[/yellow]" ,
180
- )
191
+ return str (json_data ["info" ]["version" ])
181
192
182
193
183
194
def warn_and_change_deprecated_args (kwargs : dict [str , Any ]) -> None :
@@ -198,7 +209,14 @@ def warn_and_change_deprecated_args(kwargs: dict[str, Any]) -> None:
198
209
)
199
210
200
211
201
- def get_scenes_to_render (scene_classes : list [type [Scene ]]) -> list [type [Scene ]]:
212
+ def select_scenes (scene_classes : list [type [Scene ]]) -> list [type [Scene ]]:
213
+ """Collection of selection checks for inserted scenes"""
214
+ if not scene_classes :
215
+ logger .error (NO_SCENE_MESSAGE )
216
+ return []
217
+ elif config .write_all :
218
+ return scene_classes
219
+
202
220
result = []
203
221
for scene_name in config .scene_names :
204
222
found = False
@@ -230,11 +248,11 @@ def get_scenes_to_render(scene_classes: list[type[Scene]]) -> list[type[Scene]]:
230
248
return classes
231
249
232
250
233
- def solve_rendrered_scenes (file_path_input : Path | str ) -> list [type [Scene ]]:
251
+ def solve_rendrered_scenes (file_path_input : str ) -> list [type [Scene ]]:
234
252
"""Return scenes from file path or create CLI prompt for input"""
235
253
from ...scene .scene import Scene
236
254
237
- if str ( file_path_input ) == "-" :
255
+ if file_path_input == "-" :
238
256
try :
239
257
code = code_input_prompt ()
240
258
module = module_from_text (code )
@@ -248,10 +266,4 @@ def solve_rendrered_scenes(file_path_input: Path | str) -> list[type[Scene]]:
248
266
249
267
scenes = search_classes_from_module (module , Scene )
250
268
251
- if not scenes :
252
- logger .error (NO_SCENE_MESSAGE )
253
- return []
254
- elif config .write_all :
255
- return scenes
256
- else :
257
- return get_scenes_to_render (scenes )
269
+ return select_scenes (scenes )
0 commit comments