Skip to content

Commit 3a8b144

Browse files
committed
Create GitHub Actions workflow for wheels and PyPI
1 parent b313d10 commit 3a8b144

File tree

5 files changed

+167
-9
lines changed

5 files changed

+167
-9
lines changed

.github/workflows/pypi.yml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
name: Repository Dispatch
2+
on:
3+
repository_dispatch:
4+
types: [pypi-upload]
5+
jobs:
6+
deploy:
7+
runs-on: ubuntu-latest
8+
steps:
9+
- uses: actions/checkout@v2
10+
with:
11+
ref: ${{ github.event.client_payload.ref }}
12+
- run: echo ${{ github.event.client_payload.sha }}
13+
- name: Set up Python
14+
uses: actions/setup-python@v1
15+
with:
16+
python-version: 3.8
17+
- name: Sleep to wait for CI to comlete
18+
run: |
19+
sleep 600
20+
- name: Installl script dependencies
21+
run: |
22+
python -m pip install scikit-build
23+
- name: Fetch the wheels from the release
24+
run: |
25+
curl -s https://api.github.com/repos/TkinterEP/python-tkextrafont/releases/latest | grep "browser_download_url.*whl" | cut -d : -f 2,3 | tr -d \" | wget -qi - -P dist/
26+
- name: Build a source distribution
27+
run: |
28+
python setup.py sdist
29+
- name: Check Tag
30+
id: check-tag
31+
run: |
32+
if [[ ${{ github.event.client_payload.ref }} =~ ^refs/tags/v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
33+
echo ::set-output name=match::true
34+
fi
35+
- name: Upload to PyPI
36+
if: steps.check-tag.outputs.match == 'true'
37+
uses: pypa/gh-action-pypi-publish@release/v1
38+
with:
39+
user: __token__
40+
password: ${{ secrets.PYPI_API_TOKEN }}
41+
- name: Upload to TEST PyPI
42+
uses: pypa/gh-action-pypi-publish@release/v1
43+
with:
44+
user: __token__
45+
password: ${{ secrets.TEST_PYPI_API_TOKEN }}
46+
repository_url: https://test.pypi.org/legacy/

.github/workflows/wheels.yml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: Python package build and publish
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*'
7+
8+
jobs:
9+
deploy:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v2
13+
- name: Set up Python
14+
uses: actions/setup-python@v1
15+
with:
16+
python-version: 3.8
17+
- name: Build manylinux Python wheels
18+
uses: RalfG/[email protected]_x86_64
19+
with:
20+
python-versions: 'cp36-cp36m cp37-cp37m cp38-cp38 cp39-cp39'
21+
build-requirements: 'scikit-build'
22+
system-packages: 'python3-tkinter fontconfig-devel fontconfig cmake gcc gcc-c++ make pkgconfig tcl tcl-devel tk tk-devel'
23+
package-path: '.'
24+
- name: Update wheel ownership
25+
run: |
26+
sudo chown $USER:$USER dist/*
27+
- name: Post-process manylinux wheels
28+
run: |
29+
sudo python ci/post_process_manylinux.py
30+
- name: Create Release
31+
uses: ncipollo/release-action@v1
32+
with:
33+
allowUpdates: true
34+
omitBody: true
35+
token: ${{ secrets.DEPLOY_TOKEN }}
36+
- name: Upload binaries to release
37+
uses: svenstaro/upload-release-action@v2
38+
with:
39+
repo_token: ${{ secrets.DEPLOY_TOKEN }}
40+
file: dist/*-manylinux*.whl
41+
tag: ${{ github.ref }}
42+
overwrite: true
43+
file_glob: true
44+
- name: PyPI Dispatch
45+
uses: peter-evans/repository-dispatch@v1
46+
with:
47+
token: ${{ secrets.DEPLOY_TOKEN }}
48+
repository: TkinterEP/python-tkextrafont
49+
event-type: pypi-upload
50+
client-payload: '{"ref": "${{ github.ref }}", "sha": "${{ github.sha }}"}'

.travis.yml

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,3 @@ script:
2525
- python setup.py install
2626
- rm -rf ./tkextrafont
2727
- python -m nose
28-
deploy:
29-
provider: releases
30-
token:
31-
secure: "qEbnTsfDAGXokVlBPGwzkTg/DjnPOnM9UnQonZohRTcxyVE/RWNgBfQYbK6ihfJvn9fbD+1rKNjXNia/oRRoA6YGyUpOkX7EtdlJ9rvEo9gZqwfmiM/h8n1l4TP5Igu3whh5EEPtUNt9sj09hmaBStJSdqO0lehPW1xEUs6nwpjzNF1ucyCuoivilvvoMk6jcyUSRz67b301Kd7j68rAmSj3Py7dvzCJM2FNIoxezSkw3RyJFCJvYcJdjSfYHoHZ5MStDCgAV3nHwFnwiYzZ46jvSiHsma3SplaeWrhs8ota/uI1dnxxNhBPzR3L3xwHLzMR53TMWUfE8HzTPedBnsMAkDEvJuGRGKclUt3VpbOBELEhR7j3ERbxL48pnDPOSv2xtMAVVsIh+X04X8lsimCfGnSMdZYfCXXrSVpdX0r/cmMY3rtaugVjZECjQ4RMT8WIimrg92el9KfH+tCGVFT5/y3s8x3gC3qDrKq2AGY3e7xxA6HzZn18MA+UBl68Z+JGsItyTSwcnOeCR/9xgGn0U+Iqjn3AO2aJmkSw7rHi2yflLucsknChq4I5UbkAtjs0dchpsOGkbRCgTiC2GR3eL8LIqBrsr1GWrr2B0eadIwlpq4gdpvX/ssoYZDwZ3pvw8QQUJM6KbhrKHFq1OApoupUwCmd/rGVgh/xdME4="
32-
file: dist/*.whl
33-
edge: true
34-
on:
35-
tags: true

ci/post_process_manylinux.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
"""
2+
Author: RedFantom
3+
License: GNU GPLv3
4+
Copyright (c) 2021 RedFantom
5+
6+
Modify generated wheels such that they load the sytem-version of the
7+
libfontconfig binary rather than the manylinux provided one.
8+
"""
9+
import shutil
10+
from typing import Any, List, Optional
11+
import os
12+
import zipfile # Wheels are actually zip files
13+
14+
LIB = b"libfontconfig.so.1"
15+
16+
17+
def get_whl_files() -> List[str]:
18+
return list(map(lambda s: os.path.join("dist", s), filter(lambda s: s.endswith(".whl"), os.listdir("dist"))))
19+
20+
21+
def printf(string, **kwargs):
22+
kwargs.update({"end": "", "flush": True})
23+
print(string, **kwargs)
24+
25+
26+
def first(lst: List[Any]) -> Optional[Any]:
27+
return lst[0] if len(lst) > 0 else None
28+
29+
30+
for whl in get_whl_files():
31+
# Step one: Open the wheel as a zip file
32+
printf(f"Processing {whl}...")
33+
source = zipfile.ZipFile(whl)
34+
target = zipfile.ZipFile(os.path.basename(whl), "w")
35+
printf(".")
36+
37+
# Step two: Find the fontconfig file
38+
members: List[str] = source.namelist()
39+
wo_fontconfig = [member for member in members if "libfontconfig" not in member]
40+
fontconfig = first(list(set(members) - set(wo_fontconfig)))
41+
if fontconfig is None:
42+
printf("notfound\n")
43+
continue
44+
fontconfig = os.path.basename(fontconfig)
45+
printf(fontconfig)
46+
printf(".")
47+
fontconfig = fontconfig.encode()
48+
49+
# Step three: Copy the modified contents to the target wheel file
50+
for member in wo_fontconfig:
51+
buffer: bytes = source.read(member)
52+
if "extrafont.so" in member: # We found our compiled binary!
53+
# Step four: Modify extrafont.so to no longer load the old fontconfig
54+
printf(buffer.index(fontconfig))
55+
buffer = buffer.replace(fontconfig, LIB + b"\x00" * (len(fontconfig) - len(LIB)))
56+
57+
# Step five: Write the new zipfile
58+
target.writestr(member, buffer)
59+
source.close()
60+
target.close()
61+
62+
# Step six: Replace the original wheel file with the new file
63+
os.remove(whl)
64+
shutil.copyfile(os.path.basename(whl), whl)
65+
os.remove(os.path.basename(whl))
66+
printf(" Done.\n")

tkextrafont/__init__.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,5 +114,9 @@ def load(window: tk.Tk):
114114
local = os.path.abspath(os.path.dirname(__file__))
115115
with chdir(local):
116116
window.tk.eval("source pkgIndex.tcl")
117-
window.tk.eval("package require extrafont")
117+
try:
118+
window.tk.eval("package require extrafont")
119+
except tk.TclError as e:
120+
if "libfontconfig" in e.message:
121+
raise tk.TclError("Could not load extrafont due to missing fontconfig - See issue #1 on GitHub: <https://github.com/TkinterEP/python-tkextrafont/issues/1>")
118122
window._tkextrafont_loaded = True

0 commit comments

Comments
 (0)