Repository: ManimCommunity/manim

Issue:
Can't set frame_width / frame_height via .cfg file
It seems strange but I can't change frame_width or frame_height via .cfg file.
I use the latest version of code from master branch. But it as well the same if I use Manim as lib.

I have this structure:
```
tests/manim.cfg
tests/main.py
```

manim.cfg
```cfg
[CLI]  
background_color = WHITE
frame_width = 2
frame_height = 4
```

main.py
```python
from manim import *

print(config.background_color)
print(config.frame_width)
print(config.frame_height)
```

OUTPUT
```shell
white
14.222222222222221
8.0
```

However, if I change values programmatically, not through .cfg file (if it comes to frame_width or frame_height) manim successfully change these config values as said in documentation.



Discussion:

Resolving patch:
diff --git a/manim/_config/utils.py b/manim/_config/utils.py
--- a/manim/_config/utils.py
+++ b/manim/_config/utils.py
@@ -516,6 +516,7 @@ def digest_parser(self, parser):
             "upto_animation_number",
             "frame_rate",
             "max_files_cached",
+            # the next two must be set BEFORE digesting frame_width and frame_height
             "pixel_height",
             "pixel_width",
         ]:
@@ -542,15 +543,23 @@ def digest_parser(self, parser):
             setattr(self, key, parser["CLI"].get(key, fallback="", raw=True))
 
         # float keys
-        for key in ["background_opacity"]:
+        for key in [
+            "background_opacity",
+            # the next two are floats but have their own logic, applied later
+            # "frame_width",
+            # "frame_height",
+        ]:
             setattr(self, key, parser["CLI"].getfloat(key))
 
-        # other logic
-        self["frame_height"] = 8.0
-        self["frame_width"] = (
-            self["frame_height"] * self["pixel_width"] / self["pixel_height"]
-        )
+        # the next two must be set AFTER digesting pixel_width and pixel_height
+        self["frame_height"] = parser["CLI"].getfloat("frame_height", 8.0)
+        width = parser["CLI"].getfloat("frame_width", None)
+        if width is None:
+            self["frame_width"] = self["frame_height"] * self["aspect_ratio"]
+        else:
+            self["frame_width"] = width
 
+        # other logic
         val = parser["CLI"].get("tex_template_file")
         if val:
             setattr(self, "tex_template_file", val)


Test patch:
diff --git a/tests/test_config.py b/tests/test_config.py
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -72,6 +72,7 @@ def test_digest_file(tmp_path):
             [CLI]
             media_dir = this_is_my_favorite_path
             video_dir = {media_dir}/videos
+            frame_height = 10
             """
         )
         tmp_cfg.close()
@@ -81,6 +82,49 @@ def test_digest_file(tmp_path):
         assert config.get_dir("video_dir") == Path("this_is_my_favorite_path/videos")
 
 
+def test_frame_size(tmp_path):
+    """Test that the frame size can be set via config file."""
+    assert np.allclose(config.aspect_ratio, config.pixel_width / config.pixel_height)
+    assert np.allclose(config.frame_height, 8.0)
+
+    with tempconfig({}):
+        tmp_cfg = tempfile.NamedTemporaryFile("w", dir=tmp_path, delete=False)
+        tmp_cfg.write(
+            """
+            [CLI]
+            pixel_height = 10
+            pixel_width = 10
+            """
+        )
+        tmp_cfg.close()
+        config.digest_file(tmp_cfg.name)
+
+        # aspect ratio is set using pixel measurements
+        assert np.allclose(config.aspect_ratio, 1.0)
+        # if not specified in the cfg file, frame_width is set using the aspect ratio
+        assert np.allclose(config.frame_height, 8.0)
+        assert np.allclose(config.frame_width, 8.0)
+
+    with tempconfig({}):
+        tmp_cfg = tempfile.NamedTemporaryFile("w", dir=tmp_path, delete=False)
+        tmp_cfg.write(
+            """
+            [CLI]
+            pixel_height = 10
+            pixel_width = 10
+            frame_height = 10
+            frame_width = 10
+            """
+        )
+        tmp_cfg.close()
+        config.digest_file(tmp_cfg.name)
+
+        assert np.allclose(config.aspect_ratio, 1.0)
+        # if both are specified in the cfg file, the aspect ratio is ignored
+        assert np.allclose(config.frame_height, 10.0)
+        assert np.allclose(config.frame_width, 10.0)
+
+
 def test_temporary_dry_run():
     """Test that tempconfig correctly restores after setting dry_run."""
     assert config["write_to_movie"]