Skip to content

Commit

Permalink
Merge pull request #23 from ManimCommunity/refactor-setup
Browse files Browse the repository at this point in the history
Refactor setup.py
  • Loading branch information
naveen521kk authored Feb 11, 2021
2 parents d7b6bb6 + 5732df1 commit 00d91fb
Show file tree
Hide file tree
Showing 9 changed files with 202 additions and 58 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,8 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: dist/manimpango-${{ steps.create_release.outputs.tag_name }}.tar.gz
asset_name: manimpango-${{ steps.create_release.outputs.tag_name }}.tar.gz
asset_path: dist/ManimPango-${{ steps.create_release.outputs.tag_name }}.tar.gz
asset_name: ManimPango-${{ steps.create_release.outputs.tag_name }}.tar.gz
asset_content_type: application/gzip
test_wheels_linux: # TODO: Check for i386 builds also
needs: [build_wheels]
Expand Down
5 changes: 2 additions & 3 deletions docs/RELEASE.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ This means older version would have a backport of bugs fixes.

4. Clone the repository locally.

5. Bump the version in `setup.py`_ and `conf.py`_ accordingly.
5. Bump the version in `manimpango/_version`_ accordingly.

6. Make a commit with the changes done, as ``Release v<version here>``

Expand Down Expand Up @@ -46,8 +46,7 @@ This means older version would have a backport of bugs fixes.
it in a new virtual environment.

.. _Wheels Build: https://github.com/ManimCommunity/ManimPango/actions?query=workflow%3A%22Build+Wheels%22
.. _setup.py: https://github.com/ManimCommunity/ManimPango/blob/main/setup.py
.. _conf.py: https://github.com/ManimCommunity/ManimPango/blob/main/docs/conf.py
.. _manimpango/_version: https://github.com/ManimCommunity/ManimPango/blob/main/manimpango/_version.py
.. _Github: https://github.com
.. _draft a new release: https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/managing-releases-in-a-repository#creating-a-release
.. _PyPi: https://pypi.org/project/manimpango/
Binary file added docs/_static/favicon.ico
Binary file not shown.
8 changes: 6 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,17 @@
# sys.path.insert(0, os.path.abspath(".."))


from pathlib import Path

# -- Project information -----------------------------------------------------
from pkg_resources import get_distribution

project = "ManimPango"
copyright = "2021, The Manim Community Dev Team"
author = "The Manim Community Dev Team"

# The full version, including alpha/beta/rc tags
release = "v0.2.0"
release = get_distribution("ManimPango").version
version = ".".join(release.split(".")[:2])


# -- General configuration ---------------------------------------------------
Expand Down Expand Up @@ -61,6 +64,7 @@
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ["_static"]
html_favicon = str(Path("_static/favicon.ico"))
autosummary_generate = True

# generate documentation from type hints
Expand Down
2 changes: 2 additions & 0 deletions manimpango/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# -*- coding: utf-8 -*-
import os

from ._version import __version__ # noqa: F403,F401

if os.name == "nt":
os.environ["PATH"] = (
f"{os.path.abspath(os.path.dirname(__file__))}"
Expand Down
2 changes: 2 additions & 0 deletions manimpango/_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# -*- coding: utf-8 -*-
__version__ = "0.2.0"
5 changes: 3 additions & 2 deletions manimpango/cmanimpango.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -269,8 +269,9 @@ def text2svg(
class MarkupUtils:
@staticmethod
def validate(text: str) -> bool:
text_bytes = text.encode("utf-8")
return pango_parse_markup(text_bytes, <int>len(text_bytes), 0, NULL, NULL, NULL, NULL)
length = len(text)
text_bytes = text.encode("utf-8")
return pango_parse_markup(text_bytes, <int>length, 0, NULL, NULL, NULL, NULL)

@staticmethod
def text2svg(
Expand Down
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[build-system]
requires = ["setuptools", "wheel","Cython>=0.27"]
232 changes: 183 additions & 49 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,76 +1,203 @@
# -*- coding: utf-8 -*-

import argparse
import os
import shlex
import subprocess
import sys
import warnings
from pathlib import Path
from shlex import quote
from subprocess import PIPE, Popen
from subprocess import PIPE, Popen, check_call

from setuptools import Extension, setup

try:
from Cython.Build import cythonize

USE_CYTHON = True
except ImportError:
USE_CYTHON = False
from setuptools import Extension, setup

_cflag_parser = argparse.ArgumentParser(add_help=False)
_cflag_parser.add_argument("-I", dest="include_dirs", action="append")
_cflag_parser.add_argument("-L", dest="library_dirs", action="append")
_cflag_parser.add_argument("-l", dest="libraries", action="append")
_cflag_parser.add_argument("-D", dest="define_macros", action="append")
_cflag_parser.add_argument("-R", dest="runtime_library_dirs", action="append")

def get_version():
version_file = "manimpango/_version.py"
with open(version_file) as f:
exec(compile(f.read(), version_file, "exec"))
return locals()["__version__"]

def parse_cflags(raw_cflags):
raw_args = shlex.split(raw_cflags.strip())
args, unknown = _cflag_parser.parse_known_args(raw_args)
config = {k: v or [] for k, v in args.__dict__.items()}
for i, x in enumerate(config["define_macros"]):
parts = x.split("=", 1)
value = x[1] or None if len(x) == 2 else None
config["define_macros"][i] = (parts[0], value)
return config, " ".join(quote(x) for x in unknown)

NAME = "ManimPango"
MANIMPANGO_VERSION = get_version()
MINIMUM_PANGO_VERSION = "1.30.0"
DEBUG = False

def get_library_config(name):
"""Get distutils-compatible extension extras for the given library.
This requires ``pkg-config``.
"""
try:
proc = Popen(
["pkg-config", "--cflags", "--libs", name],
stdout=PIPE,
stderr=PIPE,
if sys.platform == "win32" and sys.version_info >= (3, 10):
import atexit

atexit.register(
lambda: warnings.warn(
f"ManimPango {MANIMPANGO_VERSION} does not support Python "
f"{sys.version_info.major}.{sys.version_info.minor} and does not provide "
"prebuilt Windows binaries. We do not recommend building from source on "
"Windows.",
RuntimeWarning,
)
except OSError:
print("pkg-config is required for building manimpango")
exit(1)

raw_cflags, _ = proc.communicate()
known, unknown = parse_cflags(raw_cflags.decode("utf8"))
if unknown:
print(
"pkg-config returned flags we \
don't understand: {}".format(
unknown
)


class RequiredDependencyException(Exception):
pass


NEEDED_LIBS = [
"pangocairo-1.0",
"pango-1.0",
"gobject-2.0",
"glib-2.0",
"intl",
"harfbuzz",
"cairo",
]


class PKG_CONFIG:
"""Preform operations with pkg-config.
Parameters
==========
libname : :class:`str`
The library name to query.
"""

def __init__(self, libname: str) -> None:
self.name = libname
self.pkg_config = os.environ.get("PKG_CONFIG", "pkg-config")
self.setup_argparse()
self.check_pkgconfig = self.check_pkgconfig()

def check_pkgconfig(self):
"""Check whether pkg-config works.
If it doesn't work raise a warning.
"""
try:
check_call([self.pkg_config, "--version"], stdout=subprocess.DEVNULL)
return True
except Exception:
warnings.warn(
f"{self.pkg_config} doesn't exists or doesn't seem to work"
"We assume that you give the compiler flags using"
"corresponding environment variables.",
RuntimeWarning,
)
)
return known
return False

def parse_cflags(self, raw_cflags):
"""Parse the flags from pkg-config using argparse."""
raw_args = shlex.split(raw_cflags.strip())
args, unknown = self._cflag_parser.parse_known_args(raw_args)
config = {k: v or [] for k, v in args.__dict__.items()}
for i, x in enumerate(config["define_macros"]):
parts = x.split("=", 1)
value = x[1] or None if len(x) == 2 else None
config["define_macros"][i] = (parts[0], value)
return config, " ".join(quote(x) for x in unknown)

def setup_argparse(self):
_cflag_parser = argparse.ArgumentParser(add_help=False)
_cflag_parser.add_argument("-I", dest="include_dirs", action="append")
_cflag_parser.add_argument("-L", dest="library_dirs", action="append")
_cflag_parser.add_argument("-l", dest="libraries", action="append")
_cflag_parser.add_argument("-D", dest="define_macros", action="append")
_cflag_parser.add_argument("-R", dest="runtime_library_dirs", action="append")
self._cflag_parser = _cflag_parser

def check_min_version(self, version):
"""Check whether the library of that version exists."""
command = [
self.pkg_config,
"--print-errors",
"--atleast-version",
version,
self.name,
]
try:
check_call(command, stdout=subprocess.DEVNULL)
return True
except Exception:
raise RequiredDependencyException("{self.name} >= {version} is required")

def update_dict(dict1, dict2):
for key in dict2:
dict2[key] = list(set(dict1[key] + dict2[key]))
@property
def libs(self):
"""Get distutils-compatible extension extras for the given library.
This requires ``pkg-config``.
"""
if self.check_pkgconfig:
name = self.name
command = self.pkg_config
try:
proc = Popen(
[command, "--libs", name],
stdout=PIPE,
stderr=PIPE,
)
except Exception:
pass
raw_libs, _ = proc.communicate()
known_libs, unknown_libs = self.parse_cflags(raw_libs.decode("utf8"))
if unknown_libs:
known_libs["extra_link_args"] = unknown_libs.split()
return known_libs
return dict()

@property
def cflags(self):
if self.check_pkgconfig:
name = self.name
command = self.pkg_config
try:
proc = Popen(
[command, "--cflags", name],
stdout=PIPE,
stderr=PIPE,
)
except Exception:
pass
raw_cflags, _ = proc.communicate()
known_cflags, unknown_cflags = self.parse_cflags(raw_cflags.decode("utf8"))
if unknown_cflags:
known_cflags["extra_compile_args"] = unknown_cflags.split()
# return update_dict(known_cflags, known_libs)
return known_cflags
return dict()

@property
def setuptools_args(self):
return update_dict(self.libs, self.cflags)


def update_dict(dict1: dict, dict2: dict):
for key in dict1:
if key in dict2:
dict2[key] = dict1[key] + dict2[key]
else:
dict2[key] = dict1[key]
return dict2


ext = ".pyx" if USE_CYTHON else ".c"
base_file = Path(__file__).parent / "manimpango"
returns = get_library_config("pangocairo")
returns = update_dict(returns, get_library_config("pangofc"))
_pkg_config = PKG_CONFIG("pangocairo")
_pkg_config.check_min_version(MINIMUM_PANGO_VERSION)
returns = _pkg_config.setuptools_args
if not _pkg_config.check_pkgconfig:
returns["libraries"] = NEEDED_LIBS
if sys.platform == "win32":
returns["libraries"] += ["Gdi32"]
if hasattr(returns, "define_macros"):
returns["define_macros"] += [("UNICODE", 1)]
else:
returns["define_macros"] = [("UNICODE", 1)]

ext_modules = [
Extension(
"manimpango.cmanimpango",
Expand All @@ -83,16 +210,18 @@ def update_dict(dict1, dict2):
ext_modules,
language_level=3,
include_path=["manimpango"],
gdb_debug=DEBUG,
)
with open("README.md", "r") as fh:
with open("README.md") as fh:
long_description = fh.read()

setup(
name="manimpango",
version="0.2.0",
author="The Manim Community Developers",
name=NAME,
version=MANIMPANGO_VERSION,
author="Naveen M K",
author_email="[email protected]",
maintainer="The Manim Community Developers",
url="https://github.com/ManimCommunity/manimpango",
url="https://manimpango.manim.community/",
description="Bindings for Pango for using with Manim.",
long_description=long_description,
zip_safe=False,
Expand All @@ -113,6 +242,11 @@ def update_dict(dict1, dict2):
"Operating System :: OS Independent",
"Programming Language :: Cython",
],
project_urls={
"Documentation": "https://manimpango.manim.community/",
"Source": "https://github.com/ManimCommunity/manimpango",
"Release notes": "https://github.com/ManimCommunity/ManimPango/releases/",
},
ext_modules=ext_modules,
package_data={
"manimpango": ["*.pxd"],
Expand Down

0 comments on commit 00d91fb

Please sign in to comment.