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

Better error message #92

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Next Next commit
Fix #71
  • Loading branch information
Pebaz committed Jul 27, 2023
commit 98574cea10fd8cc97a3a24a7bab9a2e8683a987d
48 changes: 30 additions & 18 deletions nimporter/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@
LINUX: str = 'linux'
EXT_DIR: str = 'nim-extensions'

PLATFORM_TABLE: Dict[str, str] = { # Keys are known to Python and values are Nim-understood
PLATFORM_TABLE = { # Keys are known to Python and values are Nim-understood
'windows': 'Windows',
'darwin': 'MacOSX',
'linux': 'Linux',
}

ARCH_TABLE: Dict[str, str] = { # Keys are known to Python and values are Nim-understood
ARCH_TABLE = { # Keys are known to Python and values are Nim-understood
'x86_32': 'i386',
'x86_64': 'amd64',

Expand All @@ -46,7 +46,7 @@
# 'riscv_64': 'riscv64',
}

ALWAYS_ARGS: List['str'] = [
ALWAYS_ARGS = [
'nimble', # Installs dependencies :)
'c',
'--accept', # Allow installing dependencies
Expand Down Expand Up @@ -89,10 +89,8 @@ def get_import_path(path: Path, root: Path) -> str:
Coerce proper import path using root path

Args:
library(bool): hint as to how to treat the `module_path` parameter.
module_name(str): name of nim module.
module_path(Path): path to nim module.
root(Path): path to project root.
library: hint as to how to treat the `module_path` parameter.
root: path to project root.

Returns:
str: Returns the path of the nim module.
Expand Down Expand Up @@ -147,17 +145,25 @@ def run_process(
of being mainly targeted as a Nim compiler invoker.

Args:
process_args(list): the arg being the executable and the rest are args.
process_args: the arg being the executable and the rest are args.
show_output: if True, prints and does not return process output.

Returns:
A tuple containing any errors, warnings, or hints from the
compilation process.

Raises:
FileNotFoundError: only if the binary to run doesn't exist.
"""
process = subprocess.run(
process_args,
stdout=None if show_output else subprocess.PIPE,
stderr=None if show_output else subprocess.PIPE,
)
try:
process = subprocess.run(
process_args,
stdout=None if show_output else subprocess.PIPE,
stderr=None if show_output else subprocess.PIPE,
)
except FileNotFoundError:
ic(f'Binary not found. CLI: {process_args}')
raise

code, out, err = process.returncode, process.stdout, process.stderr
out = out.decode(errors='ignore') if out else '' # type: ignore[assignment]
Expand Down Expand Up @@ -201,7 +207,7 @@ def get_host_info() -> Tuple[str, str, str]:

def ensure_nimpy() -> None:
"""
Makes sure that the Nimpy Nim library is installed.
Makes sure that the Nim and the Nimpy Nim library is installed.

Verifies that the [Nimpy Library](https://github.com/yglukhov/nimpy) is
installed and installs it otherwise.
Expand All @@ -211,6 +217,12 @@ def ensure_nimpy() -> None:
"""
ic()

try:
run_process('nimble')
except FileNotFoundError as e:
error = CompilationFailedException('Nim not installed or not on path')
raise error from e

show_output = 'NIMPORTER_INSTRUMENT' in os.environ
code, *_ = run_process(shlex.split('nimble path nimpy'), show_output)

Expand All @@ -226,7 +238,6 @@ def ensure_nimpy() -> None:

class NimporterException(Exception):
"Base exception for Nimporter's exception hierarchy."
pass


class CompilationFailedException(NimporterException):
Expand All @@ -240,15 +251,14 @@ def __init__(self, stderr: Union[bytes, str]) -> None:

class ImportFailedException(NimporterException):
"Custom exception for when compilation succeeds but importing fails."
pass


def hash_extension(module_path: Path) -> bytes:
"""
Convenience function to hash an extension module or extension library.

Args:
module_path(Path): the file to hash.
module_path: the file to hash.

Returns:
The hash bytes of the Nim file.
Expand Down Expand Up @@ -293,7 +303,9 @@ class ExtLib:
def __init__(self, path: Path, root: Path, library_hint: bool) -> None:
"""
Args:
path(str): the relative path to the Nim file (for both lib & mod).
path: the relative path to the Nim file (for both lib & mod).
root: entire project root containing potentially many extensions.
library_hint: denotes either Extension Library or Extension Module.
"""
self.library = all((
any(path.parent.glob(f'{path.stem}.nim')),
Expand Down
8 changes: 4 additions & 4 deletions nimporter/nimporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ def validate_spec(spec: ModuleSpec) -> None:
it's better to have good error messages than to be fast in this case.

Args:
spec(Spec): the spec to validate if its module can be imported.
spec: the spec to validate if its module can be imported.

Raises:
A NimporterException if the spec cannot be used to import the given
Expand Down Expand Up @@ -178,9 +178,9 @@ def nimport(
capabilities.

Args:
fullname(str): the name given when importing the module in Python.
path(list): additional search paths.
library(bool): indicates whether or not to compile as a library.
fullname: the name given when importing the module in Python.
path: additional search paths.
library: indicates whether or not to compile as a library.

Returns:
A Spec object that can be used to import the (now compiled) Nim
Expand Down