Skip to content

Commit

Permalink
Merge branch 'main' into fix-2449-sound-timing-off
Browse files Browse the repository at this point in the history
  • Loading branch information
BarryLarry17Jr authored Oct 27, 2023
2 parents 2520195 + 5193e1c commit 1e51ee1
Show file tree
Hide file tree
Showing 234 changed files with 1,693 additions and 1,128 deletions.
209 changes: 209 additions & 0 deletions .github/scripts/ci_build_cairo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
# Logic is as follows:
# 1. Download cairo source code: https://cairographics.org/releases/cairo-<version>.tar.xz
# 2. Verify the downloaded file using the sha256sums file: https://cairographics.org/releases/cairo-<version>.tar.xz.sha256sum
# 3. Extract the downloaded file.
# 4. Create a virtual environment and install meson and ninja.
# 5. Run meson build in the extracted directory. Also, set required prefix.
# 6. Run meson compile -C build.
# 7. Run meson install -C build.

import hashlib
import logging
import os
import subprocess
import sys
import tarfile
import tempfile
import typing
import urllib.request
from contextlib import contextmanager
from pathlib import Path
from sys import stdout

CAIRO_VERSION = "1.18.0"
CAIRO_URL = f"https://cairographics.org/releases/cairo-{CAIRO_VERSION}.tar.xz"
CAIRO_SHA256_URL = f"{CAIRO_URL}.sha256sum"

VENV_NAME = "meson-venv"
BUILD_DIR = "build"
INSTALL_PREFIX = Path(__file__).parent.parent / "third_party" / "cairo"

logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")
logger = logging.getLogger(__name__)


def is_ci():
return os.getenv("CI", None) is not None


def download_file(url, path):
logger.info(f"Downloading {url} to {path}")
block_size = 1024 * 1024
with urllib.request.urlopen(url) as response, open(path, "wb") as file:
while True:
data = response.read(block_size)
if not data:
break
file.write(data)


def verify_sha256sum(path, sha256sum):
with open(path, "rb") as file:
file_hash = hashlib.sha256(file.read()).hexdigest()
if file_hash != sha256sum:
raise Exception("SHA256SUM does not match")


def extract_tar_xz(path, directory):
with tarfile.open(path) as file:
file.extractall(directory)


def run_command(command, cwd=None, env=None):
process = subprocess.Popen(command, cwd=cwd, env=env)
process.communicate()
if process.returncode != 0:
raise Exception("Command failed")


@contextmanager
def gha_group(title: str) -> typing.Generator:
if not is_ci():
yield
return
print(f"\n::group::{title}")
stdout.flush()
try:
yield
finally:
print("::endgroup::")
stdout.flush()


def set_env_var_gha(name: str, value: str) -> None:
if not is_ci():
return
env_file = os.getenv("GITHUB_ENV", None)
if env_file is None:
return
with open(env_file, "a") as file:
file.write(f"{name}={value}\n")
stdout.flush()


def get_ld_library_path(prefix: Path) -> str:
# given a prefix, the ld library path can be found at
# <prefix>/lib/* or sometimes just <prefix>/lib
# this function returns the path to the ld library path

# first, check if the ld library path exists at <prefix>/lib/*
ld_library_paths = list(prefix.glob("lib/*"))
if len(ld_library_paths) == 1:
return ld_library_paths[0].absolute().as_posix()

# if the ld library path does not exist at <prefix>/lib/*,
# return <prefix>/lib
ld_library_path = prefix / "lib"
if ld_library_path.exists():
return ld_library_path.absolute().as_posix()
return ""


def main():
if sys.platform == "win32":
logger.info("Skipping build on windows")
return

with tempfile.TemporaryDirectory() as tmpdir:
with gha_group("Downloading and Extracting Cairo"):
logger.info(f"Downloading cairo version {CAIRO_VERSION}")
download_file(CAIRO_URL, os.path.join(tmpdir, "cairo.tar.xz"))

logger.info("Downloading cairo sha256sum")
download_file(CAIRO_SHA256_URL, os.path.join(tmpdir, "cairo.sha256sum"))

logger.info("Verifying cairo sha256sum")
with open(os.path.join(tmpdir, "cairo.sha256sum")) as file:
sha256sum = file.read().split()[0]
verify_sha256sum(os.path.join(tmpdir, "cairo.tar.xz"), sha256sum)

logger.info("Extracting cairo")
extract_tar_xz(os.path.join(tmpdir, "cairo.tar.xz"), tmpdir)

with gha_group("Installing meson and ninja"):
logger.info("Creating virtual environment")
run_command([sys.executable, "-m", "venv", os.path.join(tmpdir, VENV_NAME)])

logger.info("Installing meson and ninja")
run_command(
[
os.path.join(tmpdir, VENV_NAME, "bin", "pip"),
"install",
"meson",
"ninja",
]
)

env_vars = {
# add the venv bin directory to PATH so that meson can find ninja
"PATH": f"{os.path.join(tmpdir, VENV_NAME, 'bin')}{os.pathsep}{os.environ['PATH']}",
}

with gha_group("Building and Installing Cairo"):
logger.info("Running meson setup")
run_command(
[
os.path.join(tmpdir, VENV_NAME, "bin", "meson"),
"setup",
BUILD_DIR,
f"--prefix={INSTALL_PREFIX.absolute().as_posix()}",
"--buildtype=release",
"-Dtests=disabled",
],
cwd=os.path.join(tmpdir, f"cairo-{CAIRO_VERSION}"),
env=env_vars,
)

logger.info("Running meson compile")
run_command(
[
os.path.join(tmpdir, VENV_NAME, "bin", "meson"),
"compile",
"-C",
BUILD_DIR,
],
cwd=os.path.join(tmpdir, f"cairo-{CAIRO_VERSION}"),
env=env_vars,
)

logger.info("Running meson install")
run_command(
[
os.path.join(tmpdir, VENV_NAME, "bin", "meson"),
"install",
"-C",
BUILD_DIR,
],
cwd=os.path.join(tmpdir, f"cairo-{CAIRO_VERSION}"),
env=env_vars,
)

logger.info(f"Successfully built cairo and installed it to {INSTALL_PREFIX}")


if __name__ == "__main__":
if "--set-env-vars" in sys.argv:
with gha_group("Setting environment variables"):
# append the pkgconfig directory to PKG_CONFIG_PATH
set_env_var_gha(
"PKG_CONFIG_PATH",
f"{Path(get_ld_library_path(INSTALL_PREFIX), 'pkgconfig').as_posix()}{os.pathsep}"
f'{os.getenv("PKG_CONFIG_PATH", "")}',
)
set_env_var_gha(
"LD_LIBRARY_PATH",
f"{get_ld_library_path(INSTALL_PREFIX)}{os.pathsep}"
f'{os.getenv("LD_LIBRARY_PATH", "")}',
)
sys.exit(0)
main()
20 changes: 16 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,22 @@ jobs:
# start xvfb in background
sudo /usr/bin/Xvfb $DISPLAY -screen 0 1280x1024x24 &
- name: Setup Cairo Cache
uses: actions/cache@v3
id: cache-cairo
if: runner.os == 'Linux' || runner.os == 'macOS'
with:
path: ${{ github.workspace }}/third_party
key: ${{ runner.os }}-dependencies-cairo-${{ hashFiles('.github/scripts/ci_build_cairo.py') }}

- name: Build and install Cairo (Linux and macOS)
if: (runner.os == 'Linux' || runner.os == 'macOS') && steps.cache-cairo.outputs.cache-hit != 'true'
run: python .github/scripts/ci_build_cairo.py

- name: Set env vars for Cairo (Linux and macOS)
if: runner.os == 'Linux' || runner.os == 'macOS'
run: python .github/scripts/ci_build_cairo.py --set-env-vars

- name: Setup macOS cache
uses: actions/cache@v3
id: cache-macos
Expand Down Expand Up @@ -103,10 +119,6 @@ jobs:
export PATH="$oriPath"
echo "Completed TinyTeX"
- name: Install cairo (MacOS)
if: runner.os == 'macOS'
run: brew install cairo

- name: Add macOS dependencies to PATH
if: runner.os == 'macOS'
shell: bash
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/python-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ jobs:
steps:
- uses: actions/checkout@v4

- name: Set up Python 3.8
- name: Set up Python 3.11
uses: actions/setup-python@v4
with:
python-version: 3.9
python-version: 3.11

- name: Install dependencies
run: python -m pip install --upgrade poetry
Expand Down
84 changes: 84 additions & 0 deletions .github/workflows/release-publish-documentation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
name: Publish downloadable documentation

on:
release:
types: [released]
workflow_dispatch:

jobs:
build-and-publish-htmldocs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Python 3.11
uses: actions/setup-python@v4
with:
python-version: 3.11

- name: Install system dependencies
run: |
sudo apt update && sudo apt install -y \
pkg-config libcairo-dev libpango1.0-dev ffmpeg wget fonts-roboto
wget -qO- "https://yihui.org/tinytex/install-bin-unix.sh" | sh
echo ${HOME}/.TinyTeX/bin/x86_64-linux >> $GITHUB_PATH
- name: Install LaTeX and Python dependencies
run: |
tlmgr install \
babel-english ctex doublestroke dvisvgm frcursive fundus-calligra jknapltx \
mathastext microtype physics preview ragged2e relsize rsfs setspace standalone \
wasy wasysym
python -m pip install --upgrade poetry
poetry install
- name: Build and package documentation
run: |
cd docs/
poetry run make html
cd build/html/
tar -czvf ../html-docs.tar.gz *
- name: Store artifacts
uses: actions/upload-artifact@v3
with:
path: ${{ github.workspace }}/manim/docs/build/html-docs.tar.gz
name: html-docs.tar.gz

- name: Install Dependency
run: pip install requests

- name: Get Upload URL
if: github.event == 'release'
id: create_release
shell: python
env:
access_token: ${{ secrets.GITHUB_TOKEN }}
tag_act: ${{ github.ref }}
run: |
import requests
import os
ref_tag = os.getenv('tag_act').split('/')[-1]
access_token = os.getenv('access_token')
headers = {
"Accept":"application/vnd.github.v3+json",
"Authorization": f"token {access_token}"
}
url = f"https://api.github.com/repos/ManimCommunity/manim/releases/tags/{ref_tag}"
c = requests.get(url,headers=headers)
upload_url=c.json()['upload_url']
with open(os.getenv('GITHUB_OUTPUT'), 'w') as f:
print(f"upload_url={upload_url}", file=f)
print(f"tag_name={ref_tag[1:]}", file=f)
- name: Upload Release Asset
if: github.event == 'release'
id: upload-release
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ${{ github.workspace }}/manim/docs/build/html-docs.tar.gz
asset_name: manim-htmldocs-${{ steps.create_release.outputs.tag_name }}.tar.gz
asset_content_type: application/gzip
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,6 @@ dist/

/media_dir.txt
# ^TODO: Remove the need for this with a proper config file

# Ignore the built dependencies
third_party/*
4 changes: 0 additions & 4 deletions .readthedocs.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
version: 2

formats:
- htmlzip

build:
os: ubuntu-22.04

Expand Down
2 changes: 2 additions & 0 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
except ModuleNotFoundError: # windows
pass

import cairo
import moderngl

# If it is running Doctest the current directory
Expand Down Expand Up @@ -39,6 +40,7 @@ def pytest_report_header(config):
info = ctx.info
ctx.release()
return (
f"\nCairo Version: {cairo.cairo_version()}",
"\nOpenGL information",
"------------------",
f"vendor: {info['GL_VENDOR'].strip()}",
Expand Down
5 changes: 5 additions & 0 deletions manim/animation/creation.py
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,11 @@ def __init__(
**kwargs,
) -> None:
self.time_per_char = time_per_char
# Check for empty text using family_members_with_points()
if not text.family_members_with_points():
raise ValueError(
f"The text mobject {text} does not seem to contain any characters."
)
if run_time is None:
# minimum time per character is 1/frame_rate, otherwise
# the animation does not finish.
Expand Down
Loading

0 comments on commit 1e51ee1

Please sign in to comment.