SkillAgentSearch skills...

Nimporter

Compile Nim Extensions for Python On Import!

Install / Use

/learn @Pebaz/Nimporter

README

<p align="center"> <img src=misc/nimporter-logo.svg> </p>

               License Latest Release Lines of Code Downloads each Month GitHub Repository Star Count GitHub Sponsor Count

Nimporter

Directly import Nim extensions for Python and seamlessly package them for distribution in 1 line of code.

<p align="center"> <img src=misc/Nimporter-Functionality.png> </p> <p align="center"> <img src=misc/Nimporter-Setup.py.png> </p>

🍱 Benefits

  • 🐆 Performance: Nim compiles to C

  • 🚚 Distribution: Packaging Nimporter libraries is the primary use case

  • 📦 Invisible: End users do not need to install Nim for source or binary distributions

  • ♻️ Ecosystem: Leverage Python libraries for breadth and Nim libraries for performance.

  • 🧣 Seamless: Integration with existing Nim code uses the Nimpy library.

  • 🎈 Simple: Nimporter barely has a user interface at all

🐣 Installation

# 🐍 From Pypi:
$ pip install nimporter

# ⚙️ From GitHub:
$ pip install git+https://github.com/Pebaz/Nimporter

Library Author Dependencies:

  1. Nim Compiler (for compiling Nim source files)
  2. Nimpy library (installed automatically if nimporter init lib is used)
  3. Nimporter library (distributed libraries will need access to Nimporter).

Nimporter can work seamlessly when Nim is installed via Choosenim or manually. No additional configuration is necessary once installed since Nimporter can find the Nim standard library and install Nimpy library if Nimble is on your path.

End User Dependencies:

Users of Nimporter libraries only need Nimporter! 🎉

📚 Documentation

To get started, first look at the Nimpy project as that is how Nim libraries are created that can be imported into Python. During development, Python can directly import the Nim file and build the public user-facing Python API in tandem with the Nim library extension. For assistance with the Nim language, look at Nim For Python Programmers as it is a great resource for getting up to speed quickly with Nim. Finally, Nimporter's unit tests all make use of a reference project that was designed to use each of Nimporter's features.

Additionally, the Nimpy tests folder contains code examples on these topics:

  • Passing/Returning None, booleans, integers, floats, strings, lists, tuples, dictionaries, JSON, and objects.
  • Defining/Raising Python exceptions from Nim.
  • Yielding values back to Python using iterators in Nim.
  • Exposing Nim functions with custom names.
  • Exposing Nim extension modules with customized names and docstrings.
  • Using Python builtin functions in Nim.
  • Using passed Python objects and accessing methods and fields.
  • Passing keyword arguments to a Python function.

📋 Features

  • Directly import Nim Extension Modules & Extension Libraries using Nimpy
  • Cache build artifacts for quicker subsequent runs
  • Invalidate cache using hash files
  • Stores artifacts and hash files in __pycache__ to not clutter project
  • Build Source & Binary Distributions using Nimporer with 1 line of code
  • Command Line Interface for introspecting, initializing, and compiling projects
  • Nimporter does not require that library end-users install a Nim compiler

🛠️ Usage

Nimporter Structure

Nimporter is a library that allows the seamless import & packaging of Nim extensions for Python built with Nimpy. Nimpy is a library that is used on the Nim side for iteroperability with Python. All Nimporter libraries rely on Nimpy in order to expose Nim functions to Python. Nimporter's role in this is to formalize a method of distributing Nimpy libraries to ease the burden on library maintainers and end users so that they do not have to even have knowledge of Nim in order to use the library.

Nimpy is a complete library by itself. For information on how to integrate Nim and Python, look at the Nimpy documentation as it will be the Nim day-to-day development experience. Nimporter's role comes into play when a library is ready to be distributed. Nimporter handles the entire packaging for source and binary distributions in 1 line of code.

Important Considerations

Nimporter was designed to help bridge the ecosystem gap between Python and Nim while utilizing Nimpy so that library authors could seamlessly develop and distribute their libraries. Due to this fact, there are important limitations to consider when using Nimporter. They are described below:

  1. Importing: Nimporter uses the C compiler that was used to build Python when importing a Nim module/library. This can be overridden in a <lib name>.nim.cfg but doing so means that the library will most likely not work on other platforms.

  2. Distributing Sources: Nimporter sets the C compiler automatically by iterating through MSVC and GCC for each platform and architecture combo. This means that there will likely be several copies of the generated C source code for each supported platform (given in get_nim_extensions()).

  3. Distributing Binaries: Nimporter uses the same process described for direct import of Nim code and will use the same C compiler that was used to build Python itself.

🎻 Instrumentation

To enable Nimporter debug traces, define NIMPORTER_INSTRUMENT in the environment and Nimporter will use IceCream to show output from Nim and other interesting bits necessary for debugging any issues that could arise.

🦓 Extension Modules & Extension Libraries

Extension Modules are distinct from Extension Libraries. Nimporter (not Nimpy) makes a distinction here. However, it is of special note that distribution of either extension type is the same (nimporter.get_nim_extensions()).

🦄 Extension Libraries

Extension Libraries are entire Nim projects exposed as a single module from the perspective of Python. They are comprised of a single folder containing all code and configuration for the extension. It is important to note that they are a concept formalized by the Nimporter project and must accept some limitations.

These limitations (and capabilities) are listed below:

  • ✔️ Can have external Nim dependencies: inside the Extension Library folder, use a <library name>.nimble in order to depend upon other Nim libraries.

  • ✔️ Can be split up into any number of Nim modules: the Extension Library folder can contain any desired inner folder structure.

  • ✔️ CLI switches used by Nim & the C compiler can be customized: this can be useful but be cognizant about cross-platform compatibility. Remember, if the C compiler used by Python is different than the one used by Nim, there will definitely without a doubt be strange issues arising from this. Note that choosing a different C compiler may result in the setup.py not being able to compile the extension. Use a <library name>.nim.cfg for this use case.

  • ❌ Must use folder structure known to Nimporter: the below folder structure is generated when nimporter init lib is used:

    the_library_name/
        the_library_name.nim  # Must be present
        the_library_name.nim.cfg  # Must be present even if empty
        the_library_name.nimble  # Must contain `requires "nimpy"`
    

🐴 Extension Modules

Extension Modules are the simplest form of using Nimpy libraries with existing Python code. Once Nimporter is imported, Nimpy libraries can be directly imported like normal Python modules. However, there are a few restrictions on what is supported when importing a Nim module in this way. It is important to remember that Nim compiles to C and therefore could theoretically integrate with a build system that is extremely brittle. To completely solve this, Nimporter disallows certain use cases that are technically possible but would otherwise prevent widespread use of the resulting technology.

Below are the restrictions present when importing a Nim Extension Module:

  • ❌ Cannot have any dependencies other than Nimpy: this is due to the fact that Nimporter disallows multiple *.nimble files strewn about in a Python project. Use an Extension Library for this use case.

  • ❌ Cannot import other Nim modules in same directory: this is because there is no way to tell which files pertain to each extension and knowing this is a prerequisite to packaging the extension up for distribution. Additionally, Nimporter moves extensions to temporary

Related Skills

View on GitHub
GitHub Stars854
CategoryDevelopment
Updated1d ago
Forks29

Languages

Python

Security Score

100/100

Audited on Mar 26, 2026

No findings