Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added type hints #849

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ coverage.xml
MANIFEST
docs/_build/
docs/gh-pages/

.vscode/
7 changes: 7 additions & 0 deletions .mypy.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[mypy]
python_version = 3.7
warn_return_any = true
warn_unused_configs = true
ignore_missing_imports = true
disallow_untyped_defs = true
exclude=(?x)(^llvmlite/test)
45 changes: 31 additions & 14 deletions llvmlite/_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
# directories (produced by setup.py build) will contain a much shorter file
# that just contains the computed version number.

from __future__ import annotations

# This file is released into the public domain. Generated by
# versioneer-0.12 (https://github.com/warner/python-versioneer)

Expand All @@ -19,7 +21,13 @@

import os, sys, re, subprocess, errno

def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False):
def run_command(
commands: list[str],
args: list[str],
cwd: str | None = None,
verbose: bool = False,
hide_stderr: bool = False,
) -> str | None:
assert isinstance(commands, list)
p = None
for c in commands:
Expand All @@ -31,7 +39,7 @@ def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False):
break
except EnvironmentError:
e = sys.exc_info()[1]
if e.errno == errno.ENOENT:
if e.errno == errno.ENOENT: # type: ignore
continue
if verbose:
print("unable to run %s" % args[0])
Expand All @@ -43,15 +51,17 @@ def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False):
return None
stdout = p.communicate()[0].strip()
if sys.version >= '3':
stdout = stdout.decode()
stdout = stdout.decode() # type: ignore
if p.returncode != 0:
if verbose:
print("unable to run %s (error)" % args[0])
return None
return stdout
return stdout # type: ignore


def versions_from_parentdir(parentdir_prefix, root, verbose=False):
def versions_from_parentdir(
parentdir_prefix: str, root: str, verbose: bool = False
) -> dict[str, str] | None:
# Source tarballs conventionally unpack into a directory that includes
# both the project name and a version string.
dirname = os.path.basename(root)
Expand All @@ -62,12 +72,12 @@ def versions_from_parentdir(parentdir_prefix, root, verbose=False):
return None
return {"version": dirname[len(parentdir_prefix):], "full": ""}

def git_get_keywords(versionfile_abs):
def git_get_keywords(versionfile_abs: str) -> dict[str, str]:
# the code embedded in _version.py can just fetch the value of these
# keywords. When used from setup.py, we don't want to import _version.py,
# so we do it with a regexp instead. This function is not used from
# _version.py.
keywords = {}
keywords: dict[str, str] = {}
try:
f = open(versionfile_abs,"r")
for line in f.readlines():
Expand All @@ -84,7 +94,10 @@ def git_get_keywords(versionfile_abs):
pass
return keywords

def git_versions_from_keywords(keywords, tag_prefix, verbose=False):

def git_versions_from_keywords(
keywords: dict[str, str], tag_prefix: str, verbose: bool = False
) -> dict[str, str] | None:
if not keywords:
return {} # keyword-finding function failed to find keywords
refnames = keywords["refnames"].strip()
Expand Down Expand Up @@ -125,7 +138,9 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose=False):
"full": keywords["full"].strip() }


def git_versions_from_vcs(tag_prefix, root, verbose=False):
def git_versions_from_vcs(
tag_prefix: str, root: str, verbose: bool = False
) -> dict[str, str]:
# this runs 'git' from the root of the source tree. This only gets called
# if the git-archive 'subst' keywords were *not* expanded, and
# _version.py hasn't already been rewritten with a short version string,
Expand All @@ -143,7 +158,7 @@ def git_versions_from_vcs(tag_prefix, root, verbose=False):
cwd=root)
if stdout is None:
return {}
if not stdout.startswith(tag_prefix):
if not stdout.startswith(tag_prefix): # type: ignore
if verbose:
print("tag '%s' doesn't start with prefix '%s'" % (stdout, tag_prefix))
return {}
Expand All @@ -152,12 +167,14 @@ def git_versions_from_vcs(tag_prefix, root, verbose=False):
if stdout is None:
return {}
full = stdout.strip()
if tag.endswith("-dirty"):
full += "-dirty"
return {"version": tag, "full": full}
if tag.endswith("-dirty"): # type: ignore
full += "-dirty" # type: ignore
return {"version": tag, "full": full} # type: ignore


def get_versions(default={"version": "unknown", "full": ""}, verbose=False):
def get_versions(
default: dict[str, str] = {"version": "unknown", "full": ""}, verbose: bool = False
) -> dict[str, str]:
# I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have
# __file__, we can work backwards from there to the root. Some
# py2exe/bbfreeze/non-CPython implementations don't do __file__, in which
Expand Down
2 changes: 1 addition & 1 deletion llvmlite/binding/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@
from .value import *
from .analysis import *
from .object_file import *
from .context import *
from .context import *
21 changes: 14 additions & 7 deletions llvmlite/binding/analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@
A collection of analysis utilities
"""

from __future__ import annotations

from ctypes import POINTER, c_char_p, c_int
from typing import Any

from llvmlite import ir
from llvmlite.binding import ffi
from llvmlite.binding.module import parse_assembly
from llvmlite.binding.value import ValueRef


def get_function_cfg(func, show_inst=True):
def get_function_cfg(func: ir.Function | ValueRef, show_inst: bool = True) -> str:
"""Return a string of the control-flow graph of the function in DOT
format. If the input `func` is not a materialized function, the module
containing the function is parsed to create an actual LLVM module.
Expand All @@ -27,7 +31,7 @@ def get_function_cfg(func, show_inst=True):
return str(dotstr)


def view_dot_graph(graph, filename=None, view=False):
def view_dot_graph(graph: Any, filename: str | None = None, view: bool = False) -> Any:
"""
View the given DOT source. If view is True, the image is rendered
and viewed by the default application in the system. The file path of
Expand All @@ -47,20 +51,23 @@ def view_dot_graph(graph, filename=None, view=False):

"""
# Optionally depends on graphviz package
import graphviz as gv
# could not be resolved
import graphviz as gv # type: ignore

src = gv.Source(graph)
src = gv.Source(graph) # type: ignore
if view:
# Returns the output file path
return src.render(filename, view=view)
return src.render(filename, view=view) # type: ignore
else:
# Attempts to show the graph in IPython notebook
try:
__IPYTHON__
__IPYTHON__ # type: ignore # is undefined
except NameError:
return src
else:
import IPython.display as display
# could not be resolved
import IPython.display as display # type: ignore

format = 'svg'
return display.SVG(data=src.pipe(format))

Expand Down
10 changes: 6 additions & 4 deletions llvmlite/binding/common.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
from __future__ import annotations

import atexit


def _encode_string(s):
def _encode_string(s: str) -> bytes:
encoded = s.encode('utf-8')
return encoded


def _decode_string(b):
def _decode_string(b: bytes) -> str:
return b.decode('utf-8')


Expand All @@ -17,14 +19,14 @@ def _decode_string(b):
_shutting_down = [False]


def _at_shutdown():
def _at_shutdown() -> None:
_shutting_down[0] = True


atexit.register(_at_shutdown)


def _is_shutting_down(_shutting_down=_shutting_down):
def _is_shutting_down(_shutting_down: list[bool] = _shutting_down) -> bool:
"""
Whether the interpreter is currently shutting down.
For use in finalizers, __del__ methods, and similar; it is advised
Expand Down
14 changes: 9 additions & 5 deletions llvmlite/binding/context.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
from __future__ import annotations

from typing import Any

from llvmlite.binding import ffi


def create_context():
def create_context() -> ContextRef:
return ContextRef(ffi.lib.LLVMPY_ContextCreate())


def get_global_context():
def get_global_context() -> GlobalContextRef:
return GlobalContextRef(ffi.lib.LLVMPY_GetGlobalContext())


class ContextRef(ffi.ObjectRef):
def __init__(self, context_ptr):
def __init__(self, context_ptr: Any) -> None:
super(ContextRef, self).__init__(context_ptr)

def _dispose(self):
def _dispose(self) -> None:
ffi.lib.LLVMPY_ContextDispose(self)


class GlobalContextRef(ContextRef):
def _dispose(self):
def _dispose(self) -> None:
pass


Expand Down
11 changes: 7 additions & 4 deletions llvmlite/binding/dylib.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
from ctypes import c_void_p, c_char_p, c_bool, POINTER
from __future__ import annotations

from ctypes import POINTER, c_bool, c_char_p, c_void_p
from typing import Any

from llvmlite.binding import ffi
from llvmlite.binding.common import _encode_string


def address_of_symbol(name):
def address_of_symbol(name: str) -> Any:
"""
Get the in-process address of symbol named *name*.
An integer is returned, or None if the symbol isn't found.
"""
return ffi.lib.LLVMPY_SearchAddressOfSymbol(_encode_string(name))


def add_symbol(name, address):
def add_symbol(name: str, address: int) -> None:
"""
Register the *address* of global symbol *name*. This will make
it usable (e.g. callable) from LLVM-compiled functions.
"""
ffi.lib.LLVMPY_AddSymbol(_encode_string(name), c_void_p(address))


def load_library_permanently(filename):
def load_library_permanently(filename: str) -> None:
"""
Load an external library
"""
Expand Down
Loading