88
99from __future__ import annotations
1010
11- import http .client
1211import json
12+ import os
1313import sys
14- import urllib .error
15- import urllib .request
14+ import time
1615from argparse import Namespace
1716from pathlib import Path
1817from typing import TYPE_CHECKING , Any , cast
@@ -100,8 +99,8 @@ def render(**kwargs: Any) -> ClickArgs | dict[str, Any]:
10099 return click_args
101100
102101 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 )
105104
106105 if config .renderer == RendererType .OPENGL :
107106 from manim .renderer .opengl_renderer import OpenGLRenderer
@@ -143,41 +142,53 @@ def render(**kwargs: Any) -> ClickArgs | dict[str, Any]:
143142
144143
145144def 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
150175
151176 manim_info_url = "https://pypi.org/pypi/manim/json"
152177 warn_prompt = "Cannot check if latest release of manim is installed"
153-
178+ request = urllib . request . Request ( manim_info_url )
154179 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 :
159181 response = cast (http .client .HTTPResponse , response )
160182 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
165187 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
171190 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" ])
181192
182193
183194def 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:
198209 )
199210
200211
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+
202220 result = []
203221 for scene_name in config .scene_names :
204222 found = False
@@ -230,11 +248,11 @@ def get_scenes_to_render(scene_classes: list[type[Scene]]) -> list[type[Scene]]:
230248 return classes
231249
232250
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 ]]:
234252 """Return scenes from file path or create CLI prompt for input"""
235253 from ...scene .scene import Scene
236254
237- if str ( file_path_input ) == "-" :
255+ if file_path_input == "-" :
238256 try :
239257 code = code_input_prompt ()
240258 module = module_from_text (code )
@@ -248,10 +266,4 @@ def solve_rendrered_scenes(file_path_input: Path | str) -> list[type[Scene]]:
248266
249267 scenes = search_classes_from_module (module , Scene )
250268
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