Skip to content

Commit

Permalink
merge: pr #19 from joshua-auchincloss/v0.3.0
Browse files Browse the repository at this point in the history
v0.3.0
  • Loading branch information
joshua-auchincloss authored Sep 1, 2023
2 parents 8de8273 + a72eb74 commit 22966ed
Show file tree
Hide file tree
Showing 15 changed files with 385 additions and 55 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@ dist/
.coverage*
.coverage
*.html
*.ipynb
.vscode/settings.json
.vscode/
39 changes: 20 additions & 19 deletions COVERAGE.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
| Name | Stmts | Miss | Branch | BrPart | Cover |
| --------------------------------------- | ------: | -----: | ------: | -----: | ------: |
| src/hatch_cython/\_\_init\_\_.py | 2 | 0 | 0 | 0 | 100% |
| src/hatch_cython/config/\_\_init\_\_.py | 2 | 0 | 0 | 0 | 100% |
| src/hatch_cython/config/autoimport.py | 9 | 0 | 4 | 0 | 100% |
| src/hatch_cython/config/config.py | 138 | 12 | 58 | 7 | 89% |
| src/hatch_cython/config/defaults.py | 6 | 0 | 0 | 0 | 100% |
| src/hatch_cython/config/files.py | 22 | 1 | 12 | 2 | 91% |
| src/hatch_cython/config/flags.py | 70 | 1 | 26 | 0 | 99% |
| src/hatch_cython/config/includes.py | 15 | 1 | 8 | 1 | 91% |
| src/hatch_cython/config/macros.py | 12 | 0 | 7 | 0 | 100% |
| src/hatch_cython/config/platform.py | 71 | 2 | 28 | 2 | 96% |
| src/hatch_cython/constants.py | 11 | 0 | 0 | 0 | 100% |
| src/hatch_cython/devel.py | 5 | 0 | 0 | 0 | 100% |
| src/hatch_cython/hooks.py | 5 | 1 | 2 | 0 | 86% |
| src/hatch_cython/plugin.py | 212 | 10 | 160 | 8 | 95% |
| src/hatch_cython/temp.py | 11 | 0 | 0 | 0 | 100% |
| src/hatch_cython/utils.py | 27 | 1 | 12 | 1 | 95% |
| **TOTAL** | **618** | **29** | **317** | **21** | **94%** |
| Name | Stmts | Miss | Branch | BrPart | Cover |
|----------------------------------------- | -------: | -------: | -------: | -------: | ------: |
| src/hatch\_cython/\_\_init\_\_.py | 2 | 0 | 0 | 0 | 100% |
| src/hatch\_cython/config/\_\_init\_\_.py | 2 | 0 | 0 | 0 | 100% |
| src/hatch\_cython/config/autoimport.py | 9 | 0 | 4 | 0 | 100% |
| src/hatch\_cython/config/config.py | 143 | 12 | 60 | 7 | 90% |
| src/hatch\_cython/config/defaults.py | 6 | 0 | 0 | 0 | 100% |
| src/hatch\_cython/config/files.py | 22 | 1 | 12 | 2 | 91% |
| src/hatch\_cython/config/flags.py | 70 | 1 | 26 | 0 | 99% |
| src/hatch\_cython/config/includes.py | 15 | 1 | 8 | 1 | 91% |
| src/hatch\_cython/config/macros.py | 12 | 0 | 7 | 0 | 100% |
| src/hatch\_cython/config/platform.py | 71 | 2 | 28 | 2 | 96% |
| src/hatch\_cython/config/templates.py | 62 | 7 | 34 | 3 | 90% |
| src/hatch\_cython/constants.py | 11 | 0 | 0 | 0 | 100% |
| src/hatch\_cython/devel.py | 5 | 0 | 0 | 0 | 100% |
| src/hatch\_cython/hooks.py | 5 | 1 | 2 | 0 | 86% |
| src/hatch\_cython/plugin.py | 215 | 10 | 160 | 8 | 95% |
| src/hatch\_cython/temp.py | 11 | 0 | 0 | 0 | 100% |
| src/hatch\_cython/utils.py | 38 | 1 | 16 | 1 | 96% |
| **TOTAL** | **699** | **36** | **357** | **24** | **94%** |
55 changes: 50 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ compile_kwargs = { }
dependencies = ["hatch-cython"]

[build.targets.wheel.hooks.cython.options]
<!-- optional, defaults below -->
directives = { boundscheck = false, nonecheck = false, language_level = 3, binding = true }
compile_args = [
"-O3",
Expand Down Expand Up @@ -116,11 +115,9 @@ exclude = [
aliases = {"abclib._filewithoutsuffix" = "abclib.importalias"}
```

## Notes
## Templating

### Templating (Tempita)

Tempita is supported for any files suffixed with `.in`, where the extension output is:
Cython tempita is supported for any files suffixed with `.in`, where the extension output is:

- `.pyx.in`
- `.pyd.in`
Expand All @@ -140,6 +137,54 @@ An example of this is included in:

- [pyi stub file](./example/src/example_lib/templated.pyi.in)
- [pyx cython source file](./example/src/example_lib/templated.pyx.in)
- [pyi stub (rendered)](./example/src/example_lib/templated_maxosx_sample.pyi)
- [pyx cython source (rendered)](./example/src/example_lib/templated_maxosx_sample.pyi)

### Template Arguments

You may also supply arguments for per-file matched namespaces. This follows the above `platforms`, `arch`, & `marker` formats, where if supplied & passing the condition the argument is passed to the template as a named series of keyword arguments.

You supply an `index` value, and all other kwargs to templates are `keywords` for each index value. Follows FIFO priority for all keys except global, which is evaluated first and overriden if there are other matching index directives. The engine will attempt to merge the items of the keywords, roughly following:

```py
args = {
"index": [
{"keyword": "global", ...},
{"keyword": "thisenv", ...},
],
"global": {"abc": 1, "other": 2},
"thisenv": {"other": 3},
}

merge(args) -> {"abc": 1, "other": 3}
```

In hatch.toml:

```toml
[build.targets.wheel.hooks.cython.options.templates]
index = [
{keyword = "global", matches = "*" },
{keyword = "templated_mac", matches = "templated.*.in", platforms = ["darwin"] },
{keyword = "templated_mac_py38", matches = "templated.*.in", platforms = ["darwin"], marker = "python == '3.8'" },
{keyword = "templated_win", matches = "templated.*.in", platforms = ["windows"] },
{keyword = "templated_win_x86_64", matches = "templated.*.in", platforms = ["windows"], arch = ["x86_64"] },

]

<!-- these are passed as arguments for templating -->

<!-- 'global' is a special directive reserved & overriden by all other matched values -->
global = { supported = ["int"] }

templated_mac = { supported = ["int", "float"] }
templated_mac_py38 = { supported = ["int", "float"] }

templated_win = { supported = ["int", "float", "complex"] }

<!-- assuming numpy is cimported in the template -->
templated_win_x86_64 = { supported = ["int", "float", "np.double"]}
```

## License

Expand Down
15 changes: 14 additions & 1 deletion example/hatch.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,22 @@ define_macros = [
["NPY_NO_DEPRECATED_API", "NPY_1_7_API_VERSION"],
]

[build.targets.wheel.hooks.custom.options.templates]
index = [
{keyword = "global", matches = "*" },
{keyword = "templated_mac", matches = "templated.*.in", platforms = ["darwin"] },
{keyword = "templated_win", matches = "templated.*.in", platforms = ["windows"] },
]

global = { supported = ["int"] }
templated_mac = { supported = ["int", "float"] }
templated_win = { supported = ["int", "float", "complex"] }


[build.targets.wheel.hooks.custom.options.files]
exclude = [
"*/no_compile/*"
"*/no_compile/*",
"*_sample*",
]
aliases = {"example_lib._alias" = "example_lib.aliased"}

Expand Down
9 changes: 2 additions & 7 deletions example/src/example_lib/templated.pyi.in
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
{{py:
def supported():
return ["int", "float"]
}}

{{for typ in supported()}}
{{for typ in supported}}

# {{typ}} C adder ({{typ}})
def c{{typ[:1]}}add(a: {{typ}}, b: {{typ}}) -> {{typ}}:
Expand All @@ -25,4 +20,4 @@ def c{{typ[:1]}}pow(a: {{typ}}, b: {{typ}}) -> {{typ}}:
"""
...

{{endfor}}
{{endfor}}
11 changes: 3 additions & 8 deletions example/src/example_lib/templated.pyx.in
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
{{py:
def supported():
return ["int", "float"]
}}

{{for typ in supported()}}
{{for typ in supported}}

# {{typ}} C adder ({{typ}})
cpdef {{typ}} c{{typ[:1]}}add({{typ}} a, {{typ}} b):
Expand All @@ -14,7 +9,7 @@ cpdef {{typ}} c{{typ[:1]}}mul({{typ}} a, {{typ}} b):
return a * b

# {{typ}} C pow ({{typ}})
cpdef {{typ}} c{{typ[:1]}}pow({{typ}} a, int b):
cpdef {{typ}} c{{typ[:1]}}pow({{typ}} a, {{typ}} b):
return a ** b

{{endfor}}
{{endfor}}
47 changes: 47 additions & 0 deletions example/src/example_lib/templated_maxosx_sample.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# DO NOT EDIT.
# Autoformatted by hatch-cython.
# Version: 0.3.0
# Cython: 3.0.2
# Platform: darwin
# Architecture: x86_64
# Keywords: {'supported': ['int', 'float']}

# int C adder (int)
def ciadd(a: int, b: int) -> int:
"""
Takes `a` `int` plus `b` `int`
"""
...

# int C mul (int)
def cimul(a: int, b: int) -> int:
"""
Takes `a` `int` times `b` `int`
"""
...

def cipow(a: int, b: int) -> int:
"""
Takes `a` `int` to the power of `b` `int`
"""
...

# float C adder (float)
def cfadd(a: float, b: float) -> float:
"""
Takes `a` `float` plus `b` `float`
"""
...

# float C mul (float)
def cfmul(a: float, b: float) -> float:
"""
Takes `a` `float` times `b` `float`
"""
...

def cfpow(a: float, b: float) -> float:
"""
Takes `a` `float` to the power of `b` `float`
"""
...
31 changes: 31 additions & 0 deletions example/src/example_lib/templated_maxosx_sample.pyx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# DO NOT EDIT.
# Autoformatted by hatch-cython.
# Version: 0.3.0
# Cython: 3.0.2
# Platform: darwin
# Architecture: x86_64
# Keywords: {'supported': ['int', 'float']}

# int C adder (int)
cpdef int ciadd(int a, int b):
return a + b

# int C mul (int)
cpdef int cimul(int a, int b):
return a * b

# int C pow (int)
cpdef int cipow(int a, int b):
return a ** b

# float C adder (float)
cpdef float cfadd(float a, float b):
return a + b

# float C mul (float)
cpdef float cfmul(float a, float b):
return a * b

# float C pow (float)
cpdef float cfpow(float a, float b):
return a ** b
16 changes: 14 additions & 2 deletions example/tests/test_templated.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
from example_lib.templated import cfpow, ciadd, cipow
from platform import system

from example_lib.templated import ciadd, cipow

PLAT = system().lower()


def test_template_ops():
assert ciadd(1, 2) == 3
assert cipow(2, 2) == 4
assert cfpow(5.5, 2) == 30.25

if PLAT in ("windows", "darwin"):
from example_lib.templated import cfpow

assert cfpow(5.5, 2) == 30.25
if PLAT == "windows":
from example_lib.templated import ccadd

assert ccadd(complex(real=4, imag=2), complex(real=2, imag=0)) == complex(real=6, imag=2)
2 changes: 1 addition & 1 deletion src/hatch_cython/__about__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2023-present joshua-auchincloss <joshua.auchincloss@proton.me>
#
# SPDX-License-Identifier: MIT
__version__ = "0.2.6"
__version__ = "0.3.0"
16 changes: 12 additions & 4 deletions src/hatch_cython/config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from hatch_cython.config.includes import parse_includes
from hatch_cython.config.macros import DefineMacros, parse_macros
from hatch_cython.config.platform import ListedArgs, PlatformArgs, parse_platform_args
from hatch_cython.config.templates import Templates, parse_template_kwds
from hatch_cython.constants import DIRECTIVES, EXIST_TRIM, INCLUDE, LTPY311, MUST_UNIQUE
from hatch_cython.types import CallableT, ListStr

Expand All @@ -22,21 +23,23 @@
"src",
"env",
"files",
"compile_py",
"includes",
"libraries",
"library_dirs",
"define_macros",
"templates",
"compile_py",
"directives",
"library_dirs",
"compile_args",
"cythonize_kwargs",
"define_macros",
"extra_link_args",
"cythonize_kwargs",
"retain_intermediate_artifacts",
)


def parse_from_dict(cls: BuildHookInterface):
given = cls.config.get("options", {})

passed = given.copy()
kwargs = {}
for kw, val in given.items():
Expand All @@ -48,6 +51,9 @@ def parse_from_dict(cls: BuildHookInterface):
elif kw == "define_macros":
val: list
parsed: DefineMacros = parse_macros(val)
elif kw == "templates":
val: dict
parsed: Templates = parse_template_kwds(val)
else:
val: any
parsed: any = val
Expand Down Expand Up @@ -108,6 +114,7 @@ class Config:
retain_intermediate_artifacts: bool = field(default=False)
envflags: EnvFlags = field(default_factory=EnvFlags)
compile_py: bool = field(default=True)
templates: Templates = field(default_factory=Templates)

def __post_init__(self):
self.directives = {**DIRECTIVES, **self.directives}
Expand Down Expand Up @@ -219,6 +226,7 @@ def flush(it):
def asdict(self):
d = asdict(self)
d["envflags"]["env"] = self.envflags.masked_environ()
d["templates"] = self.templates.asdict()
return d

def validate_include_opts(self):
Expand Down
Loading

0 comments on commit 22966ed

Please sign in to comment.