Ejemplo n.º 1
0
#!python3
import manimlib

if __name__ == "__main__":
    manimlib.main()
Ejemplo n.º 2
0
    def manim(self, line, cell):
        # execute the code - won't generate any video, however it will introduce
        # the variables into the notebook's namespace (enabling autocompletion etc);
        # this also allows users to get feedback on some code errors early on
        get_ipython().ex(cell)

        user_args = line.split(' ')

        # path of the output video
        path = None

        settings = self.defaults.copy()

        # disable the switches as indicated by the user
        for key, arg in self.magic_off_switches.items():
            if '--' + key in user_args:
                user_args.remove('--' + key)
                settings[arg] = False

        resolution_index = (user_args.index('--resolution')
                            if '--resolution' in user_args else None)
        if resolution_index is not None:
            # the resolution is passed as "height,width"
            try:
                h, w = user_args[resolution_index + 1].split(',')
                settings['height'] = h
                settings['width'] = w
            except (IndexError, KeyError):
                warn(
                    'Unable to retrieve dimensions from your resolution setting, falling back to the defaults'
                )

        remote_index = (
            user_args.index('-b') if '-b' in user_args else
            user_args.index('--base64') if '--base64' in user_args else None)
        if remote_index is not None:
            settings['remote'] = True
            if '-b' in user_args:
                user_args.remove('-b')
            if '--base64' in user_args:
                user_args.remove('--base64')

        silent = settings['silent']

        def catch_path_and_forward(lines):
            nonlocal path
            for line in lines.split('\n'):
                if not silent:
                    print(line, file=std_out)

                if line.startswith(self.path_line_start):
                    path = line[len(self.path_line_start):].strip()

        # Using a workaround for Windows permissions issue as in this questions:
        # https://stackoverflow.com/q/15169101
        f = NamedTemporaryFile('w', suffix='.py', delete=False)
        try:

            with ExitStack() as stack:

                enter = stack.enter_context

                if settings['export_variables']:
                    # TODO test this with pytest
                    pickle_path = enter(self.export_globals())

                    if pickle_path:
                        unpickle_script = UNPICKLE_SCRIPT.format(
                            pickle_path=pickle_path)
                        cell = unpickle_script + cell

                f.write(cell)
                f.close()

                args = ['manim', f.name, *user_args]

                stdout = StringIOWithCallback(catch_path_and_forward)

                enter(patch.object(sys, 'argv', args))
                enter(suppress(SystemExit))
                enter(redirect_stdout(stdout))

                if silent:
                    stderr = StringIO()
                    enter(redirect_stderr(stderr))

                manimlib.main()
        finally:
            os.remove(f.name)

        if path:
            path = Path(path)
            assert path.exists()

            # To display a video in Jupyter, we need to have access to it
            # so it has to be within the working tree. The absolute paths
            # are usually outside of the accessible range.
            relative_path = path.relative_to(Path.cwd())

            video_settings = {
                k: v
                for k, v in settings.items() if k in self.video_settings
            }
            # If in remote mode, we send with a data: url
            if settings['remote']:
                data = base64.b64encode(path.read_bytes()).decode()
                data_url = "data:video/mp4;base64," + data
                return video(data_url, **video_settings)
            # otherwise a relative path is fine
            else:
                return video(relative_path, **video_settings)
        else:
            just_show_help = '-h' in user_args or '--help' in user_args

            if not just_show_help:
                warn('Could not find path in the manim output')

            # If we were silent, some errors could have been silenced too.
            if silent:
                # Let's break the silence:
                print(stdout.getvalue())
                print(stderr.getvalue(), file=sys.stderr)
Ejemplo n.º 3
0
    def manim(self, line, cell):
        # execute the code - won't generate any video, however it will introduce
        # the variables into the notebook's namespace (enabling autocompletion etc);
        # this also allows users to get feedback on some code errors early on
        get_ipython().ex(cell)

        # path of the output video
        path = None

        settings, user_args = self.parse_arguments(line)

        silent = settings['silent']

        def catch_path_and_forward(lines):
            nonlocal path
            for line in lines.split('\n'):
                if not silent:
                    print(line, file=std_out)

                if line.startswith(self.path_line_start):
                    path = line[len(self.path_line_start):].strip()

        # Using a workaround for Windows permissions issue as in this questions:
        # https://stackoverflow.com/q/15169101
        f = NamedTemporaryFile('w', suffix='.py', delete=False)
        try:

            with ExitStack() as stack:

                enter = stack.enter_context

                if settings['export_variables']:
                    pickle_path = enter(self.export_globals())

                    if pickle_path:
                        unpickle_script = UNPICKLE_SCRIPT.format(pickle_path=pickle_path)
                        cell = unpickle_script + cell

                    try:
                        cell = self.extract_imports() + '\n' + cell
                    except Exception as e:
                        warn('Assembling imports failed: ' + str(e))

                f.write(cell)
                f.close()

                args = ['manim', f.name, *user_args]

                stdout = StringIOWithCallback(catch_path_and_forward)

                enter(patch.object(sys, 'argv', args))
                enter(suppress(SystemExit))
                enter(redirect_stdout(stdout))

                if silent:
                    stderr = StringIO()
                    enter(redirect_stderr(stderr))

                manimlib.main()
        finally:
            os.remove(f.name)

        if path:
            path = Path(path)
            assert path.exists()

            # To display a video in Jupyter, we need to have access to it
            # so it has to be within the working tree. The absolute paths
            # are usually outside of the accessible range.
            relative_path = path.relative_to(Path.cwd())

            video_settings = {
                k: v
                for k, v in settings.items()
                if k in self.video_settings
            }

            display_method = gif if settings['is_gif'] else video
            file_type = 'image/gif' if settings['is_gif'] else 'video/mp4'

            if settings['remote']:
                data = base64.b64encode(path.read_bytes()).decode()
                to_display = 'data:' + file_type + ';base64,' + data
            else:
                to_display = relative_path

            return display_method(to_display, **video_settings)
        else:
            just_show_help = '-h' in user_args or '--help' in user_args

            if not just_show_help:
                warn('Could not find path in the manim output')

            # If we were silent, some errors could have been silenced too.
            if silent:
                # Let's break the silence:
                print(stdout.getvalue())
                print(stderr.getvalue(), file=sys.stderr)
Ejemplo n.º 4
0
#!/usr/bin/env python
import manimlib

if __name__ == "__main__":
    manimlib.main()
else:
    manimlib.stream_starter.start_livestream()