https://github.com/nimpylib/nimpylib
"Write Python in Nim!" Python builtins/standard-Lib functions ported to Nim
https://github.com/nimpylib/nimpylib
library metaprogramming nim-lang nimble python python3
Last synced: 7 months ago
JSON representation
"Write Python in Nim!" Python builtins/standard-Lib functions ported to Nim
- Host: GitHub
- URL: https://github.com/nimpylib/nimpylib
- Owner: nimpylib
- License: mit
- Created: 2022-12-11T11:21:07.000Z (about 3 years ago)
- Default Branch: master
- Last Pushed: 2025-07-05T19:04:29.000Z (7 months ago)
- Last Synced: 2025-07-05T20:22:38.193Z (7 months ago)
- Topics: library, metaprogramming, nim-lang, nimble, python, python3
- Language: Nim
- Homepage: https://nimpylib.org/
- Size: 13.3 MB
- Stars: 41
- Watchers: 1
- Forks: 0
- Open Issues: 22
-
Metadata Files:
- Readme: README.md
- Changelog: changelogs/changelog_0_6_0.md
- Contributing: CONTRIBUTING.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
# NimPylib
[](https://github.com/nimpylib/pylib/actions/workflows/testC.yml)
[](https://github.com/nimpylib/pylib/actions/workflows/testJs.yml)
[](https://github.com/nimpylib/pylib/actions/workflows/docs.yml)

[](https://github.com/nimpylib/pylib/commits/)
> Write Python in Nim
Nimpylib is a collection of Python-like operators/functions and libraries as well as syntax sugars.
---
[Read Docs](https://nimpylib.github.io/pylib/)
|
[Lib Docs][]
|
[Wiki about History](https://github.com/nimpylib/pylib/wiki/History)
|
[Design Wiki](https://github.com/nimpylib/pylib/wiki/Design)
[Lib Docs]: https://nimpylib.github.io/pylib/Lib
## Why NimPyLib?
It helps you to:
- use much Python-like out-of-box API in Nim:
- with no need of any Python dependency (neither dynamic library nor binary).
- even handy for ones who don't use much Python but want more functions in Nim
- translate your Python program to Nim:
- gaining a right-away speed boot of even 700x
- no worry about binary distribution or packaging, just "compile once, distribute everywhere"
- rid of many annoying runtime-errors (which are turned to compile-time error)
- gain a better view into different behaviors between Python and Nim:
- `dynamically-typed` vs `statically-typed`
- unconvertible syntax from Python to Nim, e.g.
[`end` keyword](./doc/mustRewriteExtern/endKeyword.md),
[`not in` syntax](./doc/mustRewriteExtern/not-in.md)
### Backends
Thanks to Nim supporting multiply backends, pylib currently officially supports
to compile to C and JavaScript [^JS]. C++ and ObjC backends are currently not tested.
[^JS]: Some of features (listed
[here](./tests/skipJs.txt))
and Libs (listed
[here](./src/pylib/Lib/test/skipJs.txt))
is not available for JS backend yet.
## Demo
```nim
import pylib
from pylib/Lib/timeit import timeit
from pylib/Lib/time import sleep
from pylib/Lib/sys import nil # like python's `import sys`
from pylib/Lib/platform import nil # like python's `import platform`
import pylib/Lib/tempfile
# like python's `import tempfile; from tempfile import *`
# more python-stdlib in pylib/Lib/...
print 42 # print can be used with and without parenthesis too, like Python2.
# NOTE: from now on, the following is just valid Python3 code!
# only add the following to make it Python:
# import platform
# from timeit import timeit
# from time import sleep
# from tempfile import NamedTemporaryFile, TemporaryDirectory
print( f"{9.0} Hello {42} World {1 + 2}" ) # Python-like string interpolation
class O:
@staticmethod
def f():
print("O.f")
O.f()
def show_range_list():
python_like_range = range(0, -10, -2)
print(list(python_like_range)[1:-1]) # [-2, -4, -6]
show_range_list()
# Why using so many `def`s?
# as in `def`, you can write Nim more Python-like
# e.g. nondeclared assignment
# func definition
# typing is suppported and optional
def foo(a: int, b = 1, *args) -> int:
def add(a, b): return a + b # nesting
for i in args: print(i)
return add(a, b)
def show_literals():
ls = [1, 2] # if outside `def`, `ls` will be an Nim's `array`,
# which is fixed size and "pass by value"
ls_shallow = ls
ls.append(3)
assert len(ls_shallow) == 3
s = {"Rachel", "Zack"} # if outside `def`, `s` will be an Nim's `set`,
# which only supports small ordinal type as elements
s.add("Zack")
assert len(s) == 2
d = { # if outside `def`, `d` will be an Nim's `array[I, (K, V)]`,
# which even lacks `__getitem__` method
'S': "kaneki ken"
}
assert d['S'].title() == "Kaneki Ken" # if outside `def`,
# all double-quotation marked literals will be Nim's `string`,
# which is more like `bytearray`
# and single-quotation marked literals will be Nim's `char`,
# which repesents a single byte (ASCII character)
show_literals()
# python 3.12's type statement
type Number = float | int # which is originally supported by nim-lang itself, however ;)
for i in range(10):
# 0 1 2 3 4 5 6 7 8 9
print(i, endl=" ")
print("done!")
# Python-like variable unpacking
def show_unpack():
data = list(range(3, 15, 2))
(first, second, *rest, last) = data
assert (first + second + last) == (3 + 5 + 13)
show_unpack()
if (a := 6) > 5:
assert a == 6
print("a".center(9)) # " a "
print("" or "b") # "b"
print("a" or "b") # "a"
print(not "") # True
print("Hello,", input("What is your name? "), endl="\n~\n")
def show_divmod_and_unpack(integer_bytes):
(kilo, bite) = divmod(integer_bytes, 1_024)
(mega, kilo) = divmod(kilo, 1_024)
(giga, mega) = divmod(mega, 1_024)
show_divmod_and_unpack(2_313_354_324)
def lambda_closure(arg):
anno = lambda: "hello " + arg
return anno()
assert lambda_closure("world") == "hello world"
print(sys.platform) # "linux"
print(platform.machine) # "x86_64"
def allAny():
truty = all([True, True, False])
print(truty) # False
truty = any([True, True, False])
print(truty) # True
allAny()
def a_little_sleep():
"sleep around 0.001 milsecs."
# note Nim's os.sleep's unit is milsec,
# while Python's time.sleep's is second.
sleep(0.001)
assert timeit(a_little_sleep, number=1000) > 1.0
# Support for Python-like with statements
# All objects are closed at the end of the with statement
def test_open():
with open("some_file.txt", 'w') as file:
_ = file.write("hello world!")
with open("some_file.txt", 'r') as file:
while True:
s = file.readline()
if s == "": break
print(s)
test_open()
def show_tempfile():
with NamedTemporaryFile() as file:
_ = file.write(b"test!") # in binary mode
with TemporaryDirectory() as name:
print(name)
show_tempfile()
class Example(object): # Mimic simple Python "classes".
"""Example class with Python-ish Nim syntax!."""
start: int
stop: int
step: int
def init(self, start, stop, step=1):
self.start = start
self.stop = stop
self.step = step
def stopit(self, argument):
"""Example function with Python-ish Nim syntax."""
self.stop = argument
return self.stop
def exa():
e = Example(5, 3)
print(e.stopit(5))
exa()
```
Nimpylib heavily relies on Nim generics, converters, operator overloading, and even on concepts.
Check the [Examples folder](./examples/) for more examples.
Have more Macros or Templates for Python-like syntax, send [Pull Request](https://github.com/nimpylib/pylib/pulls).
## Installation
```shell
nimble install pylib
```
> If the installing is stuck with:
`Downloading https://github.com/Yardanico/nimpylib using git`
Please note your nimble package.json is outdated, and that old URL is 404 now [^oldUrl].
Run `nimble refresh` to fetch a newer `package.json`
Of course, a workaround is to install with full URL:
```shell
nimble install https://github.com/nimpylib/pylib
```
[^oldUrl]: see [wiki-history](https://github.com/nimpylib/pylib/wiki/History#the-newer-package-url) for details
Uninstall with `nimble uninstall pylib`.
## Requisites
- [Nim](https://nim-lang.org)
## Supported features
- [x] F-Strings `f"foo {variable} bar {1 + 2} baz"`
- [x] `str` `bytes` `bytearray` `list` `dict` `set` `frozenset()` with their methods
- [x] Python-like variable unpacking
- [x] Math with Float and Int mixed like Python.
- [x] `lambda:`
- [x] `class` Python-like OOP with methods and DocStrings (without multi-inheritance)
- [x] `@classmethod` and `@staticmethod`
- [x] `with open(fn, [, ...]):` Read, write, append, and `read()`, `seek()`, `tell()`, etc.
- [x] `super(...).method(...)`
- [x] `global/nonlocal` (with some limits)
- [x] `True` / `False`
- [x] `pass`
- [x] `del foo[x]`
- [x] `:=` Walrus Operator
- [x] `abs()`
- [x] `all()`
- [x] `any()`
- [x] `ascii()`
- [x] `bin()`
- [x] `chr()`
- [x] `complex()`
- [x] `divmod()`
- [x] `enumerate()`
- [x] `filter()`
- [x] `float()`
- [x] `format()`
- [x] `getattr()`
- [x] `hasattr()`
- [x] `hash()`
- [x] `hex()`
- [x] `id()`
- [x] `input()`
- [x] `int()`
- [x] `isinstance()`
- [x] `issubclass()`
- [x] `iter()`
- [x] `list()`
- [x] `map()`
- [x] `max()`
- [x] `min()`
- [x] `next()`
- [x] `oct()`
- [x] `ord()`
- [x] `open()` (though without close_fd, opener, errors)
- [x] `pow(base, exp, mod=None)`
- [x] `print("foo")` / `print "foo"` Python2 like
- [x] `range()`
- [x] `reversed(iterable)`
- [x] `round()`
- [x] `hasattr()`
- [x] `set()`, also named `pyset()` to distingish with `system.set`
- [x] `slice()`
- [x] `sorted(iterable)`
- [x] `str()`
- [x] `sum()`
- [x] `!=` and Python1 `<>`
- [x] `long()` Python2 like (deprecated)
- [x] `u"string here"` / `u'a'` Python2 like
- [x] `b"string here"` / `b'a'`
- [x] `zip(*iterables, strict=False)`
- [x] (WIP) standard libraries `math`, `random`, `datetime`, `os`, `tempfile`, `timeit`, ... (see [Lib Docs][] for all supported)
- [ ] `aiter` `anext` and `await` (yet `async def` is supported)
- More...
### Features cannot be implemented
However, due to Nim's AST astrict[^nimInvalidAST], a few syntaxes of Python cannot be implemented.
See [here](./doc/mustRewriteExtern/) for details and workaround.
[^nimInvalidAst]: Mostly because they cannot form valid AST in Nim.
## Other Python-like modules
- [serach in nimble](https://nimble.directory/search?query=python)
- [metacraft-labs/py2nim](https://github.com/metacraft-labs/py2nim): py2nim transpiler in Nim.
- [py2many/py2many](https://github.com/py2many/py2many): py2nim transpiler in Python.
- [juancarlospaco/cpython](https://github.com/juancarlospaco/cpython): invoke Python Standard Library API in Nim.
- [yglukhov/nimpy](https://github.com/yglukhov/nimpy): Python bridge in Nim.
## Tests
This is one snippest from version 0.9.5:
> as too much tests output is it,
and it's not suitable to list too much content in README,
the following demo
is not likely to be updated from then on.
```console
$ nimble test
[Suite] datetime
[OK] utcoffset
[OK] attrs
[OK] isoformat
[Suite] fromisoformat
[OK] if reversible
[Suite] timedelta
[OK] init
[OK] float init
[OK] normalize
[OK] stringify
[Suite] date
[OK] fromisocalendar
[OK] fromisocalendar_value_errors
[OK] ordinal_conversion
[OK] replace
[OK] strftime
[OK] ctime
[Suite] tzinfo
[OK] fromtimestamp
[Suite] gamma
[OK] gamma(-integer)
[Suite] ldexp
[Suite] sumprod
[OK] array
[OK] CPython:test_math.testSumProd
[Suite] constants
[OK] nan
[OK] inf
[Suite] classify
[OK] isinf
[OK] isfinite
[Suite] nextafter_ulp
[OK] nextafter
[OK] ulp
[Suite] ldexp
[OK] static
[OK] small
[OK] non-normal first arg
[OK] large second arg
[Suite] ErrnoAttributeTests
[OK] using_errorcode
[OK] touch, unlink, is_file
[OK] Lib/tempfile
[OK] Lib/time
[OK] Lib/timeit
[Suite] Lib/array
[OK] py3.13: 'w' Py_UCS4
[OK] bytes
[OK] cmp
[OK] byteswap
[Suite] os.path
[OK] if export right
[OK] getxtime
[Suite] Lib/os with no JS support
[OK] mkdir rmdir
[OK] open fdopen close
[OK] get,set_inheritable
[OK] getattr/set/has
[OK] bytearray
[Suite] bytes
[OK] getitem
[OK] meth
[OK] repr
[Suite] complex.__init__(str)
[OK] from str
[OK] negative_nans_from_string
[Suite] complex
[OK] init
[OK] literals
[OK] str
[OK] op
[Suite] complex.__repr__
[OK] (N+nanj)
[OK] real == 0.0
[Suite] complex.__pow__
[OK] CPython:test_complex.ComplexTest.test_pow
[OK] with small integer exponents
[OK] decorator
[OK] custom decorator
[OK] dict
[Suite] float.fromhex
[OK] literals
[OK] nans
[OK] some values
[OK] overflow
[OK] zeros and underflow
[OK] round-half-even
[Suite] float.fromhex and hex
[OK] roundtrip
[Suite] float
[OK] hex
[OK] test_nan_signs
[OK] is_integer
[OK] as_integer_ratio
[Suite] rewrite as py stmt
[OK] rewrite in `def`
[OK] rewrite raise
[OK] Floor division
[OK] int.{from,to}_bytes
[OK] io & with
[OK] bltin iters
[OK] iters as iterable
[OK] iter/next
[OK] random
[OK] Lib/string
[OK] list shallow
[OK] list.sort
[OK] list methods
[OK] Python-like types
[OK] divmod
[OK] pass
[OK] lambda
[OK] walrus operator
[OK] hex()
[OK] chr()
[OK] oct()
[OK] ord()
[OK] bin()
[OK] Modulo operations
[OK] int(x[, base])
[OK] float(str)
[OK] Range-like Nim procedure
[OK] str.format
[OK] str operations
[OK] str index
[OK] str methods
[OK] str.maketrans&translate
[OK] tonim macro
[OK] unpack macro
[OK] With statement
[OK] generics in func signature
[OK] generics in class's methods
[OK] set
PASS: tests/testaments/builtins/print.nim c ( 1.93 sec)
SKIP: tests/testaments/builtins/print.nim js
PASS: tests/testaments/builtins/print_ct.nim c ( 1.93 sec)
PASS: tests/testaments/builtins/zip_no_seq.nim c ( 1.96 sec)
PASS: tests/testaments/builtins/zip_more_args.nim c ( 0.65 sec)
PASS: tests/testaments/builtins/filter_toseq_deadloop.nim c ( 0.66 sec)
Used D:\software\scoop\shims\nim.exe to run the tests. Use --nim to override.
PASS: tests/testaments/pysugar/colonToSlice.nim c ( 2.75 sec)
SKIP: tests/testaments/pysugar/colonToSlice.nim js
PASS: tests/testaments/pysugar/strlitCat.nim c ( 1.92 sec)
SKIP: tests/testaments/pysugar/strlitCat.nim js
PASS: tests/testaments/pysugar/tripleStrTranslate.nim c ( 0.84 sec)
PASS: tests/testaments/pysugar/autoSetListDict.nim c ( 3.40 sec)
```