2020import os
2121import re
2222import sys
23- from collections .abc import Iterable , Iterator , Mapping , MutableMapping
23+ from collections .abc import Iterator , Mapping , MutableMapping
2424from pathlib import Path
2525from typing import TYPE_CHECKING , Any , ClassVar , NoReturn
2626
@@ -134,7 +134,7 @@ def make_config_parser(
134134 return parser
135135
136136
137- def _determine_quality (qual : str ) -> str :
137+ def _determine_quality (qual : str | None ) -> str :
138138 for quality , values in constants .QUALITIES .items ():
139139 if values ["flag" ] is not None and values ["flag" ] == qual :
140140 return quality
@@ -338,6 +338,7 @@ def __len__(self) -> int:
338338
339339 def __contains__ (self , key : object ) -> bool :
340340 try :
341+ assert isinstance (key , str )
341342 self .__getitem__ (key )
342343 return True
343344 except AttributeError :
@@ -428,7 +429,7 @@ def __deepcopy__(self, memo: dict[str, Any]) -> Self:
428429 # Deepcopying the underlying dict is enough because all properties
429430 # either read directly from it or compute their value on the fly from
430431 # values read directly from it.
431- c ._d = copy .deepcopy (self ._d , memo )
432+ c ._d = copy .deepcopy (self ._d , memo ) # type: ignore[arg-type]
432433 return c
433434
434435 # helper type-checking methods
@@ -655,13 +656,15 @@ def digest_parser(self, parser: configparser.ConfigParser) -> Self:
655656 "window_size"
656657 ] # if not "default", get a tuple of the position
657658 if window_size != "default" :
658- window_size = tuple (map (int , re .split (r"[;,\-]" , window_size )))
659- self .window_size = window_size
659+ window_size_numbers = tuple (map (int , re .split (r"[;,\-]" , window_size )))
660+ self .window_size = window_size_numbers
661+ else :
662+ self .window_size = window_size
660663
661664 # plugins
662665 plugins = parser ["CLI" ].get ("plugins" , fallback = "" , raw = True )
663- plugins = [] if plugins == "" else plugins .split ("," )
664- self .plugins = plugins
666+ plugin_list = [] if plugins is None or plugins == "" else plugins .split ("," )
667+ self .plugins = plugin_list
665668 # the next two must be set AFTER digesting pixel_width and pixel_height
666669 self ["frame_height" ] = parser ["CLI" ].getfloat ("frame_height" , 8.0 )
667670 width = parser ["CLI" ].getfloat ("frame_width" , None )
@@ -671,31 +674,31 @@ def digest_parser(self, parser: configparser.ConfigParser) -> Self:
671674 self ["frame_width" ] = width
672675
673676 # other logic
674- val = parser ["CLI" ].get ("tex_template_file" )
675- if val :
676- self .tex_template_file = val
677+ tex_template_file = parser ["CLI" ].get ("tex_template_file" )
678+ if tex_template_file :
679+ self .tex_template_file = Path ( tex_template_file )
677680
678- val = parser ["CLI" ].get ("progress_bar" )
679- if val :
680- self .progress_bar = val
681+ progress_bar = parser ["CLI" ].get ("progress_bar" )
682+ if progress_bar :
683+ self .progress_bar = progress_bar
681684
682- val = parser ["ffmpeg" ].get ("loglevel" )
683- if val :
684- self .ffmpeg_loglevel = val
685+ ffmpeg_loglevel = parser ["ffmpeg" ].get ("loglevel" )
686+ if ffmpeg_loglevel :
687+ self .ffmpeg_loglevel = ffmpeg_loglevel
685688
686689 try :
687- val = parser ["jupyter" ].getboolean ("media_embed" )
690+ media_embed = parser ["jupyter" ].getboolean ("media_embed" )
688691 except ValueError :
689- val = None
690- self .media_embed = val
692+ media_embed = None
693+ self .media_embed = media_embed
691694
692- val = parser ["jupyter" ].get ("media_width" )
693- if val :
694- self .media_width = val
695+ media_width = parser ["jupyter" ].get ("media_width" )
696+ if media_width :
697+ self .media_width = media_width
695698
696- val = parser ["CLI" ].get ("quality" , fallback = "" , raw = True )
697- if val :
698- self .quality = _determine_quality (val )
699+ quality = parser ["CLI" ].get ("quality" , fallback = "" , raw = True )
700+ if quality :
701+ self .quality = _determine_quality (quality )
699702
700703 return self
701704
@@ -1044,7 +1047,7 @@ def verbosity(self, val: str) -> None:
10441047 logger .setLevel (val )
10451048
10461049 @property
1047- def format (self ) -> str :
1050+ def format (self ) -> str | None :
10481051 """File format; "png", "gif", "mp4", "webm" or "mov"."""
10491052 return self ._d ["format" ]
10501053
@@ -1076,7 +1079,7 @@ def ffmpeg_loglevel(self, val: str) -> None:
10761079 logging .getLogger ("libav" ).setLevel (self .ffmpeg_loglevel )
10771080
10781081 @property
1079- def media_embed (self ) -> bool :
1082+ def media_embed (self ) -> bool | None :
10801083 """Whether to embed videos in Jupyter notebook."""
10811084 return self ._d ["media_embed" ]
10821085
@@ -1112,8 +1115,10 @@ def pixel_height(self, value: int) -> None:
11121115 self ._set_pos_number ("pixel_height" , value , False )
11131116
11141117 @property
1115- def aspect_ratio (self ) -> int :
1118+ def aspect_ratio (self ) -> float :
11161119 """Aspect ratio (width / height) in pixels (--resolution, -r)."""
1120+ assert isinstance (self ._d ["pixel_width" ], int )
1121+ assert isinstance (self ._d ["pixel_height" ], int )
11171122 return self ._d ["pixel_width" ] / self ._d ["pixel_height" ]
11181123
11191124 @property
@@ -1137,22 +1142,22 @@ def frame_width(self, value: float) -> None:
11371142 @property
11381143 def frame_y_radius (self ) -> float :
11391144 """Half the frame height (no flag)."""
1140- return self ._d ["frame_height" ] / 2
1145+ return self ._d ["frame_height" ] / 2 # type: ignore[operator]
11411146
11421147 @frame_y_radius .setter
11431148 def frame_y_radius (self , value : float ) -> None :
1144- self ._d .__setitem__ ("frame_y_radius" , value ) or self ._d .__setitem__ (
1149+ self ._d .__setitem__ ("frame_y_radius" , value ) or self ._d .__setitem__ ( # type: ignore[func-returns-value]
11451150 "frame_height" , 2 * value
11461151 )
11471152
11481153 @property
11491154 def frame_x_radius (self ) -> float :
11501155 """Half the frame width (no flag)."""
1151- return self ._d ["frame_width" ] / 2
1156+ return self ._d ["frame_width" ] / 2 # type: ignore[operator]
11521157
11531158 @frame_x_radius .setter
11541159 def frame_x_radius (self , value : float ) -> None :
1155- self ._d .__setitem__ ("frame_x_radius" , value ) or self ._d .__setitem__ (
1160+ self ._d .__setitem__ ("frame_x_radius" , value ) or self ._d .__setitem__ ( # type: ignore[func-returns-value]
11561161 "frame_width" , 2 * value
11571162 )
11581163
@@ -1285,7 +1290,7 @@ def frame_size(self) -> tuple[int, int]:
12851290
12861291 @frame_size .setter
12871292 def frame_size (self , value : tuple [int , int ]) -> None :
1288- self ._d .__setitem__ ("pixel_width" , value [0 ]) or self ._d .__setitem__ (
1293+ self ._d .__setitem__ ("pixel_width" , value [0 ]) or self ._d .__setitem__ ( # type: ignore[func-returns-value]
12891294 "pixel_height" , value [1 ]
12901295 )
12911296
@@ -1295,7 +1300,7 @@ def quality(self) -> str | None:
12951300 keys = ["pixel_width" , "pixel_height" , "frame_rate" ]
12961301 q = {k : self [k ] for k in keys }
12971302 for qual in constants .QUALITIES :
1298- if all (q [k ] == constants .QUALITIES [qual ][k ] for k in keys ):
1303+ if all (q [k ] == constants .QUALITIES [qual ][k ] for k in keys ): # type: ignore[literal-required]
12991304 return qual
13001305 return None
13011306
@@ -1312,6 +1317,7 @@ def quality(self, value: str | None) -> None:
13121317 @property
13131318 def transparent (self ) -> bool :
13141319 """Whether the background opacity is less than 1.0 (-t)."""
1320+ assert isinstance (self ._d ["background_opacity" ], float )
13151321 return self ._d ["background_opacity" ] < 1.0
13161322
13171323 @transparent .setter
@@ -1421,12 +1427,12 @@ def window_position(self, value: str) -> None:
14211427 self ._d .__setitem__ ("window_position" , value )
14221428
14231429 @property
1424- def window_size (self ) -> str :
1425- """The size of the opengl window as 'width,height' or 'default' to automatically scale the window based on the display monitor."""
1430+ def window_size (self ) -> str | tuple [ int , ...] :
1431+ """The size of the opengl window. 'default' to automatically scale the window based on the display monitor."""
14261432 return self ._d ["window_size" ]
14271433
14281434 @window_size .setter
1429- def window_size (self , value : str ) -> None :
1435+ def window_size (self , value : str | tuple [ int , ...] ) -> None :
14301436 self ._d .__setitem__ ("window_size" , value )
14311437
14321438 def resolve_movie_file_extension (self , is_transparent : bool ) -> None :
@@ -1455,7 +1461,7 @@ def enable_gui(self, value: bool) -> None:
14551461 self ._set_boolean ("enable_gui" , value )
14561462
14571463 @property
1458- def gui_location (self ) -> tuple [Any ]:
1464+ def gui_location (self ) -> tuple [int , ... ]:
14591465 """Location parameters for the GUI window (e.g., screen coordinates or layout settings)."""
14601466 return self ._d ["gui_location" ]
14611467
@@ -1639,6 +1645,7 @@ def get_dir(self, key: str, **kwargs: Any) -> Path:
16391645 all_args ["quality" ] = f"{ self .pixel_height } p{ self .frame_rate :g} "
16401646
16411647 path = self ._d [key ]
1648+ assert isinstance (path , str )
16421649 while "{" in path :
16431650 try :
16441651 path = path .format (** all_args )
@@ -1738,7 +1745,7 @@ def custom_folders(self, value: str | Path) -> None:
17381745 self ._set_dir ("custom_folders" , value )
17391746
17401747 @property
1741- def input_file (self ) -> str :
1748+ def input_file (self ) -> str | Path :
17421749 """Input file name."""
17431750 return self ._d ["input_file" ]
17441751
@@ -1767,7 +1774,7 @@ def scene_names(self, value: list[str]) -> None:
17671774 @property
17681775 def tex_template (self ) -> TexTemplate :
17691776 """Template used when rendering Tex. See :class:`.TexTemplate`."""
1770- if not hasattr (self , "_tex_template" ) or not self ._tex_template :
1777+ if not hasattr (self , "_tex_template" ) or not self ._tex_template : # type: ignore[has-type]
17711778 fn = self ._d ["tex_template_file" ]
17721779 if fn :
17731780 self ._tex_template = TexTemplate .from_file (fn )
@@ -1803,7 +1810,7 @@ def plugins(self) -> list[str]:
18031810 return self ._d ["plugins" ]
18041811
18051812 @plugins .setter
1806- def plugins (self , value : list [str ]):
1813+ def plugins (self , value : list [str ]) -> None :
18071814 self ._d ["plugins" ] = value
18081815
18091816 @property
@@ -1861,15 +1868,15 @@ def __init__(self, c: ManimConfig) -> None:
18611868 self .__dict__ ["_c" ] = c
18621869
18631870 # there are required by parent class Mapping to behave like a dict
1864- def __getitem__ (self , key : str | int ) -> Any :
1871+ def __getitem__ (self , key : str ) -> Any :
18651872 if key in self ._OPTS :
18661873 return self ._c [key ]
18671874 elif key in self ._CONSTANTS :
18681875 return self ._CONSTANTS [key ]
18691876 else :
18701877 raise KeyError (key )
18711878
1872- def __iter__ (self ) -> Iterable [ str ]:
1879+ def __iter__ (self ) -> Iterator [ Any ]:
18731880 return iter (list (self ._OPTS ) + list (self ._CONSTANTS ))
18741881
18751882 def __len__ (self ) -> int :
@@ -1887,4 +1894,4 @@ def __delitem__(self, key: Any) -> NoReturn:
18871894
18881895
18891896for opt in list (ManimFrame ._OPTS ) + list (ManimFrame ._CONSTANTS ):
1890- setattr (ManimFrame , opt , property (lambda self , o = opt : self [o ]))
1897+ setattr (ManimFrame , opt , property (lambda self , o = opt : self [o ])) # type: ignore[misc]
0 commit comments