Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SVGMobject passing NoneType to svgelements #3949

Open
jpmikhail opened this issue Oct 6, 2024 · 0 comments
Open

SVGMobject passing NoneType to svgelements #3949

jpmikhail opened this issue Oct 6, 2024 · 0 comments

Comments

@jpmikhail
Copy link

Description of bug / unexpected behavior

When using an SVG plot with a legend (below), Manim passes a NoneType to svgelements. This results in an error:
TypeError: object of type 'NoneType' has no len()

When using an otherwise identical plot with no legend (below), there is no such error and Manim is able to parse the SVG image successfully.

I'm unsure if this is fundamentally an issue with Manim or svgelements.

Expected behavior

Both plots should be easily parsable without modifying svgelements.

How to reproduce the issue

Create the following simple scene with Manim using the two attached plots.

Code for reproducing the problem
class LoadSVGPlots(Scene):
    def construct(self):
        plot0 = SVGMobject('plot_without_legend.svg')
        print('loaded plot_without_legend')
        plot1 = SVGMobject('plot_with_legend.svg')
        print('loaded plot_with_legend')

Additional media files

Images/GIFs

plot_with_legend
plot_without_legend

Logs

Terminal output

After running the command: manim -qh -v DEBUG scene.py LoadSVGPlotsmanim -qh -v DEBUG scene.py LoadSVGPlots

Manim Community v0.18.1

loaded plot_without_legend
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ /home/mikhailj/Downloads/anaconda3/envs/my-manim-environment/lib/python3.10/site-packages/manim/ │
│ cli/render/commands.py:120 in render                                                             │
│                                                                                                  │
│   117 │   │   │   try:                                                                           │
│   118 │   │   │   │   with tempconfig({}):                                                       │
│   119 │   │   │   │   │   scene = SceneClass()                                                   │
│ ❱ 120 │   │   │   │   │   scene.render()                                                         │
│   121 │   │   │   except Exception:                                                              │
│   122 │   │   │   │   error_console.print_exception()                                            │
│   123 │   │   │   │   sys.exit(1)                                                                │
│                                                                                                  │
│ /home/mikhailj/Downloads/anaconda3/envs/my-manim-environment/lib/python3.10/site-packages/manim/ │
│ scene/scene.py:229 in render                                                                     │
│                                                                                                  │
│    226 │   │   """                                                                               │
│    227 │   │   self.setup()                                                                      │
│    228 │   │   try:                                                                              │
│ ❱  229 │   │   │   self.construct()                                                              │
│    230 │   │   except EndSceneEarlyException:                                                    │
│    231 │   │   │   pass                                                                          │
│    232 │   │   except RerunSceneException as e:                                                  │
│                                                                                                  │
│ /home/mikhailj/Videos/Manim/uniform_combination/scene.py:331 in construct                        │
│                                                                                                  │
│   328 │   def construct(self):                                                                   │
│   329 │   │   plot0 = SVGMobject('plot_without_legend.svg')                                      │
│   330 │   │   print('loaded plot_without_legend')                                                │
│ ❱ 331 │   │   plot1 = SVGMobject('plot_with_legend.svg')                                         │
│   332 │   │   print('loaded plot_with_legend')                                                   │
│   333                                                                                            │
│   334 #####################                                                                      │
│                                                                                                  │
│ /home/mikhailj/Downloads/anaconda3/envs/my-manim-environment/lib/python3.10/site-packages/manim/ │
│ mobject/svg/svg_mobject.py:145 in __init__                                                       │
│                                                                                                  │
│   142 │   │   │   path_string_config = {}                                                        │
│   143 │   │   self.path_string_config = path_string_config                                       │
│   144 │   │                                                                                      │
│ ❱ 145 │   │   self.init_svg_mobject(use_svg_cache=use_svg_cache)                                 │
│   146 │   │                                                                                      │
│   147 │   │   self.set_style(                                                                    │
│   148 │   │   │   fill_color=fill_color,                                                         │
│                                                                                                  │
│ /home/mikhailj/Downloads/anaconda3/envs/my-manim-environment/lib/python3.10/site-packages/manim/ │
│ mobject/svg/svg_mobject.py:171 in init_svg_mobject                                               │
│                                                                                                  │
│   168 │   │   │   │   self.add(*mob)                                                             │
│   169 │   │   │   │   return                                                                     │
│   170 │   │                                                                                      │
│ ❱ 171 │   │   self.generate_mobject()                                                            │
│   172 │   │   if use_svg_cache:                                                                  │
│   173 │   │   │   SVG_HASH_TO_MOB_MAP[hash_val] = self.copy()                                    │
│   174                                                                                            │
│                                                                                                  │
│ /home/mikhailj/Downloads/anaconda3/envs/my-manim-environment/lib/python3.10/site-packages/manim/ │
│ mobject/svg/svg_mobject.py:199 in generate_mobject                                               │
│                                                                                                  │
│   196 │   │   modified_file_path = file_path.with_name(f"{file_path.stem}_{file_path.suffix}")   │
│   197 │   │   new_tree.write(modified_file_path)                                                 │
│   198 │   │                                                                                      │
│ ❱ 199 │   │   svg = se.SVG.parse(modified_file_path)                                             │
│   200 │   │   modified_file_path.unlink()                                                        │
│   201 │   │                                                                                      │
│   202 │   │   mobjects = self.get_mobjects_from(svg)                                             │
│                                                                                                  │
│ /home/mikhailj/Downloads/anaconda3/envs/my-manim-environment/lib/python3.10/site-packages/svgele │
│ ments/svgelements.py:9236 in parse                                                               │
│                                                                                                  │
│   9233 │   │   │   │   │   │   if SVG_TAG_PATH == tag:                                           │
│   9234 │   │   │   │   │   │   │   # Delayed path parsing, for partial paths.                    │
│   9235 │   │   │   │   │   │   │   s = Path(values, pathd_loaded=True)                           │
│ ❱ 9236 │   │   │   │   │   │   │   s.parse(values.get(SVG_ATTR_DATA))                            │
│   9237 │   │   │   │   │   │   elif SVG_TAG_CIRCLE == tag:                                       │
│   9238 │   │   │   │   │   │   │   s = Circle(values)                                            │
│   9239 │   │   │   │   │   │   elif SVG_TAG_ELLIPSE == tag:                                      │
│                                                                                                  │
│ /home/mikhailj/Downloads/anaconda3/envs/my-manim-environment/lib/python3.10/site-packages/svgele │
│ ments/svgelements.py:5969 in parse                                                               │
│                                                                                                  │
│   5966 │   def parse(self, pathdef):                                                             │
│   5967 │   │   """Parses the SVG path."""                                                        │
│   5968 │   │   tokens = SVGLexicalParser()                                                       │
│ ❱ 5969 │   │   tokens.parse(self, pathdef)                                                       │
│   5970 │                                                                                         │
│   5971 │   def validate_connections(self):                                                       │
│   5972 │   │   """                                                                               │
│                                                                                                  │
│ /home/mikhailj/Downloads/anaconda3/envs/my-manim-environment/lib/python3.10/site-packages/svgele │
│ ments/svgelements.py:347 in parse                                                                │
│                                                                                                  │
│    344 │   │   self.parser.start()                                                               │
│    345 │   │   self.pathd = pathd                                                                │
│    346 │   │   self.pos = 0                                                                      │
│ ❱  347 │   │   self.limit = len(pathd)                                                           │
│    348 │   │   while True:                                                                       │
│    349 │   │   │   cmd = self._command()                                                         │
│    350 │   │   │   if cmd is None:                                                               │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
TypeError: object of type 'NoneType' has no len()

System specifications

System Details
  • OS (with version, e.g., Windows 10 v2004 or macOS 10.15 (Catalina)): Debian GNU/Linux 10 (buster)
  • RAM:
  • Python version (python/py/python3 --version): Python 3.10.14
  • Installed modules (provide output from pip list):
Package              Version
-------------------- -----------
Brotli               1.1.0
build                1.2.2
CacheControl         0.14.0
certifi              2024.8.30
cffi                 1.17.1
charset-normalizer   3.3.2
cleo                 2.1.0
click                8.1.7
click-default-group  1.2.4
cloup                3.0.5
colorama             0.4.6
crashtest            0.4.1
cryptography         43.0.1
decorator            5.1.1
distlib              0.3.8
dulwich              0.21.7
fastjsonschema       2.20.0
filelock             3.16.0
future               1.0.0
glcontext            3.0.0
h2                   4.1.0
hpack                4.0.0
hyperframe           6.0.1
idna                 3.10
importlib_metadata   8.5.0
installer            0.7.0
isosurfaces          0.1.2
jaraco.classes       3.4.0
jeepney              0.8.0
keyring              24.3.1
manim                0.18.1
ManimPango           0.6.0
mapbox_earcut        1.0.1
markdown-it-py       3.0.0
mdurl                0.1.2
moderngl             5.10.0
moderngl-window      2.4.1
more-itertools       10.5.0
msgpack              1.1.0
multipledispatch     0.6.0
networkx             3.3
numpy                1.26.4
packaging            24.1
pexpect              4.9.0
pillow               10.4.0
pip                  24.2
pkginfo              1.11.1
platformdirs         4.3.3
poetry               1.8.3
poetry-core          1.9.0
poetry-plugin-export 1.8.0
ptyprocess           0.7.0
pycairo              1.27.0
pycparser            2.22
pydub                0.25.1
pyglet               1.5.16
Pygments             2.18.0
pyproject_hooks      1.1.0
pyrr                 0.10.3
PySocks              1.7.1
PyYAML               6.0.2
rapidfuzz            3.9.7
requests             2.32.3
requests-toolbelt    1.0.0
rich                 13.8.1
scipy                1.14.1
screeninfo           0.8.1
SecretStorage        3.3.3
setuptools           73.0.1
shellingham          1.5.4
six                  1.16.0
skia-pathops         0.8.0.post1
srt                  3.5.3
svg.path             6.3
svgelements          1.9.6
tomli                2.0.1
tomlkit              0.13.2
tqdm                 4.66.5
trove-classifiers    2024.9.12
typing_extensions    4.12.2
urllib3              2.2.3
virtualenv           20.26.4
watchdog             5.0.2
wheel                0.44.0
zipp                 3.20.2
zstandard            0.23.0
LaTeX details
  • LaTeX distribution (e.g. TeX Live 2020):
  • Installed LaTeX packages:

Additional comments

I was able to avoid the error by modifying svgelements/svgelements.py class SVGLexicalParser method parse. I replaced

    def parse(self, parser, pathd):
        self.parser = parser
        self.parser.start()
        self.pathd = pathd
        self.pos = 0
        self.limit = len(pathd)
        # the rest of the method

with

    def parse(self, parser, pathd):
        self.parser = parser
        self.parser.start()
        self.pathd = pathd
        self.pos = 0
        if pathd is not None:
            self.limit = len(pathd)
        else:
            self.limit = 0
        # the rest of the method
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: 🆕 New
Development

No branches or pull requests

1 participant