nuwa-build 0.2.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nuwa_build-0.2.5/LICENSE +21 -0
- nuwa_build-0.2.5/MANIFEST.in +5 -0
- nuwa_build-0.2.5/PKG-INFO +505 -0
- nuwa_build-0.2.5/README.md +476 -0
- nuwa_build-0.2.5/pyproject.toml +47 -0
- nuwa_build-0.2.5/setup.cfg +4 -0
- nuwa_build-0.2.5/src/nuwa_build/__init__.py +22 -0
- nuwa_build-0.2.5/src/nuwa_build/backend.py +440 -0
- nuwa_build-0.2.5/src/nuwa_build/cli.py +425 -0
- nuwa_build-0.2.5/src/nuwa_build/config.py +160 -0
- nuwa_build-0.2.5/src/nuwa_build/discovery.py +115 -0
- nuwa_build-0.2.5/src/nuwa_build/errors.py +217 -0
- nuwa_build-0.2.5/src/nuwa_build/stubs.py +129 -0
- nuwa_build-0.2.5/src/nuwa_build/templates.py +422 -0
- nuwa_build-0.2.5/src/nuwa_build/utils.py +236 -0
- nuwa_build-0.2.5/src/nuwa_build/wheel_utils.py +84 -0
- nuwa_build-0.2.5/src/nuwa_build.egg-info/PKG-INFO +505 -0
- nuwa_build-0.2.5/src/nuwa_build.egg-info/SOURCES.txt +29 -0
- nuwa_build-0.2.5/src/nuwa_build.egg-info/dependency_links.txt +1 -0
- nuwa_build-0.2.5/src/nuwa_build.egg-info/entry_points.txt +5 -0
- nuwa_build-0.2.5/src/nuwa_build.egg-info/requires.txt +13 -0
- nuwa_build-0.2.5/src/nuwa_build.egg-info/top_level.txt +1 -0
- nuwa_build-0.2.5/tests/conftest.py +151 -0
- nuwa_build-0.2.5/tests/fixtures/projects/multi_file/multi_file_test/__init__.py +5 -0
- nuwa_build-0.2.5/tests/fixtures/projects/simple/simple_test/__init__.py +5 -0
- nuwa_build-0.2.5/tests/fixtures/projects/with_errors/with_errors/__init__.py +5 -0
- nuwa_build-0.2.5/tests/integration/test_compilation.py +259 -0
- nuwa_build-0.2.5/tests/unit/test_config.py +238 -0
- nuwa_build-0.2.5/tests/unit/test_discovery.py +142 -0
- nuwa_build-0.2.5/tests/unit/test_errors.py +218 -0
- nuwa_build-0.2.5/tests/unit/test_utils.py +166 -0
nuwa_build-0.2.5/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Martin Eastwood
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,505 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: nuwa-build
|
|
3
|
+
Version: 0.2.5
|
|
4
|
+
Summary: Build and publish Nim extensions for Python with zero configuration.
|
|
5
|
+
Author-email: Martin Eastwood <martin.eastwood@gmx.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Classifier: Development Status :: 4 - Beta
|
|
8
|
+
Classifier: Intended Audience :: Developers
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
16
|
+
Requires-Python: >=3.9
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Requires-Dist: tomli>=1.2.0; python_version < "3.11"
|
|
20
|
+
Requires-Dist: watchdog>=5.0.0
|
|
21
|
+
Provides-Extra: test
|
|
22
|
+
Requires-Dist: pytest>=7.0.0; extra == "test"
|
|
23
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "test"
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
26
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
27
|
+
Requires-Dist: pre-commit>=4.0.0; extra == "dev"
|
|
28
|
+
Dynamic: license-file
|
|
29
|
+
|
|
30
|
+
# Nuwa Build
|
|
31
|
+
|
|
32
|
+
Build Python extensions with Nim using zero-configuration tooling.
|
|
33
|
+
|
|
34
|
+
## Status
|
|
35
|
+
|
|
36
|
+
🚧 **Work In Progress:** This library is currently under active development. APIs may change, and things might break. Use at your own risk!
|
|
37
|
+
|
|
38
|
+
## Features
|
|
39
|
+
|
|
40
|
+
- **Zero Configuration**: Works out of the box with sensible defaults
|
|
41
|
+
- **Multi-file Projects**: Compile multiple Nim files into a single Python extension
|
|
42
|
+
- **Flexible Configuration**: Configure via `pyproject.toml` or CLI arguments
|
|
43
|
+
- **PEP 517/660 Compatible**: Build wheels and source distributions
|
|
44
|
+
- **Editable Installs**: `pip install -e .` support for development
|
|
45
|
+
- **Watch Mode**: Auto-recompile on file changes with `nuwa watch`
|
|
46
|
+
- **Auto Dependencies**: Automatically install Nimble packages before build
|
|
47
|
+
- **Testing Support**: Includes pytest tests in project template
|
|
48
|
+
- **Validation**: Validates configuration and provides helpful error messages
|
|
49
|
+
- **Proper Platform Tags**: Generates correct wheel tags for your platform
|
|
50
|
+
|
|
51
|
+
## Installation
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# Install Nuwa
|
|
55
|
+
pip install nuwa-build
|
|
56
|
+
|
|
57
|
+
# Install nimpy (Nim-Python bridge)
|
|
58
|
+
nimble install nimpy
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**Requirements**:
|
|
62
|
+
|
|
63
|
+
- Python 3.9+
|
|
64
|
+
- Nim compiler (must be installed and available in your PATH)
|
|
65
|
+
- nimpy library (install via `nimble install nimpy`)
|
|
66
|
+
|
|
67
|
+
## Quick Start
|
|
68
|
+
|
|
69
|
+
### Create a New Project
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
nuwa new my_project
|
|
73
|
+
cd my_project
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
This creates:
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
my_project/
|
|
80
|
+
├── pyproject.toml # Python project config
|
|
81
|
+
├── nim/ # Nim source files
|
|
82
|
+
│ ├── my_project_lib.nim # Main entry point (filename = module name)
|
|
83
|
+
│ └── helpers.nim # Additional modules
|
|
84
|
+
├── my_project/ # Python package
|
|
85
|
+
│ ├── __init__.py # Package wrapper
|
|
86
|
+
│ └── my_project_lib.so # Compiled extension (generated)
|
|
87
|
+
├── tests/ # Test files
|
|
88
|
+
│ └── test_my_project.py # Pytest tests
|
|
89
|
+
├── example.py # Example/test file
|
|
90
|
+
└── README.md
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Build and Test
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
# Compile debug build
|
|
97
|
+
nuwa develop
|
|
98
|
+
|
|
99
|
+
# Compile release build
|
|
100
|
+
nuwa develop --release
|
|
101
|
+
|
|
102
|
+
# Run example
|
|
103
|
+
python example.py
|
|
104
|
+
|
|
105
|
+
# Run tests (requires pytest)
|
|
106
|
+
pip install pytest
|
|
107
|
+
pytest
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**Note**: No `pip install -e .` needed due to flat project layout. You can run `python example.py` and `pytest` directly after compiling the default template project.
|
|
111
|
+
|
|
112
|
+
### 🤖 AI-Assisted Development
|
|
113
|
+
|
|
114
|
+
This project includes a `skill.md` file designed to teach AI coding agents (Cursor, Antigravity, Copilot, etc.) how to work with Nuwa Build.
|
|
115
|
+
|
|
116
|
+
**Why use it?**
|
|
117
|
+
|
|
118
|
+
Standard LLMs often assume Python extensions require `setup.py` or `pip install -e .`. The `skill.md` file provides your agent with the correct context to:
|
|
119
|
+
|
|
120
|
+
- **Understand the flat layout:** Knows that `.so` files are generated directly in the package directory.
|
|
121
|
+
- **Use correct commands:** Enforces `nuwa develop` and `nuwa watch` instead of standard pip commands.
|
|
122
|
+
- **Write correct Nim:** Reminds the agent to use `include` for shared libraries and `{.nuwa_export.}` for bindings (which automatically generates type stubs).
|
|
123
|
+
|
|
124
|
+
**How to use:**
|
|
125
|
+
|
|
126
|
+
1. **Claude Code:** Copy the `skill.md` file into `~/.claude/skills/nuwa-build/` for global use or `<workspace-root>/.claude/skills/nuwa-build/` for project-specific use.
|
|
127
|
+
2. **Antigravity:** Copy the `skill.md` file into `~/.gemini/antigravity/skills/nuwa-build/` for global use or `<workspace-root>/.agent/skills/nuwa-build/` for project-specific use.
|
|
128
|
+
3. **Cursor:** Copy the `skill.md` file into `~/.cursor/skills/nuwa-build/` for global use or `<workspace-root>/.cursor/skills/nuwa-build/` for project-specific use.
|
|
129
|
+
4. **General Chat:** Upload or paste `skill.md` into your context window when starting a new session.
|
|
130
|
+
|
|
131
|
+
### Watch Mode
|
|
132
|
+
|
|
133
|
+
For development, use watch mode to automatically recompile when you change Nim files:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
# Watch for changes and auto-recompile
|
|
137
|
+
nuwa watch
|
|
138
|
+
|
|
139
|
+
# Watch with tests after each compile
|
|
140
|
+
nuwa watch --run-tests
|
|
141
|
+
|
|
142
|
+
# Watch in release mode
|
|
143
|
+
nuwa watch --release
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Install and Distribute
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
# Build a wheel
|
|
150
|
+
pip install . --no-build-isolation
|
|
151
|
+
|
|
152
|
+
# Build source distribution
|
|
153
|
+
python -m build
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Project Structure
|
|
157
|
+
|
|
158
|
+
Nuwa uses a simple flat layout for easy development:
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
project/
|
|
162
|
+
├── pyproject.toml # Configuration
|
|
163
|
+
├── nim/ # Nim source files
|
|
164
|
+
│ ├── my_package_lib.nim # Main entry point (determines module name)
|
|
165
|
+
│ └── helpers.nim # Additional modules
|
|
166
|
+
├── my_package/ # Python package
|
|
167
|
+
│ ├── __init__.py # Package wrapper (can add Python code)
|
|
168
|
+
│ └── my_package_lib.so # Compiled Nim extension (generated)
|
|
169
|
+
└── tests/
|
|
170
|
+
└── test_my_package.py # Pytest tests
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
The compiled extension is named `{module_name}_lib.so` to avoid conflicts with the Python package. Your `__init__.py` imports from it and can add Python wrappers.
|
|
174
|
+
|
|
175
|
+
## Configuration
|
|
176
|
+
|
|
177
|
+
### pyproject.toml
|
|
178
|
+
|
|
179
|
+
Configure your project in the `[tool.nuwa]` section:
|
|
180
|
+
|
|
181
|
+
```toml
|
|
182
|
+
[build-system]
|
|
183
|
+
requires = ["nuwa-build"]
|
|
184
|
+
build-backend = "nuwa_build"
|
|
185
|
+
|
|
186
|
+
[project]
|
|
187
|
+
name = "my-package"
|
|
188
|
+
version = "0.1.0"
|
|
189
|
+
|
|
190
|
+
[tool.nuwa]
|
|
191
|
+
# Nim source directory (default: "nim")
|
|
192
|
+
nim-source = "nim"
|
|
193
|
+
|
|
194
|
+
# Python module name (default: derived from project name)
|
|
195
|
+
module-name = "my_package"
|
|
196
|
+
|
|
197
|
+
# Internal library name (default: "{module_name}_lib")
|
|
198
|
+
lib-name = "my_package_lib"
|
|
199
|
+
|
|
200
|
+
# Entry point file (default: "{lib_name}.nim")
|
|
201
|
+
entry-point = "my_package_lib.nim"
|
|
202
|
+
|
|
203
|
+
# Output location: "auto", "src", or explicit path
|
|
204
|
+
output-location = "auto"
|
|
205
|
+
|
|
206
|
+
# Additional Nim compiler flags (optional)
|
|
207
|
+
nim-flags = []
|
|
208
|
+
|
|
209
|
+
# Nimble dependencies (auto-installed before build)
|
|
210
|
+
nimble-deps = ["nimpy", "cligen >= 1.0.0"]
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Configuration Options
|
|
214
|
+
|
|
215
|
+
| Option | Type | Default | Description |
|
|
216
|
+
| ----------------- | ------ | ------------------------- | -------------------------------------------------------------- |
|
|
217
|
+
| `nim-source` | string | `"nim"` | Directory containing Nim source files |
|
|
218
|
+
| `module-name` | string | Derived from project name | Python package name |
|
|
219
|
+
| `lib-name` | string | `{module_name}_lib` | Internal compiled extension name |
|
|
220
|
+
| `entry-point` | string | `{lib_name}.nim` | Main entry point file (relative to `nim-source`) |
|
|
221
|
+
| `output-location` | string | `"auto"` | Where to place compiled extension (`"auto"`, `"src"`, or path) |
|
|
222
|
+
| `nim-flags` | list | `[]` | Additional compiler flags |
|
|
223
|
+
| `nimble-deps` | list | `[]` | Nimble packages to auto-install before build |
|
|
224
|
+
|
|
225
|
+
**Note**: The entry point filename determines the Python module name of the compiled extension. If your entry point is `my_package_lib.nim`, the module will be importable as `my_package_lib`.
|
|
226
|
+
|
|
227
|
+
## CLI Commands
|
|
228
|
+
|
|
229
|
+
### `nuwa new <path>`
|
|
230
|
+
|
|
231
|
+
Create a new project scaffold:
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
nuwa new my_project
|
|
235
|
+
nuwa new my_project --name custom-name
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### `nuwa develop`
|
|
239
|
+
|
|
240
|
+
Compile the project in-place:
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
# Debug build
|
|
244
|
+
nuwa develop
|
|
245
|
+
|
|
246
|
+
# Release build
|
|
247
|
+
nuwa develop --release
|
|
248
|
+
|
|
249
|
+
# Override configuration
|
|
250
|
+
nuwa develop --module-name my_module
|
|
251
|
+
nuwa develop --nim-source my_nim_dir
|
|
252
|
+
nuwa develop --entry-point main.nim
|
|
253
|
+
nuwa develop --output-dir build/
|
|
254
|
+
nuwa develop --nim-flag="-d:danger" --nim-flag="--opt:size"
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
**Note**: After running `nuwa develop`, the compiled extension will be in `{module_name}/`. You can then run `python example.py` or `pytest` directly without any installation step.
|
|
258
|
+
|
|
259
|
+
### `nuwa watch`
|
|
260
|
+
|
|
261
|
+
Watch for file changes and automatically recompile:
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
# Watch for changes and auto-recompile
|
|
265
|
+
nuwa watch
|
|
266
|
+
|
|
267
|
+
# Watch with tests after each compile
|
|
268
|
+
nuwa watch --run-tests
|
|
269
|
+
|
|
270
|
+
# Watch in release mode
|
|
271
|
+
nuwa watch --release
|
|
272
|
+
|
|
273
|
+
# Override configuration
|
|
274
|
+
nuwa watch --module-name my_module
|
|
275
|
+
nuwa watch --nim-source my_nim_dir
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### `nuwa clean`
|
|
279
|
+
|
|
280
|
+
Clean build artifacts and dependencies:
|
|
281
|
+
|
|
282
|
+
```bash
|
|
283
|
+
# Clean everything (dependencies + artifacts)
|
|
284
|
+
nuwa clean
|
|
285
|
+
|
|
286
|
+
# Clean only dependencies (.nimble/ directory)
|
|
287
|
+
nuwa clean --deps
|
|
288
|
+
|
|
289
|
+
# Clean only build artifacts and cache
|
|
290
|
+
nuwa clean --artifacts
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
**What gets cleaned:**
|
|
294
|
+
|
|
295
|
+
- `--deps`: Removes the `.nimble/` directory (local Nimble packages)
|
|
296
|
+
- `--artifacts`: Removes `nimcache/`, `build/`, `dist/` directories and compiled `.so`/`.pyd` files
|
|
297
|
+
- (no flags): Cleans both dependencies and artifacts
|
|
298
|
+
|
|
299
|
+
## Entry Point Discovery
|
|
300
|
+
|
|
301
|
+
If `entry-point` is not specified, Nuwa will automatically discover the main entry point using this priority:
|
|
302
|
+
|
|
303
|
+
1. Explicit `[tool.nuwa] entry-point` configuration
|
|
304
|
+
2. `{module_name}_lib.nim` (matches the lib-name)
|
|
305
|
+
3. `lib.nim` (fallback convention)
|
|
306
|
+
4. First (and only) `.nim` file if only one exists
|
|
307
|
+
5. Error if multiple files found and no clear entry point
|
|
308
|
+
|
|
309
|
+
## Mixing Python and Nim
|
|
310
|
+
|
|
311
|
+
Your `__init__.py` can import from the compiled Nim extension and add Python wrappers:
|
|
312
|
+
|
|
313
|
+
```python
|
|
314
|
+
# In my_package/__init__.py
|
|
315
|
+
from .my_package_lib import *
|
|
316
|
+
|
|
317
|
+
__version__ = "0.1.0"
|
|
318
|
+
|
|
319
|
+
# Example: Wrap Nim functions with Python code
|
|
320
|
+
def validate_dataframe(df, column_name):
|
|
321
|
+
"""Extract pandas data and pass to Nim for zero-copy validation"""
|
|
322
|
+
import numpy as np
|
|
323
|
+
from ctypes import c_void_p
|
|
324
|
+
|
|
325
|
+
# Extract data as numpy array (zero-copy view)
|
|
326
|
+
data = df[column_name].to_numpy()
|
|
327
|
+
|
|
328
|
+
# Get pointer and pass to Nim for validation
|
|
329
|
+
result = validate_array_raw(
|
|
330
|
+
data.ctypes.data_as(c_void_p),
|
|
331
|
+
len(data)
|
|
332
|
+
)
|
|
333
|
+
return result
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
This allows you to:
|
|
337
|
+
|
|
338
|
+
- Use Python to extract/prepare data (e.g., from pandas DataFrames)
|
|
339
|
+
- Pass pointers/arrays to Nim for zero-copy processing
|
|
340
|
+
- Return results back to Python for formatting
|
|
341
|
+
|
|
342
|
+
## Multi-File Projects
|
|
343
|
+
|
|
344
|
+
Nim's module system handles dependencies automatically. Use `include` to add code from other Nim files:
|
|
345
|
+
|
|
346
|
+
**nim/my_package_lib.nim:**
|
|
347
|
+
|
|
348
|
+
```nim
|
|
349
|
+
import nuwa_sdk # Provides nuwa_export for automatic type stub generation
|
|
350
|
+
include helpers # Include helpers.nim from same directory
|
|
351
|
+
|
|
352
|
+
proc greet(name: string): string {.nuwa_export.} =
|
|
353
|
+
return make_greeting(name)
|
|
354
|
+
|
|
355
|
+
proc add(a: int, b: int): int {.nuwa_export.} =
|
|
356
|
+
return a + b
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
**nim/helpers.nim:**
|
|
360
|
+
|
|
361
|
+
```nim
|
|
362
|
+
proc make_greeting(name: string): string =
|
|
363
|
+
return "Hello, " & name & "!"
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
Compile `my_package_lib.nim` and both modules are included in the final `.so`/`.pyd` file.
|
|
367
|
+
|
|
368
|
+
**Important**: Use `include` (not `import`) when building shared libraries. The `include` directive literally includes the code at compile time, while `import` creates a separate module namespace.
|
|
369
|
+
|
|
370
|
+
### Exporting Functions to Python
|
|
371
|
+
|
|
372
|
+
**You must add the `{.nuwa_export.}` pragma to any Nim procedure you want to access from Python.**
|
|
373
|
+
|
|
374
|
+
- ✅ **Exported**: `proc add(a: int, b: int): int {.nuwa_export.}` - Accessible from Python
|
|
375
|
+
- ❌ **Not exported**: `proc add(a: int, b: int): int` - Not accessible from Python
|
|
376
|
+
|
|
377
|
+
The `{.nuwa_export.}` pragma does two things:
|
|
378
|
+
1. Makes the function callable from Python (via the underlying nimpy library)
|
|
379
|
+
2. Generates type stub information for IDE autocomplete and type checking
|
|
380
|
+
|
|
381
|
+
**Common mistake**: Forgetting the pragma means your function won't be available in Python, even though it compiles successfully.
|
|
382
|
+
|
|
383
|
+
## Output Location
|
|
384
|
+
|
|
385
|
+
The `output-location` setting controls where the compiled extension is placed:
|
|
386
|
+
|
|
387
|
+
- **`"auto"`** (default): Uses flat layout - places extension in `{module_name}/`
|
|
388
|
+
|
|
389
|
+
- **`"src"`**: Explicitly uses `src/{module_name}/` (for compatibility with old projects)
|
|
390
|
+
|
|
391
|
+
- **Explicit path**: Use a custom output directory
|
|
392
|
+
|
|
393
|
+
## Python Usage
|
|
394
|
+
|
|
395
|
+
Once compiled and installed, use your Nim extension like any Python module:
|
|
396
|
+
|
|
397
|
+
```python
|
|
398
|
+
import my_package
|
|
399
|
+
|
|
400
|
+
# Call Nim-compiled functions (imported via __init__.py)
|
|
401
|
+
result = my_package.greet("World")
|
|
402
|
+
print(result) # "Hello, World!"
|
|
403
|
+
|
|
404
|
+
sum_result = my_package.add(5, 10)
|
|
405
|
+
print(sum_result) # 15
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
## How It Works
|
|
409
|
+
|
|
410
|
+
1. **Validation**: Checks Nim compiler is installed and config is valid
|
|
411
|
+
2. **Source Discovery**: Finds Nim files in the configured directory
|
|
412
|
+
3. **Entry Point Detection**: Identifies the main entry point file
|
|
413
|
+
4. **Compilation**: Invokes `nim c --app:lib` with appropriate flags
|
|
414
|
+
5. **Module Path**: Adds `--path:{nim_dir}` so includes work between files
|
|
415
|
+
6. **Output**: Generates proper `{lib_name}.so` (Linux/Mac) or `{lib_name}.pyd` (Windows) in the module directory
|
|
416
|
+
7. **Ready to use**: Module is immediately importable from the project root
|
|
417
|
+
|
|
418
|
+
### Contributing
|
|
419
|
+
|
|
420
|
+
Contributions are welcome! The codebase is well-organized with:
|
|
421
|
+
|
|
422
|
+
- Full type hints
|
|
423
|
+
- Comprehensive error handling
|
|
424
|
+
- Proper logging support
|
|
425
|
+
- Context managers for resource management
|
|
426
|
+
|
|
427
|
+
## Troubleshooting
|
|
428
|
+
|
|
429
|
+
### "Nim compiler not found"
|
|
430
|
+
|
|
431
|
+
Make sure Nim is installed and in your PATH:
|
|
432
|
+
|
|
433
|
+
```bash
|
|
434
|
+
nim --version
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
Install from https://nim-lang.org/install.html if needed.
|
|
438
|
+
|
|
439
|
+
### "cannot open file: nimpy"
|
|
440
|
+
|
|
441
|
+
You need to install the nimpy library. You can either:
|
|
442
|
+
|
|
443
|
+
**Option 1: Auto-install via configuration** (Recommended)
|
|
444
|
+
|
|
445
|
+
```toml
|
|
446
|
+
[tool.nuwa]
|
|
447
|
+
nimble-deps = ["nimpy"]
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
**Option 2: Manual installation**
|
|
451
|
+
|
|
452
|
+
```bash
|
|
453
|
+
nimble install nimpy
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
### "nimble package manager not found"
|
|
457
|
+
|
|
458
|
+
Nimble is installed with Nim. Make sure Nim is properly installed and in your PATH:
|
|
459
|
+
|
|
460
|
+
```bash
|
|
461
|
+
nim --version
|
|
462
|
+
nimble --version
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
If nimble is not found, reinstall Nim from https://nim-lang.org/install.html.
|
|
466
|
+
|
|
467
|
+
### "ModuleNotFoundError: No module named 'my_package'"
|
|
468
|
+
|
|
469
|
+
The module needs to be compiled first. Run:
|
|
470
|
+
|
|
471
|
+
```bash
|
|
472
|
+
nuwa develop
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
Then you can import it directly from the project root. No `pip install` needed!
|
|
476
|
+
|
|
477
|
+
**For pytest**: Make sure you've compiled the extension with `nuwa develop` first. The flat layout allows pytest to discover the module automatically.
|
|
478
|
+
|
|
479
|
+
### "ValueError: Module name '...' is not a valid Python identifier"
|
|
480
|
+
|
|
481
|
+
Your project name contains invalid characters for Python modules. Module names can only contain letters, numbers, and underscores, and cannot start with a number. Use the `--name` option:
|
|
482
|
+
|
|
483
|
+
```bash
|
|
484
|
+
nuwa new my-project --name my_valid_name
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
### "Multiple .nim files found in nim/"
|
|
488
|
+
|
|
489
|
+
Nuwa found multiple `.nim` files but can't determine which is the entry point. Specify it in `pyproject.toml`:
|
|
490
|
+
|
|
491
|
+
```toml
|
|
492
|
+
[tool.nuwa]
|
|
493
|
+
entry-point = "my_entry_file.nim"
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
Or ensure there's only one `.nim` file, or name your entry point `{module_name}_lib.nim`.
|
|
497
|
+
|
|
498
|
+
## License
|
|
499
|
+
|
|
500
|
+
MIT
|
|
501
|
+
|
|
502
|
+
## Acknowledgments
|
|
503
|
+
|
|
504
|
+
- Uses [nimpy](https://github.com/yglukhov/nimpy) for Python bindings
|
|
505
|
+
- Named after [Nüwa](https://en.wikipedia.org/wiki/N%C3%BCwa), the Chinese goddess of creation
|