Python wrapper for OpenType Sanitizer, also known as just "OTS". It is similar to and partially based on ots-python, but builds OTS as a Python C Extension (instead of as an executable and calling through subprocess
as ots-python does).
NOTE: Although this package is similar to ots-python, it is not a drop-in replacement for it, as the Python API is different.
The project builds pip
-installable wheels for Python 3.9, 3.10, 3.11, or 3.12 under Mac or Linux. It is possible this project will build and run with other Pythons and other operating systems, but it has only been tested with the listed configurations.
If you just want to use pyots
, you can simply run python -m pip install -U pyots
(in one of the supported platforms/Python versions) which will install pre-built, compiled, ready-to-use Python wheels. Then you can skip down to the Use section.
If you'd like to tinker with the pyots
code, you will want to get your local setup ready:
- clone this repo
- run
python setup.py download
to download the OTS source (which is not included in this project). You can modify theversion
value insetup.cfg
under[download]
to specify a different version of OTS. You'll also need to change thesha256
hash value that corresponds to the OTS tar.xz package. Note that this scheme has some limitations: OTS sources older than 8.1.3 might not build correctly since they used different build systems. Also, versions newer than the one specified in this repo might require adjustments in order to build correctly. What can we say, we're dependent onots
... - to build and install
pyots
after downloading OTS, you can runpython setup.py install
orpython -m pip install .
- while iterating changes, you will want to delete the temporary
build
andsrc/ots/build
folders.
There is a test suite defined for exercising the Python extension. It makes use (and assumes the presence of) the downloaded OTS library source's test font data in src/ots
so ensure you have run python setup.py download
and have the ots
folder under src
. Invoke the tests with python -m pytest
.
If you wish to run tests comparing results from ots-python
against pyots
, be sure to python -m pip install opentype-sanitizer
first, otherwise that set of tests will be skipped.
Simplest case:
import pyots
result = pyots.sanitize('/path/to/font/file.ttf')
result
is an OTSResult
object with 3 attributes:
sanitized
Boolean indicating whether the file was successfully sanitizedmodified
Boolean indicating whether the file was modified* during sanitizationmessages
Tuple of message strings generated during sanitization (may be empty)
- Note: currently the back-end OTS code can modify fonts that are successfully sanitized, even when no changes are performed. Thus
modified
can sometimes be True whensanitized
is True. Usually the modification is only to the modification date and related checksums. Thus, it might be possible to devise a better detection of modification, i.e. ignoringhead.modified
and other inconsequential modifications, but that was out-of-scope for this work.
# sanitize a folder of fonts. Print messages for any that were not successfully sanitized.
import pyots
from pathlib import Path
for filename in Path("src/ots/tests/fonts/good").rglob("*"):
result = pyots.sanitize(filename.absolute())
if not result.sanitized:
print(f'{filename}:\n{", ".join([m for m in result.messages])}')
- Specify keyword
output=<path_to_output_file>
to thesanitize()
command and the sanitized file will be saved to that location - Use
quiet=True
forsanitize()
to suppress messages - Specify
font_index=<index_in_TTC>
when sanitizing a Collection (OTC/TTC) file and you want to sanitize only a particular index within the Collection (otherwise all will be sanitized per OTS's default behavior)