Skip to content

Commit

Permalink
python: add type hints
Browse files Browse the repository at this point in the history
  • Loading branch information
MaxKellermann committed Sep 26, 2023
1 parent dd89ea4 commit 3f2016e
Show file tree
Hide file tree
Showing 9 changed files with 68 additions and 54 deletions.
20 changes: 11 additions & 9 deletions python/build/autotools.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import os.path, subprocess, sys
from typing import Collection, Iterable, Optional

from build.makeproject import MakeProject

class AutotoolsProject(MakeProject):
def __init__(self, url, md5, installed, configure_args=[],
autogen=False,
autoreconf=False,
cppflags='',
ldflags='',
libs='',
subdirs=None,
def __init__(self, url: str, md5: str, installed: str,
configure_args: Iterable[str]=[],
autogen: bool=False,
autoreconf: bool=False,
cppflags: str='',
ldflags: str='',
libs: str='',
subdirs: Optional[Collection[str]]=None,
**kwargs):
MakeProject.__init__(self, url, md5, installed, **kwargs)
self.configure_args = configure_args
Expand All @@ -20,7 +22,7 @@ def __init__(self, url, md5, installed, configure_args=[],
self.libs = libs
self.subdirs = subdirs

def configure(self, toolchain):
def configure(self, toolchain) -> str:
src = self.unpack(toolchain)
if self.autogen:
if sys.platform == 'darwin':
Expand Down Expand Up @@ -68,7 +70,7 @@ def configure(self, toolchain):

return build

def _build(self, toolchain):
def _build(self, toolchain) -> None:
build = self.configure(toolchain)
if self.subdirs is not None:
for subdir in self.subdirs:
Expand Down
19 changes: 11 additions & 8 deletions python/build/cmake.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import os
import re
import subprocess
from typing import Optional, TextIO
from collections.abc import Mapping

from build.project import Project

def __write_cmake_compiler(f, language, compiler):
def __write_cmake_compiler(f: TextIO, language: str, compiler: str) -> None:
s = compiler.split(' ', 1)
if len(s) == 2:
print(f'set(CMAKE_{language}_COMPILER_LAUNCHER {s[0]})', file=f)
compiler = s[1]
print(f'set(CMAKE_{language}_COMPILER {compiler})', file=f)

def __write_cmake_toolchain_file(f, toolchain):
def __write_cmake_toolchain_file(f: TextIO, toolchain) -> None:
if '-darwin' in toolchain.actual_arch:
cmake_system_name = 'Darwin'
elif toolchain.is_windows:
Expand Down Expand Up @@ -52,7 +54,7 @@ def __write_cmake_toolchain_file(f, toolchain):
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
""")

def configure(toolchain, src, build, args=(), env=None):
def configure(toolchain, src: str, build: str, args: list[str]=[], env: Optional[Mapping[str, str]]=None) -> None:
cross_args = []

if toolchain.is_windows:
Expand Down Expand Up @@ -91,16 +93,17 @@ def configure(toolchain, src, build, args=(), env=None):
subprocess.check_call(configure, env=env, cwd=build)

class CmakeProject(Project):
def __init__(self, url, md5, installed, configure_args=[],
windows_configure_args=[],
env=None,
def __init__(self, url: str, md5: str, installed: str,
configure_args: list[str]=[],
windows_configure_args: list[str]=[],
env: Optional[Mapping[str, str]]=None,
**kwargs):
Project.__init__(self, url, md5, installed, **kwargs)
self.configure_args = configure_args
self.windows_configure_args = windows_configure_args
self.env = env

def configure(self, toolchain):
def configure(self, toolchain) -> str:
src = self.unpack(toolchain)
build = self.make_build_path(toolchain)
configure_args = self.configure_args
Expand All @@ -109,7 +112,7 @@ def configure(self, toolchain):
configure(toolchain, src, build, configure_args, self.env)
return build

def _build(self, toolchain):
def _build(self, toolchain) -> None:
build = self.configure(toolchain)
subprocess.check_call(['ninja', '-v', 'install'],
cwd=build, env=toolchain.env)
15 changes: 8 additions & 7 deletions python/build/makeproject.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,34 @@
import subprocess, multiprocessing
from typing import Optional

from build.project import Project

class MakeProject(Project):
def __init__(self, url, md5, installed,
install_target='install',
def __init__(self, url: str, md5: str, installed: str,
install_target: str='install',
**kwargs):
Project.__init__(self, url, md5, installed, **kwargs)
self.install_target = install_target

def get_simultaneous_jobs(self):
def get_simultaneous_jobs(self) -> int:
try:
# use twice as many simultaneous jobs as we have CPU cores
return multiprocessing.cpu_count() * 2
except NotImplementedError:
# default to 12, if multiprocessing.cpu_count() is not implemented
return 12

def get_make_args(self, toolchain):
def get_make_args(self, toolchain) -> list[str]:
return ['--quiet', '-j' + str(self.get_simultaneous_jobs())]

def get_make_install_args(self, toolchain):
def get_make_install_args(self, toolchain) -> list[str]:
return ['--quiet', self.install_target]

def make(self, toolchain, wd, args):
def make(self, toolchain, wd: str, args: list[str]) -> None:
subprocess.check_call(['make'] + args,
cwd=wd, env=toolchain.env)

def build_make(self, toolchain, wd, install=True):
def build_make(self, toolchain, wd: str, install: bool=True) -> None:
self.make(toolchain, wd, self.get_make_args(toolchain))
if install:
self.make(toolchain, wd, self.get_make_install_args(toolchain))
12 changes: 7 additions & 5 deletions python/build/meson.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import os
import subprocess
import platform
from typing import Optional

from build.project import Project

def make_cross_file(toolchain):
def make_cross_file(toolchain) -> str:
if toolchain.is_windows:
system = 'windows'
windres = "windres = '%s'" % toolchain.windres
Expand Down Expand Up @@ -80,7 +81,7 @@ def make_cross_file(toolchain):
""")
return path

def configure(toolchain, src, build, args=()):
def configure(toolchain, src: str, build: str, args: list[str]=[]) -> None:
cross_file = make_cross_file(toolchain)
configure = [
'meson', 'setup',
Expand All @@ -103,18 +104,19 @@ def configure(toolchain, src, build, args=()):
subprocess.check_call(configure, env=env)

class MesonProject(Project):
def __init__(self, url, md5, installed, configure_args=[],
def __init__(self, url: str, md5: str, installed: str,
configure_args: list[str]=[],
**kwargs):
Project.__init__(self, url, md5, installed, **kwargs)
self.configure_args = configure_args

def configure(self, toolchain):
def configure(self, toolchain) -> str:
src = self.unpack(toolchain)
build = self.make_build_path(toolchain)
configure(toolchain, src, build, self.configure_args)
return build

def _build(self, toolchain):
def _build(self, toolchain) -> None:
build = self.configure(toolchain)
subprocess.check_call(['ninja', '-v', 'install'],
cwd=build, env=toolchain.env)
9 changes: 5 additions & 4 deletions python/build/openssl.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import subprocess
from typing import Optional

from build.makeproject import MakeProject

class OpenSSLProject(MakeProject):
def __init__(self, url, md5, installed,
def __init__(self, url: str, md5: str, installed: str,
**kwargs):
MakeProject.__init__(self, url, md5, installed, install_target='install_dev', **kwargs)

def get_make_args(self, toolchain):
def get_make_args(self, toolchain) -> list[str]:
return MakeProject.get_make_args(self, toolchain) + [
'CC=' + toolchain.cc,
'CFLAGS=' + toolchain.cflags,
Expand All @@ -17,13 +18,13 @@ def get_make_args(self, toolchain):
'build_libs',
]

def get_make_install_args(self, toolchain):
def get_make_install_args(self, toolchain) -> list[str]:
# OpenSSL's Makefile runs "ranlib" during installation
return MakeProject.get_make_install_args(self, toolchain) + [
'RANLIB=' + toolchain.ranlib,
]

def _build(self, toolchain):
def _build(self, toolchain) -> None:
src = self.unpack(toolchain, out_of_tree=False)

# OpenSSL has a weird target architecture scheme with lots of
Expand Down
20 changes: 11 additions & 9 deletions python/build/project.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import os, shutil
import re
from typing import cast, BinaryIO, Optional

from build.download import download_and_verify
from build.tar import untar
from build.quilt import push_all

class Project:
def __init__(self, url, md5, installed, name=None, version=None,
base=None,
patches=None,
def __init__(self, url: str, md5: str, installed: str,
name: Optional[str]=None, version: Optional[str]=None,
base: Optional[str]=None,
patches: Optional[str]=None,
edits=None,
use_cxx=False):
use_cxx: bool=False):
if base is None:
basename = os.path.basename(url)
m = re.match(r'^(.+)\.(tar(\.(gz|bz2|xz|lzma))?|zip)$', basename)
Expand Down Expand Up @@ -39,10 +41,10 @@ def __init__(self, url, md5, installed, name=None, version=None,
self.edits = edits
self.use_cxx = use_cxx

def download(self, toolchain):
def download(self, toolchain) -> str:
return download_and_verify(self.url, self.md5, toolchain.tarball_path)

def is_installed(self, toolchain):
def is_installed(self, toolchain) -> bool:
tarball = self.download(toolchain)
installed = os.path.join(toolchain.install_prefix, self.installed)
tarball_mtime = os.path.getmtime(tarball)
Expand All @@ -51,7 +53,7 @@ def is_installed(self, toolchain):
except FileNotFoundError:
return False

def unpack(self, toolchain, out_of_tree=True):
def unpack(self, toolchain, out_of_tree: bool=True) -> str:
if out_of_tree:
parent_path = toolchain.src_path
else:
Expand All @@ -72,7 +74,7 @@ def unpack(self, toolchain, out_of_tree=True):

return path

def make_build_path(self, toolchain, lazy=False):
def make_build_path(self, toolchain, lazy: bool=False) -> str:
path = os.path.join(toolchain.build_path, self.base)
if lazy and os.path.isdir(path):
return path
Expand All @@ -83,5 +85,5 @@ def make_build_path(self, toolchain, lazy=False):
os.makedirs(path, exist_ok=True)
return path

def build(self, toolchain):
def build(self, toolchain) -> None:
self._build(toolchain)
5 changes: 3 additions & 2 deletions python/build/quilt.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import subprocess
from typing import Union

def run_quilt(toolchain, cwd, patches_path, *args):
def run_quilt(toolchain, cwd: str, patches_path: str, *args: str) -> None:
env = dict(toolchain.env)
env['QUILT_PATCHES'] = patches_path
subprocess.check_call(['quilt'] + list(args), cwd=cwd, env=env)

def push_all(toolchain, src_path, patches_path):
def push_all(toolchain, src_path: str, patches_path: str) -> None:
run_quilt(toolchain, src_path, patches_path, 'push', '-a')
13 changes: 7 additions & 6 deletions python/build/verify.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import hashlib
from typing import cast, Any, BinaryIO

def feed_file(h, f):
def feed_file(h: Any, f: BinaryIO) -> None:
"""Feed data read from an open file into the hashlib instance."""

while True:
Expand All @@ -10,20 +11,20 @@ def feed_file(h, f):
break
h.update(data)

def feed_file_path(h, path):
def feed_file_path(h: Any, path: str) -> None:
"""Feed data read from a file (to be opened by this function) into the hashlib instance."""

with open(path, 'rb') as f:
feed_file(h, f)

def file_digest(algorithm, path):
def file_digest(algorithm: Any, path: str) -> str:
"""Calculate the digest of a file and return it in hexadecimal notation."""

h = algorithm()
feed_file_path(h, path)
return h.hexdigest()
return cast(str, h.hexdigest())

def guess_digest_algorithm(digest):
def guess_digest_algorithm(digest: str) -> Any:
l = len(digest)
if l == 32:
return hashlib.md5
Expand All @@ -36,7 +37,7 @@ def guess_digest_algorithm(digest):
else:
return None

def verify_file_digest(path, expected_digest):
def verify_file_digest(path: str, expected_digest: str) -> bool:
"""Verify the digest of a file, and return True if the digest matches with the given expected digest."""

algorithm = guess_digest_algorithm(expected_digest)
Expand Down
9 changes: 5 additions & 4 deletions python/build/zlib.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import subprocess
from typing import Optional

from build.makeproject import MakeProject

class ZlibProject(MakeProject):
def __init__(self, url, md5, installed,
def __init__(self, url: str, md5: str, installed: str,
**kwargs):
MakeProject.__init__(self, url, md5, installed, **kwargs)

def get_make_args(self, toolchain):
def get_make_args(self, toolchain) -> list[str]:
return MakeProject.get_make_args(self, toolchain) + [
'CC=' + toolchain.cc + ' ' + toolchain.cppflags + ' ' + toolchain.cflags,
'CPP=' + toolchain.cc + ' -E ' + toolchain.cppflags,
Expand All @@ -18,13 +19,13 @@ def get_make_args(self, toolchain):
'libz.a'
]

def get_make_install_args(self, toolchain):
def get_make_install_args(self, toolchain) -> list[str]:
return [
'RANLIB=' + toolchain.ranlib,
self.install_target
]

def _build(self, toolchain):
def _build(self, toolchain) -> None:
src = self.unpack(toolchain, out_of_tree=False)

subprocess.check_call(['./configure', '--prefix=' + toolchain.install_prefix, '--static'],
Expand Down

0 comments on commit 3f2016e

Please sign in to comment.