Nimpylib
"Write Python in Nim!" Python builtins/standard-Lib functions ported to Nim
Install / Use
/learn @nimpylib/NimpylibREADME
NimPylib
<!-- [](https://github.com/nimpylib/pylib/issues) [](https://github.com/nimpylib/pylib/pulls)-->Write Python in Nim
Nimpylib is a collection of Python-like operators/functions and libraries as well as syntax sugars.
Read Docs | Lib Docs | Wiki about History | Design Wiki
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-typedvsstatically-typed- unconvertible syntax from Python to Nim, e.g.
endkeyword,not insyntax
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) and Libs (listed here) is not available for JS backend yet.
Demo
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
import pylib/Lib/os
# like python's `import tempfile; from tempfile import *`
# more python-stdlib in pylib/Lib/...
# from now on, we use `>` appended `#` to mean output
print 42 # print can be used with and without parenthesis too, like Python2.
#> 42
# 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
#> 9.0 Hello 42 World 3
class O:
@staticmethod
def f():
print("O.f")
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
# and all collection literals becomes Python's type
# 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
'a': "kaneki ken"
}
assert d['a'].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):
print(i, endl=" ")
print("done!")
#> 0 1 2 3 4 5 6 7 8 9 done!
# Python-like variable unpacking
def show_unpack():
data = list(range(3, 15, 2))
(first, second, *_, last) = data
assert (first + second + last) == (3 + 5 + 13)
show_unpack()
if (a := 6) > 5:
assert a == 6
print(repr("a".center(9))) #> ' a '
print("" or "b") #> b
print("a" or "b") #> a
print(not "") #> True
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"
# if on Linux:
#assert sys.platform == "linux"
# if on x86_64:
#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():
fn = "nimpylib_test_open_some_file.txt"
with open(fn, 'w') as file:
_ = file.write("hello world!")
with open(fn, 'r') as file:
while True:
s = file.readline()
if s == "": break
print(s)
os.remove(fn)
test_open() #> hello world!
def show_tempfile():
with NamedTemporaryFile() as file:
_ = file.write(b"test!") # in binary mode
s=""
with TemporaryDirectory() as name:
s = name
assert len(s) != 0
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() #> 5
Nimpylib heavily relies on Nim generics, converters, operator overloading, and even on concepts.
Check the Examples folder for more examples. Have more Macros or Templates for Python-like syntax, send Pull Request.
Installation
nimble install pylib
If the installing is stuck with:
Downloading https://github.com/Yardanico/nimpylib using gitPlease note your nimble package.json is outdated, and that old URL is 404 now [^oldUrl]. Runnimble refreshto fetch a newerpackage.json
Of course, a workaround is to install with full URL:
nimble install https://github.com/nimpylib/pylib
[^oldUrl]: see wiki-history for details
Uninstall with nimble uninstall pylib.
Requisites
Supported features
- [x] F-Strings
f"foo {variable} bar {1 + 2} baz" - [x]
strbytesbytearraylistdictsetfrozenset()with their methods - [x] Python-like variable unpacking
- [x] Math with Float and Int mixed like Python.
- [x]
lambda: - [x]
classPython-like OOP with methods and DocStrings (without multi-inheritance) - [x]
@classmethodand@staticmethod - [x]
with open(fn, [, ...]):Read, write, append, andread(),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 namedpyset()to distingish withsystem.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) - [ ]
aiteranextandawait(yetasync defis supported) - More...
Features cannot be implemented
However, due to Nim's AST astrict[^nimInvalidAST], a few syntaxes of Python cannot be implemented.
See here for details and workaround.
[^nimInvalidAst]: Mostly because th
