Skip to content

Commit b8a1a67

Browse files
authored
🔀 Merge pull request #36 from davep/go-faster
Add experimental support for using Numba to speed things up
2 parents c1a58bf + 0b07b41 commit b8a1a67

10 files changed

Lines changed: 213 additions & 387 deletions

File tree

.github/workflows/code-checks.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
runs-on: ubuntu-latest
1818
strategy:
1919
matrix:
20-
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
20+
python-version: ["3.12", "3.13", "3.14"]
2121

2222
steps:
2323

ChangeLog.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
# Complexitty ChangeLog
22

3+
## Unreleased
4+
5+
**Released: WiP**
6+
7+
- Dropped support for Python 3.10 and Python 3.11. ([#36](https://github.com/davep/complexitty/pull/36))
8+
- Added optional support for using [Numba](https://numba.pydata.org) to
9+
speed up the calculations.
10+
([#36](https://github.com/davep/complexitty/pull/36))
11+
312
## v1.0.0
413

514
**Released: 2025-10-03**

README.md

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,33 @@ The package can be installed using [`pipx`](https://pypa.github.io/pipx/):
2727
$ pipx install complexitty
2828
```
2929

30-
### Homebrew
30+
### uv
3131

32-
The package is available via Homebrew. Use the following commands to install:
32+
The application can be installed using [`uv`](https://docs.astral.sh/uv/getting-started/installation/):
3333

3434
```sh
35-
$ brew tap davep/homebrew
36-
$ brew install complexitty
35+
uv tool install complexitty
3736
```
3837

38+
If you don't have `uv` installed you can use [uvx.sh](https://uvx.sh) to
39+
perform the installation. For GNU/Linux or macOS or similar:
40+
41+
```sh
42+
curl -LsSf uvx.sh/complexitty/install.sh | sh
43+
```
44+
45+
or on Windows:
46+
47+
```sh
48+
powershell -ExecutionPolicy ByPass -c "irm https://uvx.sh/complexitty/install.ps1 | iex"
49+
```
50+
51+
### Going faster
52+
53+
Complexitty has a (currently experimental) installation option to make it go
54+
faster using [Numba](http://numba.pydata.org). If you want to try this out,
55+
install it as `complexitty[faster]` rather than `complexitty`.
56+
3957
## Using Complexitty
4058

4159
Once you've installed Complexitty using one of the above methods, you can

docs/source/index.md

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,25 @@ uvx complexitty
3333

3434
to run `complexitty`.
3535

36-
### Homebrew
36+
If you don't have `uv` installed you can use [uvx.sh](https://uvx.sh) to
37+
perform the installation. For GNU/Linux or macOS or similar:
3738

38-
The package is available via [Homebrew](https://brew.sh). Use the following
39-
commands to install:
39+
```sh
40+
curl -LsSf uvx.sh/complexitty/install.sh | sh
41+
```
42+
43+
or on Windows:
4044

4145
```sh
42-
brew tap davep/homebrew
43-
brew install complexitty
46+
powershell -ExecutionPolicy ByPass -c "irm https://uvx.sh/complexitty/install.ps1 | iex"
4447
```
4548

49+
### Going faster
50+
51+
Complexitty has a (currently experimental) installation option to make it go
52+
faster using [Numba](http://numba.pydata.org). If you want to try this out,
53+
install it as `complexitty[faster]` rather than `complexitty`.
54+
4655
## Running Complexitty
4756

4857
Once you've installed Complexitty using one of the [above

pyproject.toml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ dependencies = [
1212
"xdg-base-dirs>=6.0.2",
1313
]
1414
readme = "README.md"
15-
requires-python = ">= 3.10"
15+
requires-python = ">= 3.12"
1616
license = "GPL-3.0-or-later"
1717
keywords = [
1818
"terminal",
@@ -29,8 +29,6 @@ classifiers = [
2929
"Intended Audience :: End Users/Desktop",
3030
"Intended Audience :: Science/Research",
3131
"Operating System :: OS Independent",
32-
"Programming Language :: Python :: 3.10",
33-
"Programming Language :: Python :: 3.11",
3432
"Programming Language :: Python :: 3.12",
3533
"Programming Language :: Python :: 3.13",
3634
"Programming Language :: Python :: 3.14",
@@ -50,11 +48,16 @@ Source = "https://github.com/davep/complexitty"
5048
Issues = "https://github.com/davep/complexitty/issues"
5149
Discussions = "https://github.com/davep/complexitty/discussions"
5250

51+
[project.optional-dependencies]
52+
faster = [
53+
"numba>=0.59.0",
54+
]
55+
5356
[project.scripts]
5457
complexitty = "complexitty.__main__:main"
5558

5659
[build-system]
57-
requires = ["uv_build>=0.8.11,<0.9.0"]
60+
requires = ["uv_build>=0.9.4"]
5861
build-backend = "uv_build"
5962

6063
[tool.uv]

src/complexitty/mandelbrot/calculator.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,30 @@
11
"""The code for calculating the Mandelbrot set."""
22

3+
##############################################################################
4+
# Python imports.
5+
from collections.abc import Callable
6+
from typing import cast
7+
8+
##############################################################################
9+
# Set up for [faster] support.
10+
11+
type MandelbrotCalculator = Callable[[float, float, float, int], int]
12+
"""Type of the Mandelbrot calculator function."""
13+
14+
try:
15+
from numba import jit # type: ignore[import-not-found]
16+
17+
def _maybe_faster(calculator: MandelbrotCalculator) -> MandelbrotCalculator:
18+
return cast(MandelbrotCalculator, jit(nopython=True)(calculator))
19+
20+
except ImportError:
21+
22+
def _maybe_faster(calculator: MandelbrotCalculator) -> MandelbrotCalculator:
23+
return calculator
24+
325

426
##############################################################################
27+
@_maybe_faster
528
def mandelbrot(x: float, y: float, multibrot: float, max_iteration: int) -> int:
629
"""Return the Mandelbrot calculation for the given point.
730

src/complexitty/mandelbrot/colouring.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@
44
# Python imports.
55
from collections.abc import Callable
66
from functools import lru_cache
7-
from typing import Final, TypeAlias
7+
from typing import Final
88

99
##############################################################################
1010
# Textual imports.
1111
from textual.color import Color, Gradient
1212

1313
##############################################################################
14-
ColourMap: TypeAlias = Callable[[int, int], Color]
14+
type ColourMap = Callable[[int, int], Color]
1515
"""Type for a colour map."""
1616

1717

src/complexitty/mandelbrot/widget.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
from dataclasses import dataclass
1010
from time import monotonic
1111

12+
##############################################################################
13+
# Typing extension imports.
14+
from typing import Self
15+
1216
##############################################################################
1317
# Textual imports.
1418
from textual import on
@@ -20,10 +24,6 @@
2024
# Textual-canvas imports.
2125
from textual_canvas import Canvas
2226

23-
##############################################################################
24-
# Typing extension imports.
25-
from typing_extensions import Self
26-
2727
##############################################################################
2828
# Local imports.
2929
from .calculator import mandelbrot

src/complexitty/screens/main.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
# Python imports.
55
from argparse import Namespace
66
from collections import deque
7+
from functools import cache
8+
from importlib.util import find_spec
79
from math import floor, log10
810
from re import Pattern, compile
9-
from typing import Final, NamedTuple, TypeAlias
11+
from typing import Final, NamedTuple
1012

1113
##############################################################################
1214
# Textual imports.
@@ -78,7 +80,18 @@ class Situation(NamedTuple):
7880

7981

8082
##############################################################################
81-
PlotHistory: TypeAlias = deque[Situation]
83+
@cache
84+
def _faster_label() -> str:
85+
"""Get the label that gives our faster status.
86+
87+
Returns:
88+
The labelto show the faster status.
89+
"""
90+
return " | [b]Faster[/]" if find_spec("numba") else ""
91+
92+
93+
##############################################################################
94+
PlotHistory = deque[Situation]
8295
"""Type of the plot history."""
8396

8497

@@ -217,7 +230,7 @@ def _update_situation(self, message: Mandelbrot.Plotted) -> None:
217230
message.mandelbrot.border_subtitle = (
218231
f"{message.mandelbrot.multibrot:0.2f} multibrot | "
219232
f"{message.mandelbrot.max_iteration:0.2f} iterations | "
220-
f"{message.elapsed:0.4f} seconds"
233+
f"{message.elapsed:0.4f} seconds{_faster_label()}"
221234
)
222235

223236
def _remember(self) -> None:

0 commit comments

Comments
 (0)