GitHub - nimpylib/nimpylib: "Write Python in Nim!" Python builtins/standard-Lib functions ported to Nim (original) (raw)
NimPylib
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.end keyword,not in syntax
Backends
Thanks to Nim supporting multiply backends, pylib currently officially supports to compile to C and JavaScript 1. C++ and ObjC backends are currently not tested.
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 defs?
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
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 2. Runnimble refreshto fetch a newerpackage.json
Of course, a workaround is to install with full URL:
nimble install https://github.com/nimpylib/pylib
Uninstall with nimble uninstall pylib.
Requisites
Supported features
- F-Strings
f"foo {variable} bar {1 + 2} baz" strbytesbytearraylistdictsetfrozenset()with their methods- Python-like variable unpacking
- Math with Float and Int mixed like Python.
lambda:classPython-like OOP with methods and DocStrings (without multi-inheritance)@classmethodand@staticmethodwith open(fn, [, ...]):Read, write, append, andread(),seek(),tell(), etc.super(...).method(...)global/nonlocal(with some limits)True/Falsepassdel foo[x]:=Walrus Operatorabs()all()any()ascii()bin()chr()complex()divmod()enumerate()filter()float()format()getattr()hasattr()hash()hex()id()input()int()isinstance()issubclass()iter()list()map()max()min()next()oct()ord()open()(though without close_fd, opener, errors)pow(base, exp, mod=None)print("foo")/print "foo"Python2 likerange()reversed(iterable)round()hasattr()set(), also namedpyset()to distingish withsystem.setslice()sorted(iterable)str()sum()!=and Python1<>long()Python2 like (deprecated)u"string here"/u'a'Python2 likeb"string here"/b'a'zip(*iterables, strict=False)- (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 astrict3, a few syntaxes of Python cannot be implemented.
See here for details and workaround.
Other Python-like modules
- serach in nimble
- metacraft-labs/py2nim: py2nim transpiler in Nim.
- py2many/py2many: py2nim transpiler in Python.
- juancarlospaco/cpython: invoke Python Standard Library API in Nim.
- 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.
$ 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)