Skip to content

nimpylib/pylib

Repository files navigation

NimPylib

C Test JS Test Docs Commits

Write Python in Nim

Nimpylib is a collection of Python-like operators/functions and libraries as well as syntax sugars.

It helps you to:

  • use Python-like APIs in Nim, without any Python dependency
  • translate your Python program to Nim
  • gain a better view into different behaviors between Python and Nim.

Read Docs | Lib Docs | Wiki about History

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.

Usage

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 sys`
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.
pass str("This is a string.") # discard the string. Python doesn't allow this, however

# 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)) # [0, -2, -4, -6, -8]
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)

# 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)
  assert list(rest) == list([7, 9, 11])

show_unpack()

if (a := 6) > 5:
  assert a == 6

if (b := 42.0) > 5.0:
  assert b == 42.0

if (c := "hello") == "hello":
  assert c == "hello"

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)
  (tera, giga) = divmod(giga, 1_024)
  (peta, tera) = divmod(tera, 1_024)
  (exa, peta)  = divmod(peta, 1_024)
  (zetta, exa) = divmod(exa,  1_024)
  (yotta, zetta) = divmod(zetta, 1_024)
show_divmod_and_unpack(2_313_354_324)

let arg = "hello"
let anon = lambda: arg + " world"
assert anon() == "hello world"


print(sys.platform) # "linux"

print(platform.machine) # "amd64"

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

# Oop, the following is no longer Python....
let e = newExample(5, 3)
print(e.stopit(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 git Please note your nimble package.json is outdated, and that old URL is 404 now 2. Run nimble refresh to fetch a newer package.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"
  • str bytes bytearray list dict set frozenset() with their methods
  • Python-like variable unpacking
  • Math with Float and Int mixed like Python.
  • import antigravity
  • lambda:
  • class Python-like OOP with methods and DocStrings (without multi-inheritance)
  • @classmethod and @staticmethod
  • with open(fn, [, ...]): Read, write, append, and read(), seek(), tell(), etc.
  • super(...).method(...)
  • global/nonlocal (with some limits)
  • with tempfile.TemporaryDirectory(): Read, write, append, and file.read().
  • with tempfile.NamedTemporaryFile() as file: Read, write, append, and file.read().
  • timeit() with Nanoseconds precision
  • True / False
  • pass also can take and discard any arguments
  • del foo[x]
  • := Walrus Operator
  • abs()
  • 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 like
  • range()
  • reversed(iterable)
  • round()
  • hasattr()
  • set(), also named pyset() to distingish with system.set
  • slice()
  • sorted(iterable)
  • str()
  • sum()
  • != and Python1 <>
  • long() Python2 like
  • unicode() Python2 like
  • u"string here" / u'a' Python2 like
  • b"string here" / b'a'
  • zip(iterable1, iterable2)
  • More...

Other Python-like modules

Tests

$ 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] Lib/os with no JS support
  [OK] mkdir rmdir
  [OK] open fdopen close
  [OK] get,set_inheritable
[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

[Suite] os.path
  [OK] if export right
  [OK] getxtime
[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
[OK] rewrite in `def`
[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] set
[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

Footnotes

  1. Some of features (listed here) and Libs (listed here) is not available for JS backend yet.

  2. see wiki-history for details