diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index e573dfdf9..000000000 --- a/.gitattributes +++ /dev/null @@ -1,53 +0,0 @@ - - -[attr]lfTxt text eol=lf -# get rid of mess -[attr]normTxt lfTxt - -*.sh lfTxt - -/LICENSE normTxt -.gitignore normTxt - -*.nim normTxt -*.nimble normTxt -*.nims normTxt -*.py normTxt -*.c normTxt -*.yml normTxt -*.md normTxt -*.txt normTxt - -# Binary data types -*.aif binary -*.aifc binary -*.aiff binary -*.au binary -*.bmp binary -*.exe binary -*.icns binary -*.gif binary -*.ico binary -*.jpg binary -*.pck binary -*.png binary -*.psd binary -*.tar binary -*.wav binary -*.zip binary - -# Generated files -# https://github.com/github/linguist/blob/master/docs/overrides.md -# -# To always hide generated files in local diffs, mark them as binary: -# $ git config diff.generated.binary true -# -[attr]generated linguist-generated=true diff=generated - -/src/pylib/pystring/unicase/*.nim generated - - -# CRLF files -[attr]dos text eol=crlf - -*.bat dos diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index 7db3bc4b4..000000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,15 +0,0 @@ -# These are supported funding model platforms - -github: litlighilit # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] -#patreon: # Replace with a single Patreon username -open_collective: nimpylib # Replace with a single Open Collective username -#ko_fi: # Replace with a single Ko-fi username -#tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel -#community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry -#liberapay: # Replace with a single Liberapay username -#issuehunt: # Replace with a single IssueHunt username -#lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry -#polar: # Replace with a single Polar username -#buy_me_a_coffee: # Replace with a single Buy Me a Coffee username -#thanks_dev: # Replace with a single thanks.dev username -#custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml deleted file mode 100644 index 83d1146dd..000000000 --- a/.github/workflows/docs.yml +++ /dev/null @@ -1,53 +0,0 @@ -name: docs - -# yamllint disable-line rule:truthy -on: - push: - branches: - - master - workflow_dispatch: - -env: - nim-version: 'stable' - git-url-arg: --git.url:https://github.com/${{ github.repository }} --git.commit:master - deploy-dir: .gh-pages - lib-deploy-dir: .gh-pages/Lib -jobs: - docs: - runs-on: ubuntu-latest - permissions: - contents: write - steps: - - uses: actions/checkout@v4 - - name: Cache nimble - id: cache-nimble - uses: actions/cache@v4 - with: - path: ~/.nimble - key: ${{ runner.os }}-nimble - - uses: jiro4989/setup-nim-action@v1 - with: - nim-version: ${{ env.nim-version }} - - name: genDoc - run: nimble testDoc --index:on --project ${{ env.git-url-arg }} --outdir:${{ env.deploy-dir }} -d:homepage="${{ github.event.repository.homepage }}" - - name: genLibDoc - run: nimble testLibDoc ${{ env.git-url-arg }} --outdir:${{ env.lib-deploy-dir }} - - name: "Copy to index.html" - run: cp ${{ env.deploy-dir }}/${{ github.event.repository.name }}.html ${{ env.deploy-dir }}/index.html - - name: "CNAME" - run: | - cname=$(echo ${{ github.event.repository.homepage }} | grep -oP 'https?://\K[^/]+') - prefix="docs." - # py: if cname.startswith(prefix) - # bash: if [[ "${cname}" != $prefix* ]] - if [ ${cname##$prefix} = $cname ]; then - cname="${prefix}${cname}" - fi - echo -n $cname > ${{ env.deploy-dir }}/CNAME - # We must re-build CNAME as we use 'peaceiris/actions-gh-pages@v4', - # where the old dir (including CNAME) will be purged. - - name: Deploy documents - uses: peaceiris/actions-gh-pages@v4 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ${{ env.deploy-dir }} diff --git a/.github/workflows/testC.yml b/.github/workflows/testC.yml deleted file mode 100644 index 905fa9128..000000000 --- a/.github/workflows/testC.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: testC -on: - push: - branches-ignore: - - 'feat-*' - paths: - - 'src/**' - - './*.nimble' - - 'tests/**' - pull_request: -env: - nim-version: 'stable' -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Cache nimble - id: cache-nimble - uses: actions/cache@v4 - with: - path: ~/.nimble - key: ${{ runner.os }}-nimble - - uses: jiro4989/setup-nim-action@v1 - with: - nim-version: ${{ env.nim-version }} - - name: Test C backend - run: nimble testC - diff --git a/.github/workflows/testJs.yml b/.github/workflows/testJs.yml deleted file mode 100644 index 3a7f63b4b..000000000 --- a/.github/workflows/testJs.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: testJs -on: - push: - branches-ignore: - - 'feat-*' - paths: - - 'src/**' - - './*.nimble' - - 'tests/**' - pull_request: -env: - nim-version: 'stable' -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Cache nimble - id: cache-nimble - uses: actions/cache@v4 - with: - path: ~/.nimble - key: ${{ runner.os }}-nimble - - uses: jiro4989/setup-nim-action@v1 - with: - nim-version: ${{ env.nim-version }} - - name: Test JS backend - run: nimble testJs diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 02a77a9b4..000000000 --- a/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -/.vscode/ -nimcache/ -/docs/ -tester* -tempfiletest -/testresults/ -/tools/bin/ \ No newline at end of file diff --git a/tests/testaments/megatest.nim b/.nojekyll similarity index 100% rename from tests/testaments/megatest.nim rename to .nojekyll diff --git a/CNAME b/CNAME new file mode 100644 index 000000000..ca57c08dd --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +docs.nimpylib.org \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 3770481c5..000000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,17 +0,0 @@ -# Contributing to NimPylib - - -## Lib/ - -If in one library: `LIB`, one API returns str -or a variable is of str, consider firstly port a `n_LIB` -that is only in pure Nim (NimPylib-independent) if possible. - -For example, `n_time` for `time`, in which `string` shall be used. -Then let `LIB` import `n_LIB` and wrap around `string` to only return `PyStr`. - -So does for `seq` <-> `PyList`. - -In such a way, `n_LIB` is for Nim and `LIB` is for NimPylib. - - diff --git a/LICENSE b/LICENSE deleted file mode 100644 index d6cb8eb1b..000000000 --- a/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -MIT License - -Copyright (c) 2017-2023 Daniil Yarancev -Copyright (c) 2023-2025 litlighilit - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/Lib/_._/Python/config_read_env.html b/Lib/_._/Python/config_read_env.html new file mode 100644 index 000000000..e27f92864 --- /dev/null +++ b/Lib/_._/Python/config_read_env.html @@ -0,0 +1,173 @@ + + + + +
+ + +proc Py_SetLocaleFromEnv(category: cint): cstring {.discardable, ...raises: [], + tags: [], forbids: [].}
proc setenvOverwrite(key, val: string): bool {....raises: [], + tags: [WriteEnvEffect], forbids: [].}
proc Py_DecodeLocaleEx(arg: cstring; wstr: var ptr wchar_t; wlen: ptr csize_t; + reason: var cstring; current_locale: bool; + errors: Py_error_handler): int {....raises: [], tags: [], + forbids: [].}
Decode a byte string from the locale encoding.
+Use the strict error handler if 'surrogateescape' is zero. Use the surrogateescape error handler if 'surrogateescape' is non-zero: undecodable bytes are decoded as characters in range U+DC80..U+DCFF. If a byte sequence can be decoded as a surrogate character, escape the bytes using the surrogateescape error handler instead of decoding them.
+On success, return 0 and write the newly allocated wide character string into wstr (use PyMem_RawFree() to free the memory). If wlen is not NULL, write the number of wide characters excluding the null character into wlen.
+On memory allocation failure, return -1.
+On decoding error, return -2. Write the start of invalid byte sequence in the input string into wlen. If reason is not NULL, write the decoding error message into reason.
+Return -3 if the error handler 'errors' is not supported.
+Use the Py_EncodeLocaleEx() function to encode the character string back to a byte string.
+ + Source +Edit + +proc Py_GetLocaleEncoding(): string {....raises: [], tags: [], forbids: [].}
See also config_get_locale_encoding()
+ + Source +Edit + +Py_FORCE_UTF8_FS_ENCODING = false
Py_FORCE_UTF8_LOCALE = false
proc check_force_ascii(): bool {....raises: [], tags: [], forbids: [].}
proc Py_GetForceASCII(): bool {....raises: [], tags: [], forbids: [].}
proc Py_ResetForceASCII() {....raises: [], tags: [], forbids: [].}
template force_ascii(): untyped
Py_error_handler = enum + Py_ERROR_UNKNOWN = "unknown", Py_ERROR_STRICT = "strict", + Py_ERROR_SURROGATEESCAPE = "surrogateescape", Py_ERROR_REPLACE = "replace", + Py_ERROR_IGNORE = "ignore", Py_ERROR_BACKSLASHREPLACE = "backslashreplace", + Py_ERROR_SURROGATEPASS = "surrogatepass", + Py_ERROR_XMLCHARREFREPLACE = "xmlcharrefreplace", Py_ERROR_OTHER = "other"
proc Py_GetErrorHandler(errors: string): Py_error_handler {....raises: [], + tags: [], forbids: [].}
proc PyOS_getsig(sig: cint): CSigHandler {....raises: [], tags: [], forbids: [].}
proc PyOS_setsig(sig: cint; handler: CSigHandler): CSigHandler {....raises: [], + tags: [], forbids: [].}
XXX: posix/winlean's a2 cannot be nil (a var Sigaction)
+ITIMER_PROF {.importc, header: "<sys/time.h>".}: cint
ITIMER_REAL {.importc, header: "<sys/time.h>".}: cint
ITIMER_VIRTUAL {.importc, header: "<sys/time.h>".}: cint
HAVE_BROKEN_PTHREAD_SIGMASK = false
HAVE_SIGSET_T = true
PYPTHREAD_SIGMASK = true
proc c_signal(a1: cint; a2: CSigHandler): CSigHandler {.importc: "signal", + header: "<signal.h>", ...raises: [], tags: [], forbids: [].}
CSigHandler = proc (signalnum: cint) {.noconv.}
NimSigHandler = proc (signalnum: int) {.nimcall.}
PySigHandler = proc (signalnum: int; frame: PFrame) {.closure.}
proc PyDeadline_Get(deadline: PyTime): PyTime {....raises: [], tags: [TimeEffect], + forbids: [].}
proc PyDeadline_Init(timeout: PyTime): PyTime {....raises: [], tags: [TimeEffect], + forbids: [].}
func round(x: float; round: PyTime_round_t): float {....raises: [], tags: [], + forbids: [].}
func round_half_even(x: float): float {....raises: [], tags: [], forbids: [].}
PY_TIME_T_MAX = 9223372036854775807'i64
PY_TIME_T_MIN = -9223372036854775808'i64
SIZEOF_TIME_T = 8
PyTime_round_t = enum + prFLoor, prCeiling, prHalfEven, prRoundUp
Mask to quickly check whether a C 'size_t' contains a non-ASCII, UTF8-encoded char.10xxxxxx
+ALIGNOF_SIZE_T = 8
ASCII_CHAR_MASK = 0x80808080'u
func getMaxChar[C](): C
proc utf8_decode[STRINGLIB_CHAR](inptr: var (cstring | ptr char); + end: (cstring | ptr char); + dest: ptr STRINGLIB_CHAR; + outpos: var Py_ssize_t): Py_UCS4
template IS_CONTINUATION_BYTE(ch: untyped): untyped
template Py_IS_ALIGNED(p: cstring | ptr; a: typeof(ALIGNOF_SIZE_T)): bool
MaxWStrLen = 2305843009213693951
proc Py_DecodeUTF8Ex(orig_s: cstring; size: csize_t; wstr: var ptr wchar_t; + wlen: ptr csize_t; reason: var cstring; + errors: Py_error_handler): int {....raises: [], tags: [], + forbids: [].}
UTF-8 decoder: use surrogateescape error handler if 'surrogateescape' is non-zero, use strict error handler otherwise.
+On success, write a pointer to a newly allocated wide character string into wstr (use PyMem_RawFree() to free the memory) and write the output length (in number of wchar_t units) into wlen (if wlen is set).
+On memory allocation failure, return -1.
+On decoding error (if surrogateescape is zero), return -2. If wlen is non-NULL, write the start of the illegal byte sequence into wlen. If reason is not NULL, write the decoding error message into reason.
+ + Source +Edit + +DECODE_ERROR = -1
HAVE_MBRTOWC = true
INCOMPLETE_CHARACTER = -2
MAX_UNICODE_val = 0x0010FFFF
proc is_valid_wide_char(ch: wchar_t): bool {....raises: [], tags: [], forbids: [].}
proc Py_mbrtowc(wc: PWc; src: cstring; n: csize_t; mbs: var mbstate_t): csize_t
proc Py_mbstowcs(dest: ptr wchar_t; src: cstring; n: csize_t): csize_t {. + ...raises: [], tags: [], forbids: [].}
template allocWcharArr[I](n: I): ptr wchar_t
template deallocWcArr(p: ptr wchar_t)
template Py_UNICODE_IS_SURROGATE(ch: wchar_t): bool
func pyasciiImpl(us: string): string {....raises: [], tags: [], forbids: [].}
Python's ascii impl
+Note this assumes us is already processed by repr i.e., this only escape the non-ASCII characters in us using x, u, or U escapes and doesn't touch ASCII characters.
+ + Source +Edit + +PyDictItemView[K; V] = object of PyDictView + mapping*: PyDict[K, V]
PyDictKeyView[T] = object of PyDictView + mapping*: PyDict[T, auto]
PyDictValueView[T] = object of PyDictView + mapping*: PyDict[auto, T]
PyDictView = object of RootObj
SomePyDictView = PyDictKeyView | PyDictValueView | PyDictItemView
SomeSinglePyDictView[T] = PyDictValueView[T] | PyDictKeyView[T]
func contains[K, V](t: PyDictItemView[K, V]; x: (K, V)): bool
func contains[T](t: PyDictKeyView[T]; x: T): bool
func contains[T](t: PyDictValueView[T]; x: T): bool
func items[K, V](self: PyDict[K, V]): PyDictItemView[K, V]
func iter[K, V](self: PyDict[K, V]): PyIterator[K]
func keys[K, V](self: PyDict[K, V]): PyDictKeyView[K]
proc len(view: SomePyDictView): int
func setdefault[K, V](self: PyDict[K, V]; key: K; default = V.default)
func values[K, V](self: PyDict[K, V]): PyDictValueView[V]
iterator iter[K, V](self: PyDict[K, V]): K
Example:
+let d = dict(a=1) +for i in iter(d): + assert i == "a" +for i in d: + assert i[0] == "a" and i[1] == 1+ Source +Edit + +
template `$`(self: PyDictItemView): string
template `$`(self: PyDictKeyView): string
template `$`(self: PyDictValueView): string
template items(view: SomePyDictView): untyped
template iter(view: SomePyDictView): untyped
template repr(self: PyDictItemView): string {.dirty.}
template repr(self: PyDictKeyView): string {.dirty.}
template repr(self: PyDictValueView): string {.dirty.}
func emptyPyDict[K, V](): PyDict[K, V]
proc getOrDefault[A, B](t: PyDict[A, B]; key: A): B
func toNimTable[K, V](self: PyDict[K, V]): var OrderedTable[K, V]
template newPyDictImpl[K, V](x: int): untyped {. + ...deprecated: "use newPyDict, to be removed since 0.10".}
template newPyDictImpl[K, V](x: openArray[(K, V)] = []): untyped {. + ...deprecated: "use newPyDict, to be removed since 0.10".}
builtins.iter
+PyIterator[T] = ref object
func iter[T](x: Iterable[T]): PyIterator[T]
func iter[T](x: Iterator[T]): PyIterator[T]
func newPyIterator[T](it: iterator (): T): PyIterator[T]
proc next[T](self: PyIterator[T]): T
proc nextImpl[T](self: PyIterator[T]): Option[T] {.inline.}
proc nextImpl[T](self: PyIterator[T]; res: var T): bool {.inline.}
iterator items[T](self: PyIterator[T]): T
Some iterable in builtins
+XXX: For JS backend: Currently due to Nim's inner buys, using of some iterable functions in this modules may result in Error: ...:
+For details, trace:
+PreBreakCb = proc (i: NimNode): NimNode {.closure.}
preferredGenIterResName {.strdefine.} = "gen_iter_res"
proc addEachIter(loopBody: NimNode; nIt: int; itors, res: NimNode; + preBreakCb: PreBreakCb = noopPreBreakCb) {....raises: [Exception], + tags: [RootEffect], forbids: [].}
proc addLoopEach(loopBody: NimNode; parent: NimNode; + iterables: NimNode | seq[NimNode]; + res = ident preferredGenIterResName; + preBreakCb: PreBreakCb = noopPreBreakCb): NimNode {.discardable.}
proc addResDecl(body: NimNode; iterables: NimNode | seq[NimNode]; + res = ident preferredGenIterResName; + iters = genSym(nskLet, "iters")): NimNode {.discardable.}
proc newNullaryLambdaIter(body: NimNode; resType = ident"auto"): NimNode {. + ...raises: [], tags: [], forbids: [].}
func noInitVarDecl(name, Type: NimNode): NimNode {....raises: [], tags: [], + forbids: [].}
proc mapIterBodyImpl(f: NimNode; iterables: NimNode; res = genSym(nskVar, "res")): NimNode {. + ...raises: [Exception], tags: [RootEffect], forbids: [].}
func raiseZipBound(ordLonger: int) {.inline, ...raises: [ValueError], tags: [], + forbids: [].}
proc zipIterBodyImpl(iterables: NimNode | seq[NimNode]; strict: NimNode): NimNode
Python's list with its methods and sorted buitin
+LIMIT: slice literal is not supported. ls[1:3] has to be rewritten as ls[1..2]
+ +converter nimArrayAsList[T; I](arr: array[I, T]): PyList[T]
func newPyList(a: sink openArray[char]): PyList[char] {.inline, ...raises: [], + tags: [], forbids: [].}
func newPyList(a: sink openArray[float]): PyList[float] {.inline, ...raises: [], + tags: [], forbids: [].}
func newPyListOfCap[T](cap = 0): PyList[T] {.inline.}
func newPyListOfStr(a: openArray[string]): PyList[PyStr] {.inline, ...raises: [], + tags: [], forbids: [].}
template checkLenientOps(A, B)
template genDollarRepr(Coll; start, stop: char | string; linear = false; + useIter = true) {.dirty.}
template genDollarRepr(Coll; start, stop: char | string; strProc: typed; + linear = false; useIter = true) {.dirty.}
template strIterImpl(it: typed{atom}; strProc; start, stop: char | string; + linear = false; useIter = true): string
template strIterImpl(itExpr: typed{~atom}; strProc; start, stop: char | string; + linear = false; useIter = true): string
func pyreprbImpl(s: string): string {....raises: [], tags: [], forbids: [].}
func pyreprImpl(s: string; escape127: static[bool] = false): string
Python's repr but returns Nim's string.
+nim's Escape Char feature can be enabled via -d:useNimCharEsc, in which 'e' (i.e.'x1B' in Nim) will be replaced by "\e"
+ +Example:
+# NOTE: string literal's `repr` is `system.repr`, as following. +assert repr("\"") == "\"\\\"\"" # string literal of "\"" +# use pyrepr for any StringLike and returns a PyStr +assert pyreprImpl("\"") == "'\"'"+ Source +Edit + +
set and its methods. +
set[T] is still for system.set[T], with its restriction of only allowing small ordinal as elements. PySet[T] is used to minic Python's.
+ +Something like {1,2} shall be rewritten as pyset([1,2]), please note either pyset((1,2)) or pyset({1,2}) doesn't mean the same.
+ +proc `-`[H](self: PyFrozenSet[H]; o: SomePySet[H]): PyFrozenSet[H]
proc `-`[H](self: PySet[H]; o: PyFrozenSet[H]): PyFrozenSet[H]
proc difference[H; Self: SomePySet[H]; S: not PySet[H]](self: Self; s: S): Self
proc difference[H; Self: SomePySet[H]; S](self: Self; s1: auto; s2: auto; + x: varargs[S]): Self
proc difference[H](self, o: PySet[H]): PySet[H]
proc difference[H](self: PyFrozenSet[H]; o: SomePySet[H]): PyFrozenSet[H]
proc difference[H](self: PySet[H]; o: PyFrozenSet[H]): PyFrozenSet[H]
proc difference_update[H; I: Iterable[H]](self: var SomePySet[H]; i: I)
proc frozenset[H](): PyFrozenSet[H]
proc frozenset[H](arr: openArray[H]): PyFrozenSet[H]
proc frozenset[H](it: Iterable[H]): PyFrozenSet[H]
proc frozenset[H](s: HashSet[H]): PyFrozenSet[H]
proc frozenset[H](s: SomePySet[H]): PyFrozenSet[H]
proc intersection[H; Self: SomePySet[H]; S: not PySet[H]](self: Self; s: S): Self
proc intersection[H; Self: SomePySet[H]; S](self: Self; s1: auto; s2: auto; + x: varargs[S]): Self
proc intersection[H](self, o: PySet[H]): PySet[H]
proc intersection[H](self: PyFrozenSet[H]; o: SomePySet[H]): PyFrozenSet[H]
proc intersection[H](self: PySet[H]; o: PyFrozenSet[H]): PyFrozenSet[H]
proc intersection_update[H; I: Iterable[H]](self: var SomePySet[H]; i: I)
func isdisjoint[H, S](self: SomePySet[H]; s: S): bool
proc issuperset[H, S](self, o: SomePySet[H]; s: S): bool
proc symmetric_difference[H; Self: SomePySet[H]; S: not PySet[H]](self: Self; + s: S): Self
proc symmetric_difference[H; Self: SomePySet[H]; S](self: Self; s1: auto; + s2: auto; x: varargs[S]): Self
proc symmetric_difference[H](self, o: PySet[H]): PySet[H]
proc symmetric_difference[H](self: PyFrozenSet[H]; o: SomePySet[H]): PyFrozenSet[ + H]
proc symmetric_difference[H](self: PySet[H]; o: PyFrozenSet[H]): PyFrozenSet[H]
proc union[H; Self: SomePySet[H]; S: not PySet[H]](self: Self; s: S): Self
proc union[H; Self: SomePySet[H]; S](self: Self; s1: auto; s2: auto; + x: varargs[S]): Self
proc union[H](self: PyFrozenSet[H]; o: SomePySet[H]): PyFrozenSet[H]
proc union[H](self: PySet[H]; o: PyFrozenSet[H]): PyFrozenSet[H]
PyFrozenSet[H] = frozenset[H]
func hash[H](self: PyFrozenSet[H]): int
func newPyFrozenSet[H](h: HashSet[H]): PyFrozenSet[H]
func newPyFrozenSet[H](initialSize = defaultInitialSize): PyFrozenSet[H]
template `$`(self: PyFrozenSet): string
+
ref pep of `Coroutines with async and await syntax`, Future-like object is just an alias of Awaitable
+V = 1 +async def f(): + return V + +c: Coroutine[None, None, int] = f() + +try: c.send(None) +except StopIteraion as s: assert V == s.value + +try: c.send(None) +except RuntimeError as e: assert str(e) == "cannot reuse already awaited coroutine" + +# Also: V == await f()+
pep for Asynchronous Generators
+ +V = 1 +async def f(): yield V +ag = f() + +ag_asend_obj = ag.asend(None) # or `anext(ag)` +try: ag_asend_obj.send(None) +except StopIteration as s: assert V == s.value + + +ag_asend_obj = ag.asend(None) # or `anext(ag, defval)` if wanting +# the next `send` raises `StopIteration` and its value to be `defval` + +try: ag_asend_obj.send(None) +except StopAsyncIteration: pass # iteration end + ++
for ag_asend_obj, ref link of PyAsyncGenASend:
++PyAsyncGenASend is a coroutine-like object...
+ +PyAsyncGenAThrow is very similar to PyAsyncGenASend. The only difference is that PyAsyncGenAThrow.send(), when called first time, throws an exception into the parent agen object (instead of pushing a value into it.)
AsyncGenerator[Yield; Send] = concept selfof AsyncIterator[Yield] + self.asend(Send) is Awaitable[Yield] + self.athrow(CatchableError) is Awaitable[void]
AsyncIterable[T] = concept self + aiter(self) is AsyncIterator[T]
AsyncIterator[T] = concept selfof AsyncIterable[T] + anext(self) is Awaitable[T]
proc aclose(self: AsyncGenerator): owned(Future[void]) {....stackTrace: false.}
proc anext[T](self: AsyncGenerator[T]): Awaitable[T] {.inline.}
proc anext[T](self: AsyncGenerator[T]; default: T): Awaitable[T] {.inline.}
Mapping[K; V] = concept selfof Collection[K] + K + V + self[K] is V
MutableSequence[T] = concept selfof Sequence[T] + T + self[int] = T + self.delitem(int) + self.insert(int, T) ## insert item before index
Sequence[T] = concept selfof Collection[T] + T + self[int] is T
func append[T](ms: MutableSequence[T]; x: T)
func clear(ms: MutableSequence)
func extend[T](ms: MutableSequence[T]; it: Iterable[T])
func pop[T](ms: MutableSequence[T]; index = -1): T
func remove[T](ms: MutableSequence[T]; x: T)
func reverse(ms: MutableSequence)
Generator[YieldType; SendType; ReturnType] = concept selfof Iterator[YieldType] + try: + self.send(SendType) is YieldType + except StopIterationT[ReturnType]: + discard + self.throw(CatchableError)
CanIOOpenT[T] = int | PathLike[T]
proc `$`(p: CanIOOpenT): string
template mapPathLike[T](nexpr): T
template mapPathLike[T](s: PathLike[T]; nimProc): T
As Python's MutableSequence does not mixin these we place them here.
+template bodySetItem(Arr) {.dirty.}
template genDelItem(Arr) {.dirty.}
template genGenericSetItem(Arr, Arr2) {.dirty.}
template genNonGenericSetItem(Arr, Arr2) {.dirty.}
JsBigInt64Option = true
NimVersionTuple = (2, 2, 4)
CompileBackend {.pure.} = enum + c = "C", cpp = "C++", objc = "Object-C", js = "JavaScript", + nimscript = "NimScript"
template noBackends(backends: untyped; def)
template noJsBackend(def)
template noNimsBackend(def)
template noWeirdBackend(def)
proc encodings.normalize_encoding(encoding: string): string {....raises: [], + tags: [], forbids: [].}
Normalize an encoding name.
+Normalization works as follows: all non-alphanumeric characters except the dot used for Python package names are collapsed and replaced with a single underscore, e.g. ' -;#' becomes '_'. Leading and trailing underscores are removed.
+Note that encoding names should be ASCII only.
+ + Source +Edit + +proc Py_normalize_encoding(encoding: string): string {....raises: [], tags: [], + forbids: [].}
func inspect.cleandoc(doc: openArray[char]): string {....raises: [], tags: [], + forbids: [].}
Clean up indentation from docstrings.
+Any whitespace that can be uniformly removed from the second line onwards is removed.
+compiled. no need to keep the leading adn tailing blank lines like Python/compile.c: _PyCompile_CleanDoc does.
+ + Source +Edit + +Macros to protect CRT calls against instant termination when passed an invalid parameter (bpo-23524). IPH stands for Invalid Parameter Handler.
+CPython/Include/internal/pycore_fileutils.h
+ +template with_Py_SUPPRESS_IPH(body)
template platformAvail(platform; def)
Pragma on procs to generate doc of sth like Availability: Windows.
+Currently, platform must be something that can be put within defined.
+ + Source +Edit + +template platformAvailWhen(platform; cond: bool; def)
template platformNoJs(def)
func `==`(b: bool; self: PyBool): PyBool {.borrow, ...raises: [], tags: [], + forbids: [].}
func `and`(b: bool; self: PyBool): PyBool {.borrow, ...raises: [], tags: [], + forbids: [].}
func `and`(self: PyBool; b: bool): PyBool {.borrow, ...raises: [], tags: [], + forbids: [].}
func `or`(b: bool; self: PyBool): PyBool {.borrow, ...raises: [], tags: [], + forbids: [].}
func `or`(self: PyBool; b: bool): PyBool {.borrow, ...raises: [], tags: [], + forbids: [].}
converter pybool(x: bool): PyBool {....raises: [], tags: [], forbids: [].}
converter pybool[T](x: T): PyBool
Converts any to PyBool
+NOTE: In Nim, "implicit converter chain is not support". (See manual.html). Therefore any type can be implicitly converted to PyBool, not bool, which, however, is desired, as if any is convertible to bool, then there'll be ## compile-error for repr(<list>)
+ + Source +Edit + +func `+`(o: char; self: PyBytes): PyBytes {....raises: [], tags: [], forbids: [].}
func `+`(o: string; self: PyBytes): PyBytes {....raises: [], tags: [], forbids: [].}
func `+`(self: PyBytes; o: char): PyBytes {....raises: [], tags: [], forbids: [].}
func `[]`(self: PyBytes; i: HSlice[int, BackwardsIndex]): PyBytes {....raises: [], + tags: [], forbids: [].}
func bytes(nLen: int): PyBytes {....raises: [], tags: [], forbids: [].}
func bytes(s: openArray[char | uint8]): PyBytes
EXT.
+Python has no concept of openArray
+ + Source +Edit + +func bytes(s: sink string): PyBytes {.inline, ...raises: [], tags: [], forbids: [].}
func bytes(self: PyBytes): PyBytes {....raises: [], tags: [], forbids: [].}
func getCharPtr(self: PyBytes; i: Natural | BackwardsIndex): ptr char
converter toNimString(self: PyBytes): string {....raises: [], tags: [], forbids: [].}
SYS_getrandom {.importc, header: "<sys/syscall.h>".}: clong
have_getrandom = true
have_getrandom_syscall = true
py_getrandom = true
HAVE_LCHMOD = false
HAVEfchmod = true
HAVEfchmodat = true
HAVEfchmodatRUNTIME = true
--- HAVE_PY_SET_53BIT_PRECISION macro ------------------------------------Inline assembly for getting and setting the 387 FPU control word on GCC/x86.ifdef _Py_MEMORY_SANITIZERendif
+ +DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754 = false
DOUBLE_IS_BIG_ENDIAN_IEEE754 = false
DOUBLE_IS_LITTLE_ENDIAN_IEEE754 = true
HAVE_GCC_ASM_FOR_MC68881 = false
HAVE_GCC_ASM_FOR_X87 = true
X87_double_rounding = false
template HAVE_PY_SET_53BIT_PRECISION(): bool
template Py_SET_53BIT_PRECISION_END()
template Py_SET_53BIT_PRECISION_HEADER() {.dirty.}
template Py_SET_53BIT_PRECISION_START()
AT_REMOVEDIR {.importc, header: "<fcntl.h>".}: cint
AT_SYMLINK_NOFOLLOW = 256
DEFAULT_DIR_FD = -100
HAVE_FTRUNCATE = true
HAVE_OPENAT = true
HAVEfdopendir = true
HAVEfdopendirRUNTIME = true
HAVEunlinkat = true
HAVEunlinkatRUNTIME = true
O_DIRECTORY = 65536'i32
O_NOFOLLOW = 131072'i32
ref https://nim-lang.org/docs/manual.html#types-preminusdefined-floatingminuspoint-types Nim's float XX shall always follows IEEE754 --- _PY_SHORT_FLOAT_REPR macro -------------------------------------------
+WORDS_BIGENDIAN = false
WORDS_LITTLEENDIAN = true
HAVE_GETPAGESIZE = true
HAVE_PRLIMIT = true
HAVE_SYSCONF_PAGE_SIZE = false
RUSAGE_BOTH = -9223372036854775808
RUSAGE_THREAD = 1
SIZEOF_RLIMIT_T = 8
HAVEgetitimer = true
HAVEpthread_kill = true
HAVEpthread_sigmask = true
HAVEsetitimer = true
HAVEsigaction = true
HAVEsigfillset = true
HAVEsiginterrupt = true
HAVEsigpending = true
HAVEsigtimedwait = true
HAVEsigwait = true
HAVEsigwaitinfo = true
HAVEstrsignal = true
HAVEfstatat = true
HAVEfstatatRUNTIME = true
macro AC_CHECK_FUNCS(xs: varargs[untyped]): untyped
macro AC_CHECK_HEADER(header)
macro AC_CHECK_HEADER_THEN_FUNCS(header; functions)
macro AC_CHECK_HEADERS(xs: varargs[untyped]): untyped
macro from_c_int_expr(cExpr: static[string]; defval: int): int
macro from_c_int_underlined(variable: static[string]; defval: int): int
template AC_CHECK_FUNC(function)
template AC_CHECK_FUNC(res, function)
template AC_CHECK_HEADER(res, header)
template AC_LINK_IFELSE(variable, defval, code)
template AC_RUN_IFELSE(variable, defval, code)
template AX_C_FLOAT_WORDS_BIGENDIAN(id; doIfTrue, doIfFalse, doIfUnknown) {. + dirty.}
template AX_C_FLOAT_WORDS_BIGENDIAN_def(defIfTrue, defIfFalse, doIfUnknown)
template from_c_int(variable; defval: int; precode): int
template from_c_int(variable; defvar: int): int
template from_c_int(variable; includeFile: static[string]; defval = low(int)): int
ArithmeticError = object of CatchableError
ZeroDivisionError = object of ArithmeticError
See CPython's Objects/exceptions.c
+OSError_new(a.k.a. OSError.__new__) will returns a subclass of OSError, via lookup in state->errnomap, which is initialized by _PyExc_InitState,
+where key-value pairs are inserted via ADD_ERRNO macro.
+ +proc raiseErrno(errno = getErrno()) {....raises: [PyOSError], tags: [], forbids: [].}
proc raiseErrnoT[T: PyOSError](errno = getErrno())
proc raiseErrnoWithPath[T](p: PathLike[T]; errno = getErrno())
func raiseExcWithPath(fp: PathLike; exc: typedesc; err: OSErrorCode; + additionalInfo: string)
proc raiseExcWithPath(fp: PathLike; exc: typedesc; err: OSErrorCode; + osErrorMsgCb: proc = osErrorMsg)
proc raiseExcWithPath(p: PathLike) {.sideEffect.}
proc raiseExcWithPath(p: PathLike; errCode: OSErrorCode) {.sideEffect.}
proc raiseExcWithPath2(src, dst: PathLike)
template noWeirdTarget(def)
template osErrorMsgWithPath(fp: PathLike; err: OSErrorCode): string
template osErrorMsgWithPath(fp: PathLike; err: OSErrorCode; osErrorMsgCb): string
proc default_oserror(): ref PyOSError {.nimcall, noSideEffect, ...raises: [], + tags: [], forbids: [].}
template decl_c_int(name, includeFile; defval)
proc BlockingIOError(myerrno: cint; strerr: string; filename = 0; + winerror: cint = 0; filename2 = ""): ref PyOSError {. + ...raises: [], tags: [], forbids: [].}
proc BlockingIOError(strerr: string = ""): ref PyOSError {....raises: [], tags: [], + forbids: [].}
proc newBlockingIOError(myerrno: cint; strerr: string; filename = 0; + winerror: cint = 0; filename2 = ""): ref PyOSError {. + ...raises: [], tags: [], forbids: [].}
proc newBlockingIOError(strerr: string = ""): ref PyOSError {....raises: [], + tags: [], forbids: [].}
proc newPyOSError(myerrno: cint; strerr: string; filename = ""; + winerror: cint = 0; filename2 = ""): ref PyOSError {. + ...raises: [], tags: [], forbids: [].}
proc newPyOSError(strerr: string = ""): ref PyOSError {....raises: [], tags: [], + forbids: [].}
Where a function has a single filename, such as open() or some of the os module functions, PyErr_SetFromErrnoWithFilename() is called, giving a third argument which is the filename. But, so that old code using in-place unpacking doesn't break, e.g.:
+except OSError, (errno, strerror):
+we hack args so that it only contains two items. This also means we need our own __str__() which prints out the filename when it was supplied.
+(If a function has two filenames, such as rename(), symlink(), or copy(), PyErr_SetFromErrnoWithFilenameObjects() is called, which allows passing in a second filename.)
+ +OSErrorArgs[third] = tuple[errno: cint, strerror: string, filename: third, + winerror: cint, filename2: string]
proc init[E: PyOSError](self: ref E; args: OSErrorArgs)
proc OSError_new[E: PyOSError](myerrno: cint; strerr: string; + filename: string | int = ""; winerror: cint = 0; + filename2 = ""; fillMsg: static[bool] = true): ref PyOSError
template oserror_use_init[E: PyOSError](self): bool
When __init__ is defined in an OSError subclass, we want any extraneous argument to __new__ to be ignored. The only reasonable solution, given __new__ takes a variable number of arguments, is to defer arg parsing and initialization to __init__.
+But when __new__ is overridden as well, it should call our __new__ with the right arguments.
+(see http://bugs.python.org/issue12555#msg148829 )
+ + Source +Edit + +BlockingIOError = object of oserror_decl.PyOSError
BrokenPipeError = object of ConnectionError
ChildProcessError = object of oserror_decl.PyOSError
ConnectionAbortedError = object of ConnectionError
ConnectionError = object of oserror_decl.PyOSError
ConnectionRefusedError = object of ConnectionError
ConnectionResetError = object of ConnectionError
FileExistsError = object of oserror_decl.PyOSError
FileNotFoundError = object of oserror_decl.PyOSError
InterruptedError = object of oserror_decl.PyOSError
IsADirectoryError = object of oserror_decl.PyOSError
NotADirectoryError = object of oserror_decl.PyOSError
PermissionError = object of oserror_decl.PyOSError
ProcessLookupError = object of oserror_decl.PyOSError
TimeoutError = object of oserror_decl.PyOSError
KeyboardInterrupt = object of CatchableError
NotImplementedError = object of RuntimeError
RuntimeError = object of CatchableError
GeneratorExit = object of CatchableError
StopAsyncIteration = object of CatchableError
StopIteration = StopIterationT[NoneType]
StopIterationT[T] = object of CatchableError + value*: T ## generator return value
func `$`(self: StopIteration): string {....raises: [], tags: [], forbids: [].}
func `$`(self: StopIterationT): string
func msg(self: StopIteration): string {....raises: [], tags: [], forbids: [].}
func msg(self: StopIterationT): string
func newStopIteration(): ref StopIteration {....raises: [], tags: [], forbids: [].}
func newStopIteration[T](value: T): ref StopIterationT[T]
UnicodeDecodeError = object of UnicodeError
UnicodeError = object of ValueError
func newUnicodeDecodeError(codec: string; src: char; start, stop: int; + reason: string): ref UnicodeDecodeError {. + ...raises: [ValueError], tags: [], forbids: [].}
func newUnicodeDecodeError(codec: string; src: string; start, stop: int; + reason: string): ref UnicodeDecodeError {. + ...raises: [ValueError], tags: [], forbids: [].}
unicodeSpaces = [9'i32, 10'i32, 11'i32, 12'i32, 13'i32, 28'i32, 29'i32, 30'i32, + 31'i32, 32'i32, 133'i32, 160'i32, 5760'i32, 8192'i32, 8193'i32, + 8194'i32, 8195'i32, 8196'i32, 8197'i32, 8198'i32, 8199'i32, + 8200'i32, 8201'i32, 8202'i32, 8232'i32, 8233'i32, 8239'i32, + 8287'i32, 12288'i32]
f-string
+a string literal with a prefix of fr, Fr, rf of Rf behaves as if with a prefix of strformat.fmt.
+and f"xxx" is different, where the escaped literals in string will be interpreted.
+ +Example:
+import src/pylib/pystring/fstring +assert fr"\n" == "\\n" +assert f"\n" == "\n" + +let s = "asd" + +assert f"[{s}]" == "[asd]" +assert not compiles(fr s)+
template f(s: string{lit}): PyStr
Python F-String.
+Not the same as Nim's fmt"xxx" as that's equal to fmt r"xxx", a.k.a fr"xx" in Python
+Any escape-translation error is reported at compile-time, with information of filename and line number
+ +\Uhhhhhhhh is supported as Python's, while Nim's \U{...} is unsupported but \u{...} is reserved
+ +\\[0-7]{1,3} in f-string will be interpreted as octal digit as Python,
+instead of decimal as Nim.
+ +the following shows the deature of Nim's multiline string which is different from Python's
+assert "" == """ +""" + +## Unicode Names +`\N{name}` is not supported yet. ++ +
Example:
+assert f"\n" == "\n" +assert f"123{'a'}\n456" == "123a\n456" + +assert f"\U0001f451" == "👑" + +assert f"\10" == "\x08" # nim's "\10" means chr(10) + +assert f"""\t123 +""" == "\t123\n" # even if the source code's newline is crlf.+ Source +Edit + +
func ascii(us: string): PyStr {....raises: [], tags: [], forbids: [].}
Example:
+assert ascii("𐀀") == r"'\U00010000'" +assert ascii("đ") == r"'\u0111'" +assert ascii("和") == r"'\u548c'" +let s = ascii("v我\n\e") +when not defined(useNimCharEsc): + let rs = r"'v\u6211\n\x1b'" +else: + let rs = r"'v\u6211\n\e'" +assert s == rs +assert ascii("\"") == "'\"'" +assert ascii("\"'") == "'\"\\''" +let s2 = ascii("'") +when not defined(singQuotedStr): + let rs2 = "\"'\"" +else: + let rs2 = r"'\''" +assert s2 == rs2+ Source +Edit + +
func pyrepr(s: StringLike): PyStr
Example:
+# NOTE: string literal's `repr` is `system.repr`, as following. +assert repr("\"") == "\"\\\"\"" # string literal of "\"" +# use pyrepr for any StringLike and returns a PyStr +assert pyrepr("\"") == "'\"'"+ Source +Edit + +
func repr(x: PyStr): string {....raises: [], tags: [], forbids: [].}
Overwites system.repr for PyStr
+The same as proc ascii except for unicode chars being remained AS-IS, and returns Nim's string.
+ + Source +Edit + +StringLike = string | char | PyStr
func `==`(o: string; self: PyStr): bool {.borrow, ...raises: [], tags: [], + forbids: [].}
func `[]`(self: PyStr; i: HSlice[int, BackwardsIndex]): PyStr {....raises: [], + tags: [], forbids: [].}
converter toNimString(self: PyStr): string {....raises: [], tags: [], forbids: [].}
func capitalize(a: PyStr): PyStr {....raises: [], tags: [], forbids: [].}
make the first character have title/upper case and the rest lower case.
+changed when Python 3.8: the first character will have title case.
+while Nim's unicode.capitalize only make the first character upper-case.
+ + Source +Edit + +func casefold(a: PyStr): PyStr {....raises: [], tags: [], forbids: [].}
str.casefold()
+str.lower() is used for most characters, but, for example, Cherokee letters is casefolded to their uppercase counterparts, and some will be converted to their normal case, e.g. "ß" -> "ss"
+ + Source +Edit + +func count(a: PyStr; sub: PyStr): int {....raises: [], tags: [], forbids: [].}
func endsWith(a: char; suffix: PyStr): bool {....raises: [], tags: [], forbids: [].}
func endsWith(a: PyStr; suffix: char): bool {....raises: [], tags: [], forbids: [].}
func endsWith[Suf: PyStr | tuple](a: PyStr; suffix: Suf; start, end: int): bool
func expandtabs(a: PyStr; tabsize = 8): PyStr {....raises: [], tags: [], + forbids: [].}
func lower(a: PyStr): PyStr {....raises: [], tags: [], forbids: [].}
str.lower
+not the same as Nim's unicode.toLower, see examples
+ +Example:
+import std/unicode +let dotI = Rune 0x0130 # İ (LATIN CAPITAL LETTER I WITH DOT ABOVE) +assert str(dotI).lower() == "i\u0307" ## i̇ (\u0207 is a upper dot) +assert dotI.toLower() == Rune('i')+ Source +Edit + +
func startsWith(a: char; suffix: PyStr): bool {....raises: [], tags: [], + forbids: [].}
func startsWith(a: PyStr; suffix: char): bool {....raises: [], tags: [], + forbids: [].}
func startsWith[Suf: PyStr | tuple](a: PyStr; suffix: Suf; start, end: int): bool
func startsWith[Suf: PyStr | tuple](a: PyStr; suffix: Suf; start: int): bool
func startsWith[Tup: tuple](a: PyStr; suffix: Tup): bool
func title(a: PyStr): PyStr {....raises: [], tags: [], forbids: [].}
str.title()
+not the same as title proc in std/unicode, see example.
+ +Example:
+let s = "lj" # \u01c9 +let u = str(s) +assert u.title() == "Lj" # \u01c8 +import std/unicode +assert unicode.title(s) == "LJ" # \u01c7+ Source +Edit + +
func upper(a: PyStr): PyStr {....raises: [], tags: [], forbids: [].}
str.upper
+not the same as Nim's unicode.toUpper, see examples
+ +Example:
+import std/unicode +let a = "ᾷ" +# GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI +assert str(a).upper() == "Α͂Ι" # 3 chars +assert a.toUpper() == a # Nim just maps it as-is. +# There is more examples... (101 characters in total)+ Source +Edit + +
template `*`(a: StringLike; i: int): PyStr
template `*`(i: int; a: StringLike): PyStr
str.translate
NOTE: Nim's KeyError is a subclass of ValueError instead of LookupError. Therefore when writing a custom TranslateTableABC or TypedTranslateTableABC for translate, beware a Nim's KeyError is not considered as a sign to leave such a character untouched, but will be just raised outside.
+However, TranslateTable or StrTypedTranslateTable is handled via overload. Using them as translate table is fine.
+ +StrTypedTranslateTable = TableRef[int, PyStr]
TranslateAction {.pure.} = enum + skip, aOrd, aChr, aStr
TranslateTable = TableRef[int, TranslateTableVal]
TranslateTableABC = concept self + self[int] is TranslateTableVal
TranslateTableVal = object + case + of skip: + nil + of aOrd: + i*: int + of aChr: + c*: char + of aStr: + s*: PyStr
TranslateValType = int | PyStr | char | NoneType
TypedTranslateTableABC[V] = concept self + V + self[int] is V
func repr(table: TranslateTable): string {....raises: [], tags: [], forbids: [].}
proc translate(s: PyStr; table: StrTypedTranslateTable): PyStr {. + ...raises: [TypeError], tags: [], forbids: [].}
proc translate(s: PyStr; table: TranslateTable): PyStr {. + ...raises: [TypeError, ValueError, KeyError], tags: [], forbids: [].}
proc translate[K: TranslateValType](s: PyStr; table: TypedTranslateTableABC[K]): PyStr
macro maketrans(_: typedesc[PyStr]; mapOrLit: untyped): TranslateTable
Example:
+let tbl = PyStr.maketrans({"a": None, "b": "123"}) +assert "axb".translate(tbl) == "x123"+ Source +Edit + +
template `$`(table: TranslateTable): string
str.format
+NOTE: only str in Python has format method, not bytes nor bytearray.
+ + +proc pyformatImplAux(s: string; args: seq[NimNode]; kw: Kw): NimNode {. + ...raises: [ValueError, KeyError], tags: [], forbids: [].}
if -d:pylibUseFormatValue, use formatValue instead of format for formatting.
+Convertion is not supported yet (like !r).
+ + Source +Edit + +func removeprefix[S](a: S; suffix: S): S
func removesuffix[S](a: S; suffix: S): S
func rpartition[S](a: S; sep: S): tuple[before, sep, after: S]
func startsWith[S; Suf: S | tuple](a: S; suffix: Suf; start, end: int): bool
func startsWith[S; Suf: S | tuple](a: S; suffix: Suf; start: int): bool
func startsWith[S; Tup: tuple](a: S; suffix: Tup): bool
template expandtabsImpl[S](a: S; tabsize: int; strByteLen: int; iter): string
template istitleImpl(a, isupper, islower: typed; iter, firstItemGetter)
template startsWith[S](a: char; suffix: S): bool
template startsWith[S](a: S; suffix: char): bool
DefSplitCap = 12
STRINGLIB_MUTABLE = false
func norm_maxsplit(maxsplit: int; str_len, sep_len: int): int {....raises: [], + tags: [], forbids: [].}
template norm_maxsplit(maxsplit: int; str_len): int
template PREPARE_CAP(maxcount): int
proc rsplit_whitespace[S](pystr: S; maxsplit = -1): PyList[S]
proc split_whitespace[S](pystr: S; maxsplit = -1): PyList[S]
iterator split_whitespace[S](pystr: S; maxsplit = -1): S
We cannot just use strutils.splitLines for str.splitlines, even nor for bytes.splitlines, as Python uses Univeral NewLine as sep.
+See https://docs.python.org/3/glossary.html#term-universal-newlines
+For a table of all Universal Newlines, see https://docs.python.org/3/library/stdtypes.html#str.splitlines
+ + +iterator splitlines[S](self: S; keepends = false): S
func translateEscape(pattern: string): string {....raises: [], tags: [], + forbids: [].}
macro translateEscapeWithErr(pattern: string): string
macro templWrapExportSincePy(major, minor: static int; sym: typed)
macro wrapExportSincePy(major, minor: static int; sym: typed)
template exportSincePy(major, minor: int; sym: typed)
to be imported by ./version
+PyReleaseLevelEnum {.pure.} = enum + alpha = 10, beta = 11, gamma = 12, final = 15
PyReleaseLevel = PyReleaseLevelEnum.final
ReleaseLevel = "alpha"
array
HasReadNRetBytesLike = concept self + self.read(int) is BytesLike
HasWriteBytesLike = concept self + self.write(BytesLike)
func `[]=`(self: var PyArray[Py_UCS4]; i: int): PyStr {.inline, ...raises: [], + tags: [], forbids: [].}
func `[]=`(self: var PyArray[Py_UCS4]; i: int; v: char) {.inline, ...raises: [], + tags: [], forbids: [].}
Example:
+from std/unicode import Rune +var a = array('w', "123") +a[0] = Rune(65) +a[1] = '3'+ Source +Edit + +
func buffer_info[T](arr: PyArray[T]): tuple[address: int, length: int]
func byteswap[T](arr: var PyArray[T])
array.byteswap
+Currently only compilable for c_* types, a.k.a. not for Nim's int*, e.g. int16
+Example:
+when sizeof(cshort) == 2: + var arr = array('h', [1, 2]) + arr.byteswap() + assert arr[0] == 256, $arr[0] # int from \x01\x00 + assert arr[1] == 512, $arr[1]+ Source +Edit + +
func frombytes[C: SomeChar](arr: var PyArray[C]; buffer: BytesLike)
func frombytes[T: not SomeChar](arr: var PyArray[T]; buffer: BytesLike)
Example:
+when sizeof(cshort) == 2: + var h = array('h', [1, 2]) + h.frombytes(b"\x05\x00") + when cpuEndian == littleEndian: + assert h[2] == 5 + else: + assert h[2] == 1280+ Source +Edit + +
func fromfile[T](arr: var PyArray[T]; f: File; n: int)
func fromfile[T](self: var PyArray[T]; f: HasReadNRetBytesLike; n: int)
func newPyArray[T](len = 0): PyArray[T] {.inline.}
func newPyArrayOfCap[T](cap: int): PyArray[T] {.inline.}
func tofile[T](arr: var PyArray[T]; f: File)
func tofile[T](self: PyArray[T]; f: HasWriteBytesLike)
macro array(typecode: static[char]): PyArray
Example:
+var a = array('i') +assert a.typecode == 'i' +assert len(a) == 0 +a.append(3) +assert a.len == 1 and a[0] == 3+ Source +Edit + +
macro array(typecode: static[char]; initializer: typed): PyArray
bytes or bytearray, a Unicode string, or iterable over elements of the appropriate type.
+initializer can be a bracket stmt, no need to manually add type convert, see examples
+ +Example:
+assert array('i', [1, 2])[1] == c_int(2) +assert array('b', b"123")[2] == c_schar('3')+ Source +Edit + +
proc insort_left[T; K](a: MutableSequence[T]; x: K; lo = 0; hi = len(a); + key: NoneType | Key[T, K] = None)
proc insort_right[T; K](a: MutableSequence[T]; x: K; lo = 0; hi = len(a); + key: NoneType | Key[T, K] = None)
Lib/cmath
+complex math library for Python's complex
+ + +func isfinite(z: PyTComplex): bool
func isnan(z: PyTComplex): bool
func log[T](z: PyTComplex[T]): PyTComplex[T]
func log[T](z: PyTComplex[T]; base: SomeNumber | PyTComplex[T]): PyTComplex[T]
func rect[T](r, phi: T): PyTComplex[T]
template acos(x: PyTComplex): untyped
template acosh(x: PyTComplex): untyped
template asin(x: PyTComplex): untyped
template asinh(x: PyTComplex): untyped
template atan(x: PyTComplex): untyped
template atanh(x: PyTComplex): untyped
template exp(z: PyTComplex): PyTComplex
template log10(z: PyTComplex): PyTComplex
template phase(z: PyTComplex): PyTComplex
template polar(z: PyTComplex): PyTComplex
template sin(z: PyTComplex): PyTComplex
template sqrt(z: PyTComplex): PyTComplex
converter noneToTzInfo(_: NoneType): tzinfo {....raises: [], tags: [], forbids: [].}
PyDatetime = datetime
func asNimDatetime(self: datetime): DateTime {....raises: [], tags: [], forbids: [].}
func microsecond(self: datetime): int {....raises: [], tags: [], forbids: [].}
func newDatetime(dt: DateTime; tzinfo: tzinfo = nil; isfold = false): datetime {. + ...raises: [], tags: [], forbids: [].}
General calendrical helper functions
+For each month ordinal in 1..12, the number of days in that month, and the number of days before that month in the same year. These are correct for non-leap years only.
+ +func days_before_month(year, month: int): int {....raises: [], tags: [], + forbids: [].}
proc iso_to_ymd(iso: YWD; ymd: var YMD) {....raises: [ValueError], tags: [], + forbids: [].}
proc iso_week1_monday(year: int): int {....raises: [], tags: [], forbids: [].}
proc ord_to_ymd(ordinal: int; result: var YMD) {....raises: [], tags: [], + forbids: [].}
func ymd_to_ord(year, month, day: int): int {....raises: [], tags: [], forbids: [].}
proc ymd_to_ord(ymd: YMD): int {....raises: [], tags: [], forbids: [].}
date
+func isocalendar(self: datetime): YWD {....raises: [], tags: [], forbids: [].}
func isoweekday(self: datetime): int {....raises: [], tags: [], forbids: [].}
proc replace(self: datetime; year = self.year; month = self.month; + day = self.day; hour = self.hour; minute = self.minute; + second = self.second; microsecond = self.microsecond; + tzinfo = self.tzinfo; fold = 0): datetime {....raises: [ValueError], + tags: [], forbids: [].}
translated from CPython/Python/pytime.c
+proc nPyTime_gmtime(t: time_t; tm: var Tm) {....raises: [PyOSError], tags: [], + forbids: [].}
proc nPyTime_localtime(t: time_t; tm: var Tm) {....raises: [PyOSError], tags: [], + forbids: [].}
func nPyTime_ObjectToTimeval(obj: Timestamp; sec: var time_t; usec: var long; + round: PyTime_round_t)
proc fromisocalendar(_: _`gensym1744830498:type; year, week, day: int): datetime
proc fromisoformat(_: _`gensym1744830487:type; nonkw: string): datetime
proc fromordinal(_: _`gensym1744830492:type; ordinal: int): datetime
proc fromtimestamp(_: _`gensym1744830592:type; timestamp: Timestamp; tz = TzNone): datetime
struct_tm {.importc: "struct tm", header: "<time.h>", completeStruct.} = object
Tm {.importc: "struct tm", header: "<time.h>".} = object + tm_year*: int ## years since 1900 + tm_mon*: range[0 .. 11] + tm_mday*: range[1 .. 31] + tm_hour*: range[0 .. 23] + tm_min*: range[0 .. 59] + tm_sec*: range[0 .. 61] ## C89 is 0..61, C99 is 0..60 + tm_wday*: range[0 .. 6] + tm_yday*: range[0 .. 365] + tm_isdst*: int
HAVE_STRUCT_TM_TM_ZONE = false
macro cTmToNormCall(call; tm: Tm; kwargs: varargs[untyped]): untyped
max_fold_seconds = BiggestInt(86400)
proc local_to_seconds(year, month, day, hour, minute, second: int; fold: int): BiggestInt {. + ...raises: [ValueError, PyOSError], tags: [], forbids: [].}
func utc_to_seconds(year, month, day, hour, minute, second: int): BiggestInt {. + ...raises: [ValueError], tags: [], forbids: [].}
template notImplErr(meth)
TimeDeltaNone: timedelta = nil
func asDuration(self: timedelta): Duration {....raises: [], tags: [], forbids: [].}
func flush_hash(self: timedelta) {....raises: [], tags: [], forbids: [].}
func inMicroseconds(self: timedelta): int64 {....raises: [], tags: [], forbids: [].}
func isTimeDeltaNone(self: timedelta): bool {....raises: [], tags: [], forbids: [].}
func newTimedelta(days, seconds, microseconds: int; normalize = true): timedelta {. + ...raises: [], tags: [], forbids: [].}
func newTimedelta(dur: Duration): timedelta {....raises: [], tags: [], forbids: [].}
func microseconds(self: timedelta): int64 {....raises: [], tags: [], forbids: [].}
func microsecondsImpl(parts: DurationParts): int64 {....raises: [], tags: [], + forbids: [].}
func secondsImpl(parts: DurationParts): int64 {....raises: [], tags: [], + forbids: [].}
func `*`(f: float; self: timedelta): timedelta {....raises: [], tags: [], + forbids: [].}
func `*`(i: int64; self: timedelta): timedelta {....raises: [], tags: [], + forbids: [].}
func resolution(_: _`gensym1610612824:type): timedelta
func timedelta(days: FI = 0; seconds: FI = 0; microseconds: FI = 0; + milliseconds: FI = 0; minutes: FI = 0; hours: FI = 0; + weeks: FI = 0): timedelta
func timedelta(days: int64; seconds = 0'i64; microseconds = 0'i64; + milliseconds = 0'i64; minutes = 0'i64; hours = 0'i64; + weeks = 0'i64): timedelta {....raises: [], tags: [], forbids: [].}
timedelta with int-only arguments
+See timedelta that accepts mixin float and int as arguments
+func total_seconds(self: timedelta): float {....raises: [], tags: [], forbids: [].}
func format_utcoffset(parts: DurationParts; sep: string | char = ':'; + prefix = "UTC"): string
proc newPyTimezone(offset: timedelta): timezone {....raises: [ValueError], + tags: [], forbids: [].}
func newPyTimezone(offset: timedelta; name: string): timezone {. + ...raises: [ValueError], tags: [], forbids: [].}
method toNimTimezone(self: timezone): Timezone {....raises: [], tags: [], + forbids: [].}
method toNimTimezone(self: tzinfo): Timezone {.base, ...raises: [], tags: [], + forbids: [].}
template tzToNimTimezone(tz: tzinfo): Timezone
template GenPyEnumInit(Self, Value: typedesc; sym) {.dirty.}
template GenPyEnumMeth(Self; Value: typedesc; genObjMeth = true; + genInit = false; nameError = NameError; Str = string) {. + dirty.}
template DeclIntEnumMeth(Self; Int = int; genObjMeth = true; genInit = false) {. + dirty.}
template GenIntEnumMeth(Self: typedesc; Int = int; genObjMeth = true; + genInit = false) {.dirty.}
EADDRINUSE {.importc, header: "<errno.h>".}: cint
EADDRNOTAVAIL {.importc, header: "<errno.h>".}: cint
EAFNOSUPPORT {.importc, header: "<errno.h>".}: cint
ECONNABORTED {.importc, header: "<errno.h>".}: cint
ECONNREFUSED {.importc, header: "<errno.h>".}: cint
ECONNRESET {.importc, header: "<errno.h>".}: cint
EDESTADDRREQ {.importc, header: "<errno.h>".}: cint
EHOSTUNREACH {.importc, header: "<errno.h>".}: cint
EINPROGRESS {.importc, header: "<errno.h>".}: cint
EKEYEXPIRED {.importc, header: "<errno.h>".}: cint
EKEYREJECTED {.importc, header: "<errno.h>".}: cint
EKEYREVOKED {.importc, header: "<errno.h>".}: cint
EMEDIUMTYPE {.importc, header: "<errno.h>".}: cint
ENAMETOOLONG {.importc, header: "<errno.h>".}: cint
ENETUNREACH {.importc, header: "<errno.h>".}: cint
ENOPROTOOPT {.importc, header: "<errno.h>".}: cint
ENOTRECOVERABLE {.importc, header: "<errno.h>".}: cint
EOPNOTSUPP {.importc, header: "<errno.h>".}: cint
EOWNERDEAD {.importc, header: "<errno.h>".}: cint
EPFNOSUPPORT {.importc, header: "<errno.h>".}: cint
EPROTONOSUPPORT {.importc, header: "<errno.h>".}: cint
EPROTOTYPE {.importc, header: "<errno.h>".}: cint
ESOCKTNOSUPPORT {.importc, header: "<errno.h>".}: cint
ETOOMANYREFS {.importc, header: "<errno.h>".}: cint
EWOULDBLOCK {.importc, header: "<errno.h>".}: cint
EXT. stable
+ +template prepareROErrno() {.dirty.}
template prepareRWErrno() {.dirty.}
template setErrnoRaw(v: cint)
Errno {.pure.} = enum + E_SUCCESS = "success", ## inner. unstable. + E2BIG = "Argument list too long", EACCES = "Permission denied", + EADDRINUSE = "Address already in use", + EADDRNOTAVAIL = "Cannot assign requested address", EADV = "Advertise error", + EAFNOSUPPORT = "Address family not supported by protocol", + EAGAIN = "Resource temporarily unavailable", + EALREADY = "Operation already in progress", EBADE = "Invalid exchange", + EBADF = "Bad file descriptor", EBADFD = "File descriptor in bad state", + EBADMSG = "Bad message", EBADR = "Invalid request descriptor", + EBADRQC = "Invalid request code", EBADSLT = "Invalid slot", + EBFONT = "Bad font file format", EBUSY = "Device or resource busy", + ECANCELED = "Operation canceled", ECHILD = "No child processes", + ECHRNG = "Channel number out of range", ECOMM = "Communication error on send", + ECONNABORTED = "Software caused connection abort", + ECONNREFUSED = "Connection refused", ECONNRESET = "Connection reset by peer", + EDEADLK = "Resource deadlock avoided", + EDEADLOCK = "Resource deadlock avoided", + EDESTADDRREQ = "Destination address required", + EDOM = "Numerical argument out of domain", EDOTDOT = "RFS specific error", + EDQUOT = "Disk quota exceeded", EEXIST = "File exists", + EFAULT = "Bad address", EFBIG = "File too large", EHOSTDOWN = "Host is down", + EHOSTUNREACH = "No route to host", EIDRM = "Identifier removed", + EILSEQ = "Invalid or incomplete multibyte or wide character", + EINPROGRESS = "Operation now in progress", EINTR = "Interrupted system call", + EINVAL = "Invalid argument", EIO = "Input/output error", + EISCONN = "Transport endpoint is already connected", + EISDIR = "Is a directory", EISNAM = "Is a named type file", + EKEYEXPIRED = "Key has expired", EKEYREJECTED = "Key was rejected by service", + EKEYREVOKED = "Key has been revoked", EL2HLT = "Level 2 halted", + EL2NSYNC = "Level 2 not synchronized", EL3HLT = "Level 3 halted", + EL3RST = "Level 3 reset", ELIBACC = "Can not access a needed shared library", + ELIBBAD = "Accessing a corrupted shared library", + ELIBEXEC = "Cannot exec a shared library directly", + ELIBMAX = "Attempting to link in too many shared libraries", + ELIBSCN = ".lib section in a.out corrupted", + ELNRNG = "Link number out of range", + ELOOP = "Too many levels of symbolic links", + EMEDIUMTYPE = "Wrong medium type", EMFILE = "Too many open files", + EMLINK = "Too many links", EMSGSIZE = "Message too long", + EMULTIHOP = "Multihop attempted", ENAMETOOLONG = "File name too long", + ENAVAIL = "No XENIX semaphores available", ENETDOWN = "Network is down", + ENETRESET = "Network dropped connection on reset", + ENETUNREACH = "Network is unreachable", + ENFILE = "Too many open files in system", ENOANO = "No anode", + ENOBUFS = "No buffer space available", ENOCSI = "No CSI structure available", + ENODATA = "No data available", ENODEV = "No such device", + ENOENT = "No such file or directory", ENOEXEC = "Exec format error", + ENOKEY = "Required key not available", ENOLCK = "No locks available", + ENOLINK = "Link has been severed", ENOMEDIUM = "No medium found", + ENOMEM = "Cannot allocate memory", ENOMSG = "No message of desired type", + ENONET = "Machine is not on the network", ENOPKG = "Package not installed", + ENOPROTOOPT = "Protocol not available", ENOSPC = "No space left on device", + ENOSR = "Out of streams resources", ENOSTR = "Device not a stream", + ENOSYS = "Function not implemented", ENOTBLK = "Block device required", + ENOTCONN = "Transport endpoint is not connected", ENOTDIR = "Not a directory", + ENOTEMPTY = "Directory not empty", ENOTNAM = "Not a XENIX named type file", + ENOTRECOVERABLE = "State not recoverable", + ENOTSOCK = "Socket operation on non-socket", + ENOTSUP = "Operation not supported", + ENOTTY = "Inappropriate ioctl for device", + ENOTUNIQ = "Name not unique on network", ENXIO = "No such device or address", + EOPNOTSUPP = "Operation not supported", + EOVERFLOW = "Value too large for defined data type", + EOWNERDEAD = "Owner died", EPERM = "Operation not permitted", + EPFNOSUPPORT = "Protocol family not supported", EPIPE = "Broken pipe", + EPROTO = "Protocol error", EPROTONOSUPPORT = "Protocol not supported", + EPROTOTYPE = "Protocol wrong type for socket", + ERANGE = "Numerical result out of range", EREMCHG = "Remote address changed", + EREMOTE = "Object is remote", EREMOTEIO = "Remote I/O error", + ERESTART = "Interrupted system call should be restarted", + ERFKILL = "Operation not possible due to RF-kill", + EROFS = "Read-only file system", + ESHUTDOWN = "Cannot send after transport endpoint shutdown", + ESOCKTNOSUPPORT = "Socket type not supported", ESPIPE = "Illegal seek", + ESRCH = "No such process", ESRMNT = "Srmount error", + ESTALE = "Stale file handle", ESTRPIPE = "Streams pipe error", + ETIME = "Timer expired", ETIMEDOUT = "Connection timed out", + ETOOMANYREFS = "Too many references: cannot splice", + ETXTBSY = "Text file busy", EUCLEAN = "Structure needs cleaning", + EUNATCH = "Protocol driver not attached", EUSERS = "Too many users", + EWOULDBLOCK = "Resource temporarily unavailable", + EXDEV = "Invalid cross-device link", EXFULL = "Exchange full"
ErrnoCount = 133
macro initErrorcodeMap(K, V; res: untyped; initFunc: typed)
template declErrorcodeWith[K, V](initFunc: typed)
FractionInt = int
PyFraction = TFraction[FractionInt]
func `$`(self: PyFraction): string {....raises: [], tags: [], forbids: [].}
func `%`(a, b: PyFraction): PyFraction {....raises: [], tags: [], forbids: [].}
func `%`(a: PyFraction; b: float): float {....raises: [], tags: [], forbids: [].}
func `%`(a: PyFraction; b: int): PyFraction {....raises: [], tags: [], forbids: [].}
func `%`(b: float; a: PyFraction): float {....raises: [], tags: [], forbids: [].}
func `%`(b: int; a: PyFraction): PyFraction {....raises: [], tags: [], forbids: [].}
func `%=`(self: PyFraction; other: PyFraction) {....raises: [], tags: [], + forbids: [].}
func `*`(a, b: PyFraction): PyFraction {....raises: [], tags: [], forbids: [].}
func `*`(a: PyFraction; b: float): float {....raises: [], tags: [], forbids: [].}
func `*`(a: PyFraction; b: int): PyFraction {....raises: [], tags: [], forbids: [].}
func `*`(b: float; a: PyFraction): float {....raises: [], tags: [], forbids: [].}
func `*`(b: int; a: PyFraction): PyFraction {....raises: [], tags: [], forbids: [].}
func `*=`(a, b: PyFraction) {....raises: [], tags: [], forbids: [].}
func `*=`(a: PyFraction; b: float) {.error: "Python allowed this but make `self` to a float".}
func `*=`(a: PyFraction; b: int) {....raises: [], tags: [], forbids: [].}
func `+`(a, b: PyFraction): PyFraction {....raises: [], tags: [], forbids: [].}
func `+`(a: PyFraction; b: float): float {....raises: [], tags: [], forbids: [].}
func `+`(a: PyFraction; b: int): PyFraction {....raises: [], tags: [], forbids: [].}
func `+`(b: float; a: PyFraction): float {....raises: [], tags: [], forbids: [].}
func `+`(b: int; a: PyFraction): PyFraction {....raises: [], tags: [], forbids: [].}
func `+=`(a, b: PyFraction) {....raises: [], tags: [], forbids: [].}
func `+=`(a: PyFraction; b: float) {.error: "Python allowed this but make `self` to a float".}
func `+=`(a: PyFraction; b: int) {....raises: [], tags: [], forbids: [].}
func `-`(a, b: PyFraction): PyFraction {....raises: [], tags: [], forbids: [].}
func `-`(a: PyFraction; b: float): float {....raises: [], tags: [], forbids: [].}
func `-`(a: PyFraction; b: int): PyFraction {....raises: [], tags: [], forbids: [].}
func `-`(b: float; a: PyFraction): float {....raises: [], tags: [], forbids: [].}
func `-`(b: int; a: PyFraction): PyFraction {....raises: [], tags: [], forbids: [].}
func `-=`(a, b: PyFraction) {....raises: [], tags: [], forbids: [].}
func `-=`(a: PyFraction; b: float) {.error: "Python allowed this but make `self` to a float".}
func `-=`(a: PyFraction; b: int) {....raises: [], tags: [], forbids: [].}
func `/`(a, b: PyFraction): PyFraction {....raises: [], tags: [], forbids: [].}
func `/`(a: PyFraction; b: float): float {....raises: [], tags: [], forbids: [].}
func `/`(a: PyFraction; b: int): PyFraction {....raises: [], tags: [], forbids: [].}
func `/`(b: float; a: PyFraction): float {....raises: [], tags: [], forbids: [].}
func `/`(b: int; a: PyFraction): PyFraction {....raises: [], tags: [], forbids: [].}
func `//`(a, b: PyFraction): FractionInt {....raises: [], tags: [], forbids: [].}
func `/=`(a, b: PyFraction) {....raises: [], tags: [], forbids: [].}
func `/=`(a: PyFraction; b: float) {.error: "Python allowed this but make `self` to a float".}
func `/=`(a: PyFraction; b: int) {....raises: [], tags: [], forbids: [].}
func `<`(a, b: PyFraction): bool {....raises: [], tags: [], forbids: [].}
func `<=`(a, b: PyFraction): bool {....raises: [], tags: [], forbids: [].}
func `==`(a, b: PyFraction): bool {....raises: [], tags: [], forbids: [].}
func abs(self: PyFraction): PyFraction {....raises: [], tags: [], forbids: [].}
func as_integer_ratio(self: PyFraction): (FractionInt, FractionInt) {. + ...raises: [], tags: [], forbids: [].}
func ceil(self: PyFraction): int {....raises: [], tags: [], forbids: [].}
func denominator(self: PyFraction): FractionInt {....raises: [], tags: [], + forbids: [].}
func denominator=(self: PyFraction; v: FractionInt) {. + error: "AttributeError: can\'t set attribute".}
func float(self: PyFraction): system.float {....raises: [], tags: [], forbids: [].}
func floor(self: PyFraction): int {....raises: [], tags: [], forbids: [].}
func Fraction(f: float): PyFraction {....raises: [], tags: [], forbids: [].}
func Fraction(numerator = 0; denominator = 1): PyFraction {....raises: [], + tags: [], forbids: [].}
func Fraction(other: PyFraction): PyFraction {....raises: [], tags: [], forbids: [].}
func Fraction(str: string): PyFraction {....raises: [ValueError], tags: [], + forbids: [].}
func from_float(typ: typedesc[PyFraction]; flt: float): PyFraction
func hash(self: PyFraction): int {....raises: [], tags: [], forbids: [].}
func is_integer(self: PyFraction): bool {....raises: [], tags: [], forbids: [].}
func newPyFraction(): PyFraction {....raises: [], tags: [], forbids: [].}
func numerator(self: PyFraction): FractionInt {....raises: [], tags: [], + forbids: [].}
func numerator=(self: PyFraction; v: FractionInt) {. + error: "AttributeError: can\'t set attribute".}
func repr(self: PyFraction): string {....raises: [], tags: [], forbids: [].}
func round(self: PyFraction): int {....raises: [], tags: [], forbids: [].}
func round(self: PyFraction; ndigits: int): float {....raises: [], tags: [], + forbids: [].}
func toPyFraction(r: Rational[int]): PyFraction {....raises: [], tags: [], + forbids: [].}
func toTFraction[T](r: Rational[T]): PyFraction
template conjugate(self: PyFraction): PyFraction
template imag(self: PyFraction): int
template real(self: PyFraction): PyFraction
Lib/gc +
Since Nim 2.0, ORC becomes the default mm (memory management). In ORC, only a cycle collector will runs at runtime, so enable and disable only affect this cycle collector, a.k.a. collect for objects that not causes cycle cannot be disabled in runtime, as it's determined at compile-time, namely by ARC.
+Document for Nim's mm.
+Python's gc is similar with Nim's `refc` mm, which is default for Nim 1.x
+As Nim's mm is so different from Python's gc, only a few APIs of gc can be ported to Nim.
+ +GcCollectResult = 0
proc collect(): int {.discardable, ...raises: [Exception], tags: [RootEffect], + forbids: [].}
iterator getmembers[T](obj: T): GetMemberType
iterator getmembers[T](obj: T; predict: GetMembersPredict): GetMemberType
template getdoc(obj: untyped): OptionalObj[PyStr]
template getmembers(obj): PyList
template getmembers(obj; predict: GetMembersPredict): PyList
template getmembers_static(obj): untyped
template getmembers_static(obj; predict: GetMembersPredict): untyped
template getmodulename(obj: PyStr): OptionalObj[PyStr]
template getsourcefile(obj: untyped): OptionalObj[PyStr]
template getsourcelines(obj: typed): (PyList[PyStr], int)
template isawaitable(obj: typed): bool
template iscoroutinefunction(obj: typed): bool
template markcoroutinefunction[T](obj: T): T
macro iscoroutine(obj: typed): bool
macro iscoroutinefunction(obj: typed): bool
macro isfunction(obj: typed): bool
macro markcoroutinefunction[T](obj: T): T
template isawaitable(obj: typed): bool
template istraceback(obj: typed): bool
GetMembersPredict = proc (x: MemberType): bool
GetMembersType = seq[GetMemberType]
GetMemberType = (string, MemberType)
iterator getmembers[T](obj: var T): GetMemberType
iterator getmembers[T](obj: var T; predict: GetMembersPredict): GetMemberType
template gen_getmembers_static(prag): untyped {.dirty.}
template getmembers(obj): seq
template getmembers(obj; predict: GetMembersPredict): seq
template getmembers_static(obj): untyped {.dirty.}
template getmembers_static(obj; predict: GetMembersPredict): untyped {.dirty.}
template getmembersImpl[R](obj; predict; initResult): R
func getdocNoDedentImpl(obj: NimNode): string {....raises: [], tags: [], + forbids: [].}
macro getfile(obj: typed): string
macro getsource(obj: typed): string
Example:
+func f: int = + ## doc + 1 +static: + assert getsource(f) == """ +func f(): int = + result = + ## doc + 1 +"""+ Source +Edit + +
template getsourcefile(obj: typed): string
template getsourcelinesImpl(obj: NimNode; splitlines): untyped
get source code of the object
+the first element is the source code the second element is the line number of the first line of the source code
+ + Source +Edit + +NOTE: not support js currently +
Its param: closefd, opener is not implemented yet
+ +There is difference that Python's TextIOBase.seek will reset state of encoder at some conditions, while Nim doesn't have access to encoder's state Therefore, seek here doesn't change that
+ +Python's __next__ will yield newline as part of result but Nim's iterator lines does not
+ +BufferedIOBase = ref object of IOBase
BufferedRandom = ref object of BufferedIOBase
BufferedReader = ref object of BufferedIOBase
BufferedWriter = ref object of BufferedIOBase
NoEncTextIOBase = ref object of IOBase
NoEncTextIOWrapper = ref object of NoEncTextIOBase + name*: PyStr + mode*: PyStr
TextIOWrapper = ref object of NoEncTextIOWrapper + ## do not use string, so is always valid
UnsupportedOperation = object of PyOSError
DEFAULT_BUFFER_SIZE = 8192
DefEncoding = ""
DefNewLine = "None"
LocaleEncoding = "locale"
func encoding(s: TextIOWrapper): PyStr {....raises: [], tags: [], forbids: [].}
func errors(s: TextIOWrapper): PyStr {....raises: [], tags: [], forbids: [].}
proc initBufAsPy(nfile: var File; buf: int) {....raises: [], tags: [], forbids: [].}
proc newNoEncTextIO(file: File; name: string; newline = DefNewLine): NoEncTextIOWrapper {. + ...raises: [ValueError], tags: [], forbids: [].}
proc read(self: NoEncTextIOWrapper): PyStr {....raises: [IOError], + tags: [ReadIOEffect], forbids: [].}
proc read(self: NoEncTextIOWrapper; size: int): PyStr {....raises: [IOError], + tags: [ReadIOEffect], forbids: [].}
proc read(self: RawIOBase): PyBytes {....raises: [IOError], tags: [ReadIOEffect], + forbids: [].}
proc read(self: RawIOBase; size: int): PyBytes {....raises: [IOError], + tags: [ReadIOEffect], forbids: [].}
proc read(self: TextIOWrapper): PyStr {....raises: [IOError, Exception], + tags: [ReadIOEffect, RootEffect], + forbids: [].}
proc read(self: TextIOWrapper; size: int): PyStr {....raises: [IOError, Exception], + tags: [ReadIOEffect, RootEffect], forbids: [].}
proc readline(self: NoEncTextIOWrapper): PyStr {....raises: [IOError], + tags: [ReadIOEffect], forbids: [].}
proc readline(self: NoEncTextIOWrapper; size: int): PyStr {....raises: [IOError], + tags: [ReadIOEffect], forbids: [].}
proc readline(self: RawIOBase): PyBytes {....raises: [IOError], + tags: [ReadIOEffect], forbids: [].}
proc readline(self: RawIOBase; size: Natural): PyBytes {....raises: [IOError], + tags: [ReadIOEffect], forbids: [].}
proc readline(self: TextIOWrapper): PyStr {....raises: [IOError, Exception], + tags: [ReadIOEffect, RootEffect], forbids: [].}
Example:
+import std/strutils +const fn = "tempfiletest" +proc check(ls: varargs[string], newline: string) = + var f = open(fn, newline=newline) + for l in ls: + let s = f.readline() + assert s == l, + "expected $#, but got $#, with newline=$#" % [l.repr, s.repr, newline.repr] + + f.close() + +writeFile fn, "abc\r\n123\n-\r_" + +check "abc\n", "123\n", "-\n", "_", newline=DefNewLine +check "abc\r\n", "123\n", "-\r", "_", newline="" +check "abc\r", "\n123\n-\r", "_", newline="\r" +check "abc\r\n", "123\n", "-\r_", newline="\n" +check "abc\r\n", "123\n-\r_", newline="\r\n"+ Source +Edit + +
proc readline(self: TextIOWrapper; size: Natural): PyStr {. + ...raises: [IOError, Exception], tags: [ReadIOEffect, RootEffect], forbids: [].}
proc write(self: NoEncTextIOWrapper; s: PyStr): int {.discardable, + ...raises: [Exception], tags: [RootEffect], forbids: [].}
proc write(self: RawIOBase; s: PyBytes): int {.discardable, ...raises: [IOError], + tags: [WriteIOEffect], forbids: [].}
proc write(self: TextIOWrapper; s: PyStr): int {.discardable, + ...raises: [Exception], tags: [RootEffect], forbids: [].}
Writes the s to the stream and return the number of characters written
+The following is from Python's doc of open: if newline is None, any 'n' characters written are translated to the system default line separator, os.linesep. If newline is "" or 'n', no translation takes place. If newline is any of the other legal values, any 'n' characters written are translated to the given string.
+ +Example:
+const fn = "tempfiletest" +proc checkW(s, dest: string, newline=DefNewLine, encoding=DefEncoding; + writeLen=dest.len # dest.len returns bytes size + ) = + var f = open(fn, 'w', newline=newline, encoding=encoding) + assert writeLen == f.write s + f.close() + let res = readFile fn + assert dest == res, "expected "&dest.repr&" but got "&res.repr +checkW "1\n2", when defined(windows): "1\r\n2" else: "1\n2" +checkW "1\n2", "1\p2" # same as above +checkW "1\n2", "1\r2", newline="\r" +checkW "我", "我", encoding="utf-8", writeLen=1+ Source +Edit + +
method close(self: IOBase) {.base, ...raises: [], tags: [], forbids: [].}
method close(self: TextIOWrapper) {....raises: [Exception], tags: [RootEffect], + forbids: [].}
method seek(f: IOBase; cookie: int64; whence = SEEK_SET): int64 {.base, + discardable, ...raises: [IOError], tags: [], forbids: [].}
method seek(self: TextIOWrapper; cookie: int64; whence = SEEK_SET): int64 {. + discardable, + ...raises: [ValueError, UnsupportedOperation, IOError, PyOSError, Exception], + tags: [RootEffect], forbids: [].}
Example:
+var f = open("tempfiletest", 'w') +doAssertRaises UnsupportedOperation: + f.seek(1, SEEK_CUR) +f.close()+ Source +Edit + +
template open(file: int; mode: static[string | char] = "r"; buffering: int = -1; + encoding: string = DefEncoding; errors: string = DefErrors; + newline: string | char = DefNewLine): untyped
template open[S](file: PathLike[S]; mode: static[string | char] = "r"; + buffering: int = -1; encoding: string = DefEncoding; + errors: string = DefErrors; newline: string | char = DefNewLine): untyped
Example:
+const fn = "tempfiletest" +const nonfn = r" \:/ $&* " +doAssertRaises LookupError: + # raise LookupError instead of FileNotFoundError (like Python) + discard open(nonfn, encoding="this is a invalid enc") +doAssertRaises FileNotFoundError: + discard io.open(nonfn) # an invalid filename, never existing +block Write: + var f = open(fn, "w", encoding="utf-8") + let ret = f.write("123\r\n") + when defined(windows): + assert ret == 6 # Universal Newline, written "123\r\r\n" + else: + assert ret == 5 # written "123\r\n" + assert not f.closed + f.close() + assert f.closed + assert readFile(fn) == (when defined(windows):"123\r\r\n" else:"123\r\n") +block Read: + var f = open(fn, 'r') + let uniLineRes = f.read() # Universal Newline, "123\r\n\n" -> "123\n\n" + assert uniLineRes == (when defined(windows):"123\n\n" else:"123\n") + f.close()+ Source +Edit + +
func accumulate[T](iterable: Iterable[T]; binop: BinOp[T] = binOpAdd; + inital = mayZeroDefault(T)): Accumulate[T]
func combinations[T](iterable: Iterable[T]; r: int): Combinations[T]
iterator accumulate[T](iterable: Iterable[T]; binop: BinOp[T] = binOpAdd; + inital = mayZeroDefault(T)): T
iterator combinations[T](iterable: Iterable[T]; r: int): PyList[T]
Lib/math
+Wrapper around Lib/n_math, and raises exceptions when math error occurs as CPython behaves.
+ +template dist[T](p, q: (Iterable[T] and not openArray[T])): float
template dist[T](p, q: ClosureIter[T]): float
template sumprod[T](p, q: (Iterable[T] and not openArray[T])): float
template sumprod[T](p, q: ClosureIter[T]): float
from https://www.netlib.org/cephes/ cmath.tgz cbrt.c And single.tgz cbrtf.c
+Cube root
+DESCRIPTION:
+Returns the cube root of the argument, which may be negative.
+Range reduction involves determining the power of 2 of the argument. A polynomial of degree 2 applied to the mantissa, and multiplication by the cube root of 1, 2, or 4 approximates the root to within about 0.1%. Then Newton's iteration is used three times to converge to an accurate result.
+ACCURACY:
+Relative error:+
arithmetic domain # trials peak rms DEC -10,10 200000 1.8e-17 6.2e-18 IEEE 0,1e308 30000 1.5e-16 5.0e-17
+cbrt.c
+Cephes Math Library Release 2.8: June, 2000 Copyright 1984, 1991, 2000 by Stephen L. Moshier
+cbrt.nim Copyright litlighilit 2024
+ + + + +template GET_FLOAT_WORD(word: var uint32; x: float32)
template GET_FLOAT_WORD(x: float32): uint32
template getLowWord(x: float32): uint16
template getLowWord(x: float64): uint32
template setHighWord(x: float; hi)
compiletime/expm1.nim 10/19/2024:
---
+@(#)s_expm1.c 1.5 04/04/22 And s_expm1f.c
+==================================================== Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved. Copyright (C) 2024 by litlighilit. All rights reserved.
+Permission to use, copy, modify, and distribute this software is freely granted, provided that this notice is preserved. ==================================================== expm1(x) Returns exp(x)-1, the exponential of x minus 1.
++Method + 1. Argument reduction: + Given x, find r and integer k such that + + x = k*ln2 + r, |r| <= 0.5*ln2 ~ 0.34658 + + Here a correction term c will be computed to compensate + the error in r when rounded to a floating-point number. + + 2. Approximating expm1(r) by a special rational function on + the interval [0,0.34658]: + Since + r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 - r^4/360 + ... + we define R1(r*r) by + r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 * R1(r*r) + That is, + R1(r**2) = 6/r *((exp(r)+1)/(exp(r)-1) - 2/r) + = 6/r * ( 1 + 2.0*(1/(exp(r)-1) - 1/r)) + = 1 - r^2/60 + r^4/2520 - r^6/100800 + ... + We use a special Remes algorithm on [0,0.347] to generate + a polynomial of degree 5 in r*r to approximate R1. The + maximum error of this polynomial approximation is bounded + by 2**-61. In other words, + R1(z) ~ 1.0 + Q1*z + Q2*z**2 + Q3*z**3 + Q4*z**4 + Q5*z**5 + where Q1 = -1.6666666666666567384E-2, + Q2 = 3.9682539681370365873E-4, + Q3 = -9.9206344733435987357E-6, + Q4 = 2.5051361420808517002E-7, + Q5 = -6.2843505682382617102E-9; + (where z=r*r, and the values of Q1 to Q5 are listed below) + with error bounded by + | 5 | -61 + | 1.0+Q1*z+...+Q5*z - R1(z) | <= 2 + | | + + expm1(r) = exp(r)-1 is then computed by the following + specific way which minimize the accumulation rounding error: + 2 3 + r r [ 3 - (R1 + R1*r/2) ] + expm1(r) = r + --- + --- * [--------------------] + 2 2 [ 6 - r*(3 - R1*r/2) ] + + To compensate the error in the argument reduction, we use + expm1(r+c) = expm1(r) + c + expm1(r)*c + ~ expm1(r) + c + r*c + Thus c+r*c will be added in as the correction terms for + expm1(r+c). Now rearrange the term to avoid optimization + screw up: + ( 2 2 ) + ({ ( r [ R1 - (3 - R1*r/2) ] ) } r ) + expm1(r+c)~r - ({r*(--- * [--------------------]-c)-c} - --- ) + ({ ( 2 [ 6 - r*(3 - R1*r/2) ] ) } 2 ) + ( ) + + = r - E + 3. Scale back to obtain expm1(x): + From step 1, we have + expm1(x) = either 2^k*[expm1(r)+1] - 1 + = or 2^k*[expm1(r) + (1-2^-k)] + 4. Implementation notes: + (A). To save one multiplication, we scale the coefficient Qi + to Qi*2^i, and replace z by (x^2)/2. + (B). To achieve maximum accuracy, we compute expm1(x) by + (i) if x < -56*ln2, return -1.0, (raise inexact if x!=inf) + (ii) if k=0, return r-E + (iii) if k=-1, return 0.5*(r-E)-0.5 + (iv) if k=1 if r < -0.25, return 2*((r+0.5)- E) + else return 1.0+2.0*(r-E); + (v) if (k<-2||k>56) return 2^k(1-(E-r)) - 1 (or exp(x)-1) + (vi) if k <= 20, return 2^k((1-2^-k)-(E-r)), else + (vii) return 2^k(1-((E+2^-k)-r)) + +Special cases: + expm1(INF) is INF, expm1(NaN) is NaN; + expm1(-INF) is -1, and + for finite argument, only expm1(0)=0 is exact. + +Accuracy: + according to an error analysis, the error is always less than + 1 ulp (unit in the last place). + +Misc. info. + For IEEE double + if x > 7.09782712893383973096e+02 then expm1(x) overflow ++
Constants: The hexadecimal values are the intended ones for the following constants. The decimal values may be used, provided that the compiler will convert from decimal to binary accurately enough to produce the hexadecimal values shown.
+ + + + + +compiletime/log1p.nim 2024/10/19:
@(#)s_log1p.c 1.3 95/01/18 +Along with: +s_log1pf.c -- float version of s_log1p.c. +Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + + +==================================================== +Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. +Copyright (C) 2024 by litlighilit. All rights reserved. + +Developed at SunSoft, a Sun Microsystems, Inc. business. +Permission to use, copy, modify, and distribute this +software is freely granted, provided that this notice +is preserved. +==================================================== + +double log1p(double x) + +Method : + 1. Argument Reduction: find k and f such that + 1+x = 2^k * (1+f), + where sqrt(2)/2 < 1+f < sqrt(2) . + + Note. If k=0, then f=x is exact. However, if k!=0, then f + may not be representable exactly. In that case, a correction + term is need. Let u=1+x rounded. Let c = (1+x)-u, then + log(1+x) - log(u) ~ c/u. Thus, we proceed to compute log(u), + and add back the correction term c/u. + (Note: when x > 2**53, one can simply return log(x)) + + 2. Approximation of log1p(f). + Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s) + = 2s + 2/3 s**3 + 2/5 s**5 + ....., + = 2s + s*R + We use a special Reme algorithm on [0,0.1716] to generate + a polynomial of degree 14 to approximate R The maximum error + of this polynomial approximation is bounded by 2**-58.45. In + other words, + 2 4 6 8 10 12 14 + R(z) ~ Lp1*s +Lp2*s +Lp3*s +Lp4*s +Lp5*s +Lp6*s +Lp7*s + (the values of Lp1 to Lp7 are listed in the program) + and + | 2 14 | -58.45 + | Lp1*s +...+Lp7*s - R(z) | <= 2 + | | + Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2. + In order to guarantee error in log below 1ulp, we compute log + by + log1p(f) = f - (hfsq - s*(hfsq+R)). + + 3. Finally, log1p(x) = k*ln2 + log1p(f). + = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo))) + Here ln2 is split into two floating point number: + ln2_hi + ln2_lo, + where n*ln2_hi is always exact for |n| < 2000. + +Special cases: + log1p(x) is NaN with signal if x < -1 (including -INF) ; + log1p(+INF) is +INF; log1p(-1) is -INF with signal; + log1p(NaN) is that NaN with no signal. + +Accuracy: + according to an error analysis, the error is always less than + 1 ulp (unit in the last place). + +Constants: +The hexadecimal values are the intended ones for the following +constants. The decimal values may be used, provided that the +compiler will convert from decimal to binary accurately enough +to produce the hexadecimal values shown. + + +Note: Assuming log() return accurate answer, the following + algorithm can be used to compute log1p(x) to within a few ULP: + + u = 1+x; + if(u==1.0) return x ; else + return log(u)*(x/(u-1.0)); + + See HP-15C Advanced Functions Handbook, p.193. ++ + + + +
template genWithArg(sym, v32, v64) {.dirty.}
template genWithBracket(sym, v32, v64)
template genWithBracket(sym, v32, v64, Ret) {.dirty.}
GammaError = enum + geOk, geDom = "x in {0, -1, -2, ...}", ## when . + ## Infinity discontinuity, + ## which shall produce `Complex Infinity` in SymPy and + ## means domain error + geOverFlow = "x > MAX_GAMMA_X, result overflow as inf", + geUnderFlow = "x < MIN_GAMMA_X, result underflow as `-0.0` or `0.0`.", geZeroCantDetSign = "`x < -maxSafeInteger`(exclude -inf), " & + "can\'t detect result\'s sign", ## `x` losing unit digit, often not regard as an error + geGotNegInf = "x == -inf" ## this is made as a enumerate item as different languages' + ## implementation has different treatment towards -inf
func mapRaiseGammaErr(err: GammaError) {....raises: [ValueError], tags: [], + forbids: [].}
template raiseDomainErr()
template raiseDomainErr(details: string)
template raiseRangeErr()
template raiseRangeErr(details: string)
c_log1p(x) = 1.09861228866811 ct_log1p.log1p(x) = 1.09861228866811 relative_tol = -2.021137094636221e-16
+ +c_log1p(x) = 2.639057329615258 ct_log1p.log1p(x) = 2.639057329615259 relative_tol = 1.682756963505621e-16
+ +c_log1p(x) = 3.871201010907891 ct_log1p.log1p(x) = 3.871201010907891 relative_tol = -1.147161329516994e-16
+ +c_log1p(x) = 4.30406509320417 ct_log1p.log1p(x) = 4.304065093204169 relative_tol = -2.063580360581673e-16
+ +Thus in fact, these constants are no need to be very accurate, just to ensure they're greater than the actual value is enough.
+But as such a short-cur is introduced, I think it better to make it accurate.
+The values are calcuated from tools/math/gamma_x_range.py
+ +35.040096282958984'f32 0b01000010_00001100_00101001_00001111'f32
+ +0b11000010_00011010_01100111_11011000'f32
+ +171.6243769563027'f64 0b01000000_01100101_01110011_11111010_11100101_01100001_11110110_01000111'f64
+ +0b11000000_01100110_00111000_11111011_10001100_00011011_11010100_01000111'f64
+ +I found stdlib-js/gamma uses following values: 171.61447887182298
+But what I tested using SymPy was different. If SymPy is right and my method is so, then the old values are uncorrect and shall not be used, as the old checking range for zero/inf result is bigger. (it doesn't matter if that was smaller) So I change to use current values.
+ +template MAX_GAMMA_X[F](_: typedesc[F]): F
template MIN_GAMMA_X[F](_: typedesc[F]): F
compileLittleEndian = true
func isLittleEndian(): bool {.compileTime, ...raises: [], tags: [], forbids: [].}
maxExponent F - 1 = (MAX - 1) - BIAS = 254 - BIAS = 127 or 2046 - BIAS = 10230b1_00000000_1111111 => 32895 0b1_00000000000_11111111111111111111 => 2148532223mask whose exponent is equal to 126, 1022 a.k.a. (BIAS-1): 0b0_01111110_0000000 => 16256 0b0_01111111110_00000000000000000000 => 1071644672HIGH_WORD_EXPONENT_MASK: 0b0_11111111_0000000 0b0_11111111111_00000000000000000000mantissaDigits F - 1
+template CLEAR_EXP_MASK[F](): untyped
template HighWordFracBits[F](): untyped
template MantissaDigits[F](): untyped
template MAX_EXPONENT[F](_: typedesc[F]): F
template MAX_SUBNORMAL_EXPONENT[F](_: typedesc[F]): F
template MIN_SUBNORMAL_EXPONENT[F](_: typedesc[F]): F
template SET_EXP_MASK[F](): untyped
for JS and C-like backends
+Not for nimvm, see {to,from}Words for impl for nimvm backend
+ +template init32FloatView(FLOAT32_VIEW, UINT16_VIEW)
template init64FloatView(FLOAT64_VIEW, UINT32_VIEW)
253 - 1 224 - 1
+SQRT_TWO_PI = 2.5066282746310007
template maxSafeInteger[F](_: typedesc[F]): F
c_fma means compatible fma, using <math.h> fma when for C
+UNRELIABLE_FMA = true
Stirling's formula for the gamma function gamma(x) = sqrt(2 pi) x^(x-.5) exp(-x) ( 1 + 1/x P(1/x) )
+For float32: .028 < 1/x < .1 relative error < 1.9e-11
+ +func gamma[F: SomeFloat](x: F): F
Example:
+template chkValueErr(arg) = + doAssertRaises ValueError: discard gamma arg +chkValueErr NegInf +chkValueErr 0.0 +# Currently +-0.0 result is not consistent with CPython; +# assert NegInf == 1.0/gamma(-180.5)+ Source +Edit + +
func gamma[T: SomeFloat](x: T; res: var T): GammaError
func stdlibJsGamma[F: SomeFloat](x: F): F {....raises: [].}
template MAX_STIRLING[F](_: typedesc[F]): F
template UseSmallApprox[F](_: typedesc[F]): F
+
This module was hand-translated from FreeBSD's lgamma implementation;
+and with some modification:
+The following copyright, license, and long comment were part of the original implementation available as part of FreeBSD
+Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + +Developed at SunPro, a Sun Microsystems, Inc. business. +Permission to use, copy, modify, and distribute this +software is freely granted, provided that this notice +is preserved.+ + +
func lgamma[F: SomeFloat](x: F): F
Evaluates the natural logarithm of the absolute value of gamma function.
+The following was formatted as Nim-Favor Markdown from FreeBSD `lgamma` source with some minor amendment.
+ +Since gamma(1+s)=s*gamma(s), for x in [0,8], we may +reduce x to a number in [1.5,2.5] by + lgamma(1+s) = log(s) + lgamma(s) +for example, + lgamma(7.3) = log(6.3) + lgamma(6.3) + = log(6.3*5.3) + lgamma(5.3) + = log(6.3*5.3*4.3*3.3*2.3) + lgamma(2.3)+ +
Create a polynomial approximation of lgamma around its minimun ymin=1.461632144968362245 to maintain monotonicity.
+On [ymin-0.23, ymin+0.27] (i.e., [1.23164,1.73163]), use + Let z = x-ymin; + lgamma(x) = -1.214862905358496078218 + z^2*poly(z) +where + poly(z) is a 14 degree polynomial.+ +
We use the following approximation: + s = x-2.0; + lgamma(x) = 0.5*s + s*P(s)/Q(s) +with accuracy + |P/Q - (lgamma(x)-0.5s)| < 2**-61.71 +Our algorithms are based on the following observation + + zeta(2)-1 2 zeta(3)-1 3 +lgamma(2+s) = s*(1-Euler) + --------- * s - --------- * s + ... + 2 3+
where Euler = 0.5771... is the Euler constant, which is very close to 0.5.
+ +For x>=8, we have + lgamma(x) ~ (x-0.5)log(x)-x+0.5*log(2pi)+1/(12x)-1/(360x**3)+.... + +(better formula: + lgamma(x) ~ (x-0.5)*(log(x)-1)-.5*(log(2pi)-1) + ...) + +Let z = 1/x, then we approximation + f(z) = lgamma(x) - (x-0.5)(log(x)-1) +by + 3 5 11 + w = w0 + w1*z + w2*z + w3*z + ... + w6*z +where + |w - f(z)| < 2**-58.74+ +
For negative x, since (G is gamma function) + -x*G(-x)*G(x) = pi/sin(pi*x), +we have + G(x) = pi/(sin(pi*x)*(-x)*G(-x)) +since G(-x) is positive, sign(G(x)) = sign(sin(pi*x)) for x<0 +Hence, for x<0, signgam = sign(sin(pi*x)) and + lgamma(x) = log(|Gamma(x)|) + = log(pi/(|x*sin(pi*x)|)) - lgamma(-x);+
lgamma(2+s) ~ s*(1-Euler) for tiny s + lgamma(1) = lgamma(2) = 0 + lgamma(x) ~ -log(|x|) for tiny x + lgamma(0) = lgamma(neg.integer) = inf and raise divide-by-zero + lgamma(inf) = inf + lgamma(-inf) = inf # see belowFor lgamma(-inf), +
and C/C++ returns +inf; which is not suitable, as gamma(x) where x < about -200 is always truncated to 0.0 at ieee754 float domain. This behavior was said for bug compatible with C99, and is readlly documented by POSIX man and cppreference.com
+In my option, ln(|gamma(-oo)|) -[ieee754 float trunc]-> ln(0+) -> -inf
+But in this function it returns +inf to keep consistent with Python,
+ +Example:
+from std/math import isNaN +assert lgamma(1.0) == 0.0 +assert lgamma(Inf) == Inf +assert lgamma(NaN).isNaN+ Source +Edit + +
func lgamma[F: SomeFloat](x: F; res: var F): GammaError
func scipyGammaLn[F: SomeFloat](x: F): F {....raises: [].}
func stdlibJsLgamma[F: SomeFloat](x: F): F {....raises: [].}
translated from https://github.com/scijs/nextafter/blob/master/nextafter.js
+And add respect to the sign of zero, e.g.
+nextafter(-0.0, 0.0) == 0.0 nextafter(0.0, -0.0) == -0.0
+ + + + +The implementation uses Horner's rule for more efficient computation.
+ClosureIter[T] = iterator (): T
OpenarrayOrNimIter[T] = openArray[T] or ClosureIter[T]
func dist_checkedSameLen[T](p, q: T): int {.inline.}
template openarray_Check(x): bool
template toNimIterator[T](x): ClosureIter[T]
DoubleLength = object + hi*: float + lo*: float
proc dl_mul(x: float; y: float): DoubleLength {....raises: [], tags: [], + forbids: [].}
func dl_sum(a, b: float): DoubleLength {....raises: [], tags: [], forbids: [].}
func sumprod[P, Q](p: openArray[P]; q: openArray[Q]): float
func sumprod[P, Q](p_it: ClosureIter[P]; q_it: ClosureIter[Q]): float
proc bisect_left[T, K](a: openArray[T]; x: K; lo = 0; hi = a.len; key: Key[T, K]): int
proc bisect_left[T](a: openArray[T]; x: T; lo = 0; hi = a.len): int
proc bisect_right[T, K](a: openArray[T]; x: K; lo = 0; hi = a.len; + key: Key[T, K]): int
proc bisect_right[T](a: openArray[T]; x: T; lo = 0; hi = a.len): int
proc insort_left[T; K](a: var seq[T]; x: K; lo = 0; hi = len(a); key: Key[T, K])
proc insort_left[T](a: var seq[T]; x: T; lo = 0; hi = len(a))
proc insort_right[T; K](a: var seq[T]; x: K; lo = 0; hi = len(a); key: Key[T, K])
proc insort_right[T](a: var seq[T]; x: T; lo = 0; hi = len(a))
func cleandoc(s: string): string {.inline, ...raises: [], tags: [], forbids: [].}
Cleans up a docstring by removing leading whitespace and trailing newlines.
+The first line of the docstring is also removed, as it is assumed to be the docstring's summary.
+The docstring is also trimmed of leading and trailing whitespace.
+ + Source +Edit + +proc getmodulename(obj: string): string {....raises: [ValueError], tags: [], + forbids: [].}
macro getsourcelines(obj: typed): (seq[string], int)
iterator accumulate[T](iterable: openArray[T]; binop: BinOp[T] = binOpAdd; + inital = mayZeroDefault(T)): T
iterator combinations[T](iterable: openArray[T]; r: int): seq[T]
template mayZeroDefault[T](t: typedesc[T]): T
Nim's Python-like math, but raises no catchable exception, using errno to report math error. a.k.a. non will be raised (but not for Defects)
+which allows fast code.
+For Python-like error handler (exception-based), see Lib/math
+Also this is not just a module that wraps Nim's std/math,
+but also providing some extensions that Nim's std/math lacks, for example:
+And fix some non-C99 behavior on some systems, e.g. log(-ve) -> -Inf on Solaris
+NOTE: Currently int is not acceptable when it comes to float about functions
+ +func comb(n, k: int): int {....raises: [], tags: [], forbids: [].}
func isqrtPositive(n: Positive): int {.inline, ...raises: [], tags: [], forbids: [].}
func math_is_error(x: SomeFloat; exc: var ref Exception): bool
inner usage (used by Lib/math).
+Call this when errno != 0, and where x is the result libm returned. This will usually set up an exception and return true, but may return false without setting up an exception.
+ + Source +Edit + +template py_math_isclose_impl(abs)
inner use. Implementation of isclose.
+mixin a, b, isinf, rel_tol, abs_tol
+ + Source +Edit + +uname_result = tuple[sysname, nodename, release, version, machine: string]
proc uname(): uname_result {....raises: [PyOSError], tags: [], forbids: [].}
func capwords(a: string): string {....raises: [], tags: [], forbids: [].}
Mimics Python string.capwords(s) -> str:
+Runs of whitespace characters are replaced by a single space and leading and trailing whitespace are removed.
+ + Source +Edit + +func capwords(a: string; sep: string): string {....raises: [], tags: [], + forbids: [].}
Mimics Python string.capwords(s, sep) -> str:
+Split the argument into words using split, capitalize each word using capitalize, and join the capitalized words using join. sep is used to split and join the words.
+ + Source +Edit + +proc get_identifiers(templ: Template): seq[string] {....raises: [Exception], + tags: [RootEffect], forbids: [].}
macro safe_substitute(templ: Template; kws: varargs[untyped]): string
macro safe_substitute(templ: Template; mapping: Table; kws: varargs[untyped]): string
macro substitute(templ: Template; kws: varargs[untyped]): string
macro substitute(templ: Template; mapping: Table; kws: varargs[untyped]): string
orig_argv = newSeqOfCap(argc)
hexversion = 51577072
implementation = ("pynim", (0, 9, 11, "alpha", 0), 51577072, + (val: "", has: false))
platform = "linux"
and haiku/netbsd appended with major version instead of "unknown". In short, this won't be "unknown" as Python does.
+ + Source +Edit + +version_info = (major: 3, minor: 13, patch: 0, releaselevel: "final", serial: 0)
template executable(): string
XXX: FIXED-NIM-BUG: though nimAllowNonVarDestructor is defined at least since 2.0.6, it still cannot be compiled till about 2.1.1
+ +TemporaryDirectoryWrapper = object + name*: string
TemporaryFileCloser[IO] = ref object + file*: IO + name*: string
TemporaryFileWrapper[IO] = object
proc `=destroy`(self: TemporaryDirectoryWrapper) {....raises: [], + tags: [WriteDirEffect, ReadDirEffect], forbids: [].}
proc cleanup(self: TemporaryDirectoryWrapper) {....raises: [PyOSError], + tags: [WriteDirEffect, ReadDirEffect], forbids: [].}
proc close(self: TemporaryDirectoryWrapper) {....raises: [], + tags: [WriteDirEffect, ReadDirEffect], forbids: [].}
proc close(t: TemporaryFileWrapper)
proc close[IO](self: TemporaryFileCloser[IO]; unlink = os.removeFile)
proc flush[IO](self: TemporaryFileWrapper[IO])
proc gettempdir(): string {....raises: [ValueError, OSError, NotImplementedError, + FileNotFoundError], tags: [ReadEnvEffect], + forbids: [].}
proc gettempprefix(): string {....raises: [], tags: [], forbids: [].}
proc TemporaryDirectory(suffix = sNone; prefix = sNone; dir = sNone; + ignore_cleanup_errors = False; delete = True): TemporaryDirectoryWrapper {....raises: [ + ValueError, OSError, NotImplementedError, FileNotFoundError, Exception, + IOError], tags: [ReadEnvEffect, RootEffect, WriteDirEffect, ReadDirEffect], + forbids: [].}
Example:
+import std/os +let d = TemporaryDirectory() +assert dirExists d.name +d.cleanup() +assert not dirExists d.name+ Source +Edit + +
template name(self: TemporaryFileWrapper): string
template NamedTemporaryFile(mode: static[string | char] = "w+b"; buffering = -1; + encoding = DefEncoding; newline = DefNewLine; + suffix = sNone; prefix = sNone; dir = sNone; + delete = True; errors = DefErrors): TemporaryFileWrapper
Example:
+var tempf = NamedTemporaryFile("w+t") +let msg = "test" +tempf.write(msg) +tempf.flush() +tempf.seek(0) +let s = tempf.read() +assert s == msg + +import std/os +assert fileExists tempf.name +tempf.close() +assert not fileExists tempf.name+ Source +Edit + +
template read[IO](self: TemporaryFileWrapper[IO]; + args`gensym17: varargs[typed]): untyped
template readline[IO](self: TemporaryFileWrapper[IO]; + args`gensym18: varargs[typed]): untyped
template seek[IO](self: TemporaryFileWrapper[IO]; + args`gensym19: varargs[typed]): untyped
template tell[IO](self: TemporaryFileWrapper[IO]; + args`gensym20: varargs[typed]): untyped
template write[IO](self: TemporaryFileWrapper[IO]; + args`gensym16: varargs[typed]): untyped
+
the only difference with Python's is where some types in time is str, there is string in n_time's.
+e.g. n_time.ctime() returns a string
+ +Currently, tm_name is either "LOCAL" or "Etc/UTC", due to std/times only returning those two.
+DefaultTimeFormat = "%a %b %d %H:%M:%S %Y"
proc asctime(): string {....raises: [], tags: [TimeEffect], forbids: [].}
func asctime(t: struct_time): string {....raises: [], tags: [], forbids: [].}
func asctime(tup: struct_time_tuple): typeof(asctime do: + bind struct_time + struct_time(tm_year: 1900, tm_mon: 1, tm_mday: 1, tm_yday: 1, tm_isdst: -1)) {. + ...raises: [], tags: [], forbids: [].}
func asctime(tup: struct_time_tuple10): typeof(asctime do: + bind struct_time + struct_time(tm_year: 1900, tm_mon: 1, tm_mday: 1, tm_yday: 1, tm_isdst: -1)) {. + ...raises: [], tags: [], forbids: [].}
func asctime(tup: struct_time_tuple11): typeof(asctime do: + bind struct_time + struct_time(tm_year: 1900, tm_mon: 1, tm_mday: 1, tm_yday: 1, tm_isdst: -1)) {. + ...raises: [], tags: [], forbids: [].}
proc strptime(s: string): struct_time {....raises: [ValueError, TimeParseError, + TimeFormatParseError], tags: [TimeEffect], forbids: [].}
n_timeit: timeit for Nim.
+see Lib/timeit for python compatiable APIs
+ +NullaryFunc = concept self + self()
TimeitParam = string | NullaryFunc
default_timer = default_timer_defval
default_number = 1000000
default_repeat = 5
proc newTimer(stmt: TimeitParam = NullStmt; setup: TimeitParam = NullStmt; + timer = default_timer; number = default_number): Timer
template repeat(self: Timer; repeat = default_repeat; number = default_number): seq[ + float]
template repeat(stmt: TimeitParam = NullStmt; setup: TimeitParam = NullStmt; + timer = default_timer; repeat = default_repeat; + number = default_number): seq[float]
template timeit(repetitions: int; statements: untyped)
EXT. unstable.
+returns nothing but send output to stdout.
+output shows more information than Pythons.
+ +Example:
+var i = 0 +timeit(10): + i.inc +assert i == 10+ Source +Edit + +
template timeit(stmt: TimeitParam = NullStmt; setup: TimeitParam = NullStmt; + timer = default_timer; number = default_number): float
timeit(stmt, setup, number=1000000) with globals is globals()|locals()
+stmt, setup are Callable or str literal
+ +Example:
+discard timeit("i.inc", "var i = 0") +assert i != 0 + +proc f() = discard +discard timeit(f) +proc retf(): int = 1 +discard timeit(retf)+ Source +Edit + +
EXT. Nim's codec. not the same as Python's codec
+EncErrors {.pure.} = enum + strict, ## - raise a ValueError error (or a subclass) + ignore, ## - ignore the character and continue with the next + replace, ## - replace with a suitable replacement character; + ## Python will use the official U+FFFD REPLACEMENT + ## CHARACTER for the builtin Unicode codecs on + ## decoding and "?" on encoding. + surrogateescape, ## - replace with private code points U+DCnn. + xmlcharrefreplace, ## - Replace with the appropriate XML + ## character reference (only for encoding). + backslashreplace, ## - Replace with backslashed escape sequences. + namereplace ## - Replace with \N{...} escape sequences + ## (only for encoding).
NCodecInfo = object + name*: string + errors*: string + encode*, decode*: EncoderCvt + close*: EncoderClose
func initNCodecInfo(encoding: string; errors = DefErrors): NCodecInfo {. + ...raises: [LookupError], tags: [], forbids: [].}
see docs.python.org/3/library/os.html
+Also export everything of std/os
+uname_result = tuple[sysname, nodename, release, version, machine: PyStr]
proc cpu_count(): OptionalObj[int] {....raises: [], tags: [], forbids: [].}
proc getrandom(size: int; flags = 0): PyBytes {....raises: [], tags: [], + forbids: [].}
proc process_cpu_count(): OptionalObj[int] {....raises: [], tags: [], forbids: [].}
proc uname(): uname_result {....raises: [PyOSError], tags: [], forbids: [].}
SEEK_* is in ./posix_like/seek_c
+O_NONBLOCK {.importc: "O_NONBLOCK", header: "<fcntl.h>".}: cint
supports_dir_fd = (data: [(0, ""), (0, ""), (-5621059606328173438, "chmod"), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (-8228877975097993322, "stat"), (0, ""), + (0, ""), (0, ""), (0, ""), + (-4711118966769550309, "rmdir"), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (2912131129587157308, "unlink"), + (-8854294602768111171, "open"), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, "")], counter: 5)
supports_effective_ids = (data: [(0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, "")], counter: 0)
supports_fd = (data: [(0, ""), (0, ""), (-5621059606328173438, "chmod"), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (-8228877975097993322, "stat"), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (-8294136327585020825, "truncate"), (0, ""), + (0, ""), (6400877751686740842, "scandir"), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, "")], counter: 4)
supports_follow_symlinks = (data: [(0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), + (-8228877975097993322, "stat"), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, ""), (0, ""), + (0, ""), (0, ""), (0, ""), (0, "")], + counter: 1)
macro issuperset(s: HaveFunc; fns: untyped): bool
proc get_handle_inheritable(handle: int): bool {....raises: [], tags: [], + forbids: [].}
proc get_inheritable(fd: int): bool {....raises: [PyOSError], tags: [], forbids: [].}
proc Py_set_inheritable(fd: int; inheritable: bool; atomic_flag_works: ptr int): int {. + ...raises: [PyOSError], tags: [WriteIOEffect], forbids: [].}
proc set_handle_inheritable(handle: int; inheritable: bool) {....raises: [], + tags: [], forbids: [].}
proc set_inheritable(fd: int; inheritable: int | bool)
proc set_inheritableImpl(fd: int; inheritable: bool) {....raises: [PyOSError], + tags: [WriteIOEffect], forbids: [].}
proc nestListWithFirst(op: NimNode; pack: NimNode; first: NimNode): NimNode {. + ...raises: [], tags: [], forbids: [].}
proc samestat(s1, s2: stat_result): bool {....raises: [], tags: [], forbids: [].}
func splitdrive[T](p: PathLike[T]): (T, T)
posixmodule, also mimic posix api for Windows
+proc dir_fdandfdinvalid(function_name: string; dir_fd: int; fd: int): bool {. + discardable, ...raises: [ValueError], tags: [], forbids: [].}
proc dir_fdandfollow_symlinksinvalid(function_name: string; dir_fd: int; + follow_symlinks: bool): bool {.discardable, + ...raises: [ValueError], tags: [], forbids: [].}
proc fdandfollow_symlinksinvalid(function_name: string; fd: int; + follow_symlinks: bool): bool {.discardable, + ...raises: [ValueError], tags: [], forbids: [].}
proc follow_symlinks_specified(function_name: string; follow_symlinks: bool): bool {. + discardable, ...raises: [NotImplementedError], tags: [], forbids: [].}
proc pathanddir_fdinvalid(function_name: string; path: Path; dir_fd: int): bool {. + discardable.}
template dir_fdandfdinvalid(dir_fd; fd): untyped {.dirty.}
template dir_fdandfollow_symlinksinvalid(dir_fd; follow_symlinks): untyped {. + dirty.}
template fdandfollow_symlinksinvalid(fd; follow_symlinks): untyped {.dirty.}
template follow_symlinks_specified(follow_symlinks: bool): untyped
template pathanddir_fdinvalid(path; dir_fd): untyped {.dirty.}
template importConfig(name)
proc is_junction(self: DirEntry): bool
func is_symlink(self: DirEntry): bool
proc scandir(): ScandirIterator[PyStr] {....raises: [], tags: [], forbids: [].}
proc stat(self: DirEntry; follow_symlinks = true): stat_result
template SEEK_DATA(): int
not defined in Windows
+stat_result = ref object + data*: Stat ## inner, used by `getattr` of `stat_result`
func `[]`(self: stat_result; i: int): BiggestInt {....raises: [], tags: [], + forbids: [].}
proc fstat(fd: int): stat_result {....raises: [PyOSError], tags: [], forbids: [].}
proc lstat[T](path: PathLike[T]; dir_fd = DEFAULT_DIR_FD): stat_result
proc Py_fstat_noraise(fd: int; status: var Stat): cint {....raises: [], tags: [], + forbids: [].}
EXT.
+fileutils.c _Py_fstat_noraise
+ + Source +Edit + +func st_atime(self`gensym1: stat_result): float {....raises: [], tags: [], + forbids: [].}
func st_atime_ns(self`gensym1: stat_result): BiggestInt {....raises: [], tags: [], + forbids: [].}
func st_ctime(self`gensym3: stat_result): float {....raises: [], tags: [], + forbids: [].}
func st_ctime_ns(self`gensym3: stat_result): BiggestInt {....raises: [], tags: [], + forbids: [].}
func st_mtime(self`gensym2: stat_result): float {....raises: [], tags: [], + forbids: [].}
func st_mtime_ns(self`gensym2: stat_result): BiggestInt {....raises: [], tags: [], + forbids: [].}
proc stat(path: int; dir_fd = DEFAULT_DIR_FD; follow_symlinks = true): stat_result {. + ...raises: [ValueError], tags: [], forbids: [].}
proc stat[T](path: PathLike[T]; dir_fd = DEFAULT_DIR_FD; follow_symlinks = true): stat_result
proc unlinkImpl(p: PathLike)
terminal_size = tuple[columns, lines: int]
proc get_terminal_size(fd = STDOUT_FILENO): terminal_size {....raises: [], + tags: [], forbids: [].}
minics Python's os.get_terminal_size.
+but if you are using Nim's stdlib, terminalSize<https://nim-lang.org/docs/terminal.html#terminalSize> in std/terminal does futher than even Python's shutil.get_terminal_size
+ + Source +Edit + +proc removedirs(d: PathLike)
WCONTINUED = int(cWCONTINUED)
proc wait(): tuple[pid: int, status: int] {....raises: [], tags: [], forbids: [].}
proc wait3(options: int): tuple[pid: int, status: int, rusage: struct_rusage] {. + ...raises: [], tags: [], forbids: [].}
proc wait4(pid: int; options: int): tuple[pid: int, status: int, + rusage: struct_rusage] {....raises: [], tags: [], forbids: [].}
proc waitpid(pid: int; options: int): tuple[pid: int, status: int] {....raises: [], + tags: [], forbids: [].}
proc waitstatus_to_exitcode(status: int): int {....raises: [], tags: [], + forbids: [].}
proc WEXITSTATUS(status: int): bool {....raises: [], tags: [], forbids: [].}
proc WIFCONTINUED(status: int): bool {....raises: [], tags: [], forbids: [].}
proc WIFSIGNALED(status: int): bool {....raises: [], tags: [], forbids: [].}
proc WIFSTOPPED(status: int): bool {....raises: [], tags: [], forbids: [].}
walk_symlinks_as_files = WalkSymlinksAsFiles(proc () {.noconv.} = discard )
shallIgnore: OnErrorCb = nil
proc hardlink_to(self: Path; target: string | Path)
proc read_bytes(self: Path): PyBytes {....raises: [IOError], tags: [ReadIOEffect], + forbids: [].}
proc symlink_to(self: Path; target: string | Path; target_is_directory = false)
proc write_bytes(self: Path; b: PyBytes) {....raises: [IOError], + tags: [WriteIOEffect], forbids: [].}
proc write_text(self: Path; data: PyStr; encoding = DefEncoding; + errors = DefErrors): int {.discardable, + ...raises: [ValueError, LookupError, PyOSError, Exception], tags: [RootEffect], + forbids: [].}
template open(self: Path; mode: StringLike = "r"; buffering = -1; + encoding = DefEncoding; errors = DefErrors; newline = DefNewLine): untyped
proc is_absolute(self: Path): bool {....raises: [], tags: [], forbids: [].}
proc is_relative_to(self: Path; other: Path): bool {....raises: [Exception], + tags: [RootEffect], forbids: [].}
proc is_relative_to(self: Path; other: string): bool {....raises: [Exception], + tags: [RootEffect], forbids: [].}
proc is_symlink(self: Path): bool {....raises: [], tags: [ReadDirEffect], + forbids: [].}
proc mkdirParentsExistsOk(self: Path) {....raises: [OSError, IOError], + tags: [WriteDirEffect, ReadDirEffect], + forbids: [].}
EXT. equal to path.mkdir(parents=True, exists_ok=True)
+not for JS backend
+ + Source +Edit + +proc read_nstring(self: Path): string {....raises: [IOError], tags: [ReadIOEffect], + forbids: [].}
proc write_nstring(self, s: string) {....raises: [IOError], tags: [WriteIOEffect], + forbids: [].}
func python_implementation(): PyStr {.inline, ...raises: [], tags: [], forbids: [].}
used by Lib/os and Lib/platform
+platform.system = "Linux"
proc ac_md_release(): string {....raises: [OSError, IOError], + tags: [ExecIOEffect, ReadIOEffect, RootEffect], + forbids: [].}
proc platform.version(): string {....raises: [OSError, IOError], tags: [ + ExecIOEffect, ReadIOEffect, RootEffect], forbids: [].}
proc uname_release_major(): string {....raises: [OSError, IOError], tags: [ + ExecIOEffect, ReadIOEffect, RootEffect], forbids: [].}
TODO: PyRandom uses method; impl SysRandom TODO: commandLine pysince(3,13)
+ +func triangular[F: SomeFloat](self: PyRandom; low: F = 0.0; high: F = 1.0; + mode: F | NoneType = None): F
template triangular[F: SomeFloat](low: F = 0.0; high: F = 1.0; + mode: F | NoneType = None): F
replace justLessThanOne declaration with hard-coded constant if you wanna get rid of n_math dependence
+ +justLessThanOne = 0.9999999999999999
functions and methods that can be directly dispatched to std/random
+func genrand_uint32(self: PyRandom): uint32 {....raises: [], tags: [], forbids: [].}
proc getstate(): PyRandomState {....raises: [], tags: [], forbids: [].}
proc setstate(state: PyRandomState) {....raises: [], tags: [], forbids: [].}
template genrand_uint32(): uint32
func betavariate(self: PyRandom; alpha, beta: float): float {. + ...raises: [ValueError], tags: [], forbids: [].}
Beta distribution.
+Conditions on the parameters are alpha > 0 and beta > 0. Returned values range between 0 and 1.
+The mean (expected value) and variance of the random variable are:
+E[X] = alpha / (alpha + beta) + Var[X] = alpha * beta / ((alpha + beta)**2 * (alpha + beta + 1))+ + Source +Edit + +
func binomialvariate(self: PyRandom; n = 1.0; p = 0.5): float {. + ...raises: [ValueError], tags: [], forbids: [].}
Binomial random variable.
+Gives the number of successes for n independent trials with the probability of success in each trial being p:
+sum(random() < p for i in range(n))
+Returns an integer in the range: 0 <= X <= n
+The mean (expected value) and variance of the random variable are:
+E[X] = n * p +Var[x] = n * p * (1 - p)+ + Source +Edit + +
func expovariate(self: PyRandom; lambd = 1.0): float {....raises: [], tags: [], + forbids: [].}
func gammavariate(self: PyRandom; alpha, beta: float): float {. + ...raises: [ValueError], tags: [], forbids: [].}
func lognormalvariate(self: PyRandom; mu, sigma: float): float {....raises: [], + tags: [], forbids: [].}
func normalvariate(self: PyRandom; mu = 0.0; sigma = 1.0): float {....raises: [], + tags: [], forbids: [].}
func paretovariate(self: PyRandom; alpha: float): float {....raises: [], tags: [], + forbids: [].}
func triangular[F: SomeFloat](self: PyRandom; low: F = 0.0; high: F = 1.0): F
func triangular[F: SomeFloat](self: PyRandom; low: F = 0.0; high: F = 1.0; + mode: F): F
func vonmisesvariate(self: PyRandom; mu, kappa: float): float {....raises: [], + tags: [], forbids: [].}
func weibullvariate(self: PyRandom; alpha, beta: float): float {....raises: [], + tags: [], forbids: [].}
Weibull distribution.
+alpha is the scale parameter and beta is the shape parameter.
+ + Source +Edit + +method getrandbits(self: PyRandom; k: int): int {.base, ...raises: [], tags: [], + forbids: [].}
template betavariate(alpha, beta: float): float
template binomialvariate(n = 1.0; p = 0.5): float
template expovariate(lambd = 1.0): float
template gammavariate(alpha, beta: float): float
template getrandbits(k: int): int
template lognormalvariate(mu, sigma: float): float
template normalvariate(mu = 0.0; sigma = 1.0): float
template paretovariate(alpha: float): float
template shuffleImpl(self: PyRandom; x)
template triangular[F: SomeFloat](low: F = 0.0; high: F = 1.0): F
template triangular[F: SomeFloat](low: F = 0.0; high: F = 1.0; mode: F): F
template vonmisesvariate(mu, kappa: float): float
template weibullvariate(alpha, beta: float): float
RLIMIT_CORE = int(cRLIMIT_CORE)
RLIMIT_CPU = int(cRLIMIT_CPU)
RLIMIT_DATA = int(cRLIMIT_DATA)
RLIMIT_FSIZE = int(cRLIMIT_FSIZE)
RLIMIT_MEMLOCK = int(cRLIMIT_MEMLOCK)
RLIMIT_MSGQUEUE = int(cRLIMIT_MSGQUEUE)
RLIMIT_NICE = int(cRLIMIT_NICE)
RLIMIT_NOFILE = int(cRLIMIT_NOFILE)
RLIMIT_NPROC = int(cRLIMIT_NPROC)
RLIMIT_OFILE = int(cRLIMIT_OFILE)
RLIMIT_RSS = int(cRLIMIT_RSS)
RLIMIT_RTPRIO = int(cRLIMIT_RTPRIO)
RLIMIT_RTTIME = int(cRLIMIT_RTTIME)
RLIMIT_SIGPENDING = int(cRLIMIT_SIGPENDING)
RLIMIT_STACK = int(cRLIMIT_STACK)
RUSAGE_CHILDREN = int(cRUSAGE_CHILDREN)
RUSAGE_SELF = int(cRUSAGE_SELF)
RLIM_INFINITY = 0xFFFFFFFF'u
RUSAGE_THREAD = 1
proc checked_resource(resource: int): cint {....raises: [ValueError], tags: [], + forbids: [].}
proc getpagesize(): int {....raises: [], tags: [], forbids: [].}
proc getrusage(who: int): struct_rusage {....raises: [ValueError, PyOSError], + tags: [], forbids: [].}
struct_rusage = ref object + ru_utime*: float + ru_stime*: float + ru_maxrss*: int + ru_ixrss*: int + ru_idrss*: int + ru_isrss*: int + ru_minflt*: int + ru_majflt*: int + ru_nswap*: int + ru_inblock*: int + ru_oublock*: int + ru_msgsnd*: int + ru_msgrcv*: int + ru_nsignals*: int + ru_nvcsw*: int + ru_nivcsw*: int
proc toPyObject(rusage: Rusage): struct_rusage {....raises: [], tags: [], + forbids: [].}
SameFileError = object of Error
proc copyfileobj(s, d: File; length = COPY_BUFSIZE) {. + ...raises: [IOError, OSError], tags: [WriteIOEffect, ReadIOEffect], forbids: [].}
shutil.copyfileobj but for Nim's File
+if length is negative, it means copying the data without looping over the source data in chunks
+ + Source +Edit + +proc get_terminal_size(fallback = (80, 24)): terminal_size {....raises: [], + tags: [ReadEnvEffect], forbids: [].}
call os.get_terminal_size. This is a wrapper around terminalSize of std/terminal, which is more steady, returning meaningful result even when stdout is not associatd with a terminal.
+ + Source +Edit + +proc pthread_sigmask(how: int; mask: Sigset): PySet[int] {....raises: [PyOSError], + tags: [], forbids: [].}
proc sigpending(): PySet[int] {....raises: [PyOSError], tags: [], forbids: [].}
proc strsignal(signalnum: int): OptionalObj[PyStr] {....raises: [ValueError], + tags: [], forbids: [].}
proc valid_signals(): PySet[int] {....raises: [PyOSError], tags: [], forbids: [].}
proc PyErr_CheckSignals(): int {....raises: [], tags: [], forbids: [].}
proc PyErr_CheckSignalsAndRaises() {....raises: [], tags: [], forbids: [].}
proc toCSighandler(p: PySigHandler): CSigHandler {....raises: [], tags: [], + forbids: [].}
proc toPySighandler(p: CSigHandler | NimSigHandler): PySigHandler
ITIMER_PROF = int(ITIMER_PROF)
ITIMER_REAL = int(ITIMER_REAL)
ITIMER_VIRTUAL = int(ITIMER_VIRTUAL)
SIG_SETMASK = add_member(Sigmasks, "SIG_SETMASK", 2'i32)
SIG_UNBLOCK = add_member(Sigmasks, "SIG_UNBLOCK", 1'i32)
proc `$`(self: Handlers): string {....raises: [KeyError], tags: [], forbids: [].}
proc `==`(self: Handlers; other: Handlers): bool {....raises: [], tags: [], + forbids: [].}
proc add_alias(self: Handlers; name: string) {....raises: [KeyError, NameError], + tags: [], forbids: [].}
proc add_member(enum_class: typedesc[Handlers]; name: string; value: int): Handlers
proc add_member(enum_class: typedesc[Sigmasks]; name: string; value: int): Sigmasks
proc add_member(enum_class: typedesc[Signals]; name: string; value: int): Signals
proc hash(self: Handlers): Hash {....raises: [KeyError], tags: [], forbids: [].}
proc name(self: Handlers): string {.inline, ...raises: [KeyError], tags: [], + forbids: [].}
proc repr(self: Handlers): string {....raises: [KeyError], tags: [], forbids: [].}
proc getFrameOrNil(): PFrame {....raises: [], tags: [], forbids: [].}
proc getFrameOrNil(up: int): PFrame {....raises: [], tags: [], forbids: [].}
template Py_atomic_load[T](obj: T): T
template Py_atomic_load_ptr[T](obj: ptr T): T
template Py_atomic_store[T](obj: T; value: T)
template Py_atomic_store_ptr[T](obj: ptr T; value: T)
struct_siginfo = ref object
proc fill_siginfo(si: SigInfo): struct_siginfo {....raises: [], tags: [], + forbids: [].}
proc si_band(self: struct_siginfo): auto {....raises: [], tags: [], forbids: [].}
proc si_code(self: struct_siginfo): auto {....raises: [], tags: [], forbids: [].}
proc si_errno(self: struct_siginfo): auto {....raises: [], tags: [], forbids: [].}
proc si_pid(self: struct_siginfo): auto {....raises: [], tags: [], forbids: [].}
proc si_signo(self: struct_siginfo): auto {....raises: [], tags: [], forbids: [].}
proc si_status(self: struct_siginfo): auto {....raises: [], tags: [], forbids: [].}
proc si_uid(self: struct_siginfo): auto {....raises: [], tags: [], forbids: [].}
proc getsignal(signalnum: int): PySigHandler {....raises: [ValueError], tags: [], + forbids: [].}
proc pidfd_send_signal(pid: int; sig: int; siginfo: struct_siginfo = nil; + flags = 0) {....raises: [PyOSError], tags: [], forbids: [].}
proc raise_signal(signalnum: int) {....raises: [PyOSError], tags: [], forbids: [].}
proc default_int_handler(signalnum: int; frame: PFrame) {. + ...raises: [KeyboardInterrupt], tags: [], forbids: [].}
proc set_wakeup_signal(signalnum: int): int {....raises: [], tags: [], forbids: [].}
proc signal(signalnum: int; handler: CSigHandler | NimSigHandler | Handlers): PySigHandler {. + discardable.}
proc signal(signalnum: int; handler: PySigHandler): PySigHandler {.discardable, + ...raises: [ValueError, PyOSError], tags: [], forbids: [].}
template fromIterable(result: var Sigset; obj)
proc add_sigset(res: var Set[int]; mask: var Sigset)
proc sigset_to_set(mask: var Sigset): HashSet[int] {....raises: [], tags: [], + forbids: [].}
XXX: FIXED-NIM-BUG: though nimAllowNonVarDestructor is defined at least since 2.0.6, it still cannot be compiled till abour 2.1.1
+signal_state_t = object + handlers*: array[Py_NSIG, handler] + when DWin: + sigint_event*: Handle + default_handler*, ignore_handler*: PySigHandler
proc get_handler(i: cint): PySigHandler {....raises: [], tags: [], forbids: [].}
proc initPySignal(install_signal_handlers: bool) {....raises: [], tags: [], + forbids: [].}
proc PySignal_Fini() {....raises: [], tags: [], forbids: [].}
proc set_handler(i: cint; fn: PySigHandler) {....raises: [], tags: [], forbids: [].}
template signal_global_state(): signal_state_t
ItimerError = object of PyOSError
proc pthread_kill(thread_id: uint; signalnum: int) {....raises: [PyOSError], + tags: [], forbids: [].}
proc pthread_sigmask(how: int; mask: Sigset): Set[int] {....raises: [PyOSError], + tags: [], forbids: [].}
proc siginterrupt(signalnum, flag: int) {....raises: [ValueError, PyOSError], + tags: [], forbids: [].}
proc sigpending(): Set[int] {....raises: [PyOSError], tags: [], forbids: [].}
proc sigtimedwait(sigset: Sigset; timeout: Timestamp): struct_siginfo
proc sigwaitinfo(sigset: Sigset): struct_siginfo {....raises: [PyOSError], + tags: [], forbids: [].}
have_valid_signals = true
proc fill_valid_signals(res: var Set[int])
ascii_letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
ascii_lowercase = "abcdefghijklmnopqrstuvwxyz"
ascii_uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
printable = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%&\\\'()*+,-./:;<=>?@[\\\\]^_`{|}~ \t\n\r\v\f"
punctuation = """!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~"""
whitespace = " \t\n\r\v\f"
func capwords(a: StringLike): PyStr
Mimics Python string.capwords(s) -> str:
+Runs of whitespace characters are replaced by a single space and leading and trailing whitespace are removed.
+ + Source +Edit + +func capwords(a: StringLike; sep: StringLike): PyStr
Mimics Python string.capwords(s, sep) -> str:
+Split the argument into words using split, capitalize each word using capitalize, and join the capitalized words using join. sep is used to split and join the words.
+ + Source +Edit + +macro safe_substitute(templ: Template; kws: varargs[untyped]): PyStr
ascii_letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
ascii_lowercase = "abcdefghijklmnopqrstuvwxyz"
ascii_uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
printable = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%&\\\'()*+,-./:;<=>?@[\\\\]^_`{|}~ \t\n\r\v\f"
punctuation = """!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~"""
whitespace = " \t\n\r\v\f"
proc initIgnoreExcHandle(): ExcHandle {....raises: [], tags: [], forbids: [].}
proc initRaisesExcHandle(): ExcHandle {....raises: [], tags: [], forbids: [].}
proc initSubsCfg(excHandle = initRaisesExcHandle(); delimiter = Delimiter): SubsCfg {. + ...raises: [], tags: [], forbids: [].}
proc resetSubsCfg(cfg: SubsCfg; excHandle = initRaisesExcHandle(); + delimiter = Delimiter) {....raises: [], tags: [], forbids: [].}
proc substituteAux[M](templ: string; m: M; excHandle = initRaisesExcHandle(); + delimiter = Delimiter): string
iterator getIdentifiers(templ: string): string {....raises: [Exception], + tags: [RootEffect], forbids: [].}
iterator get_identifiersMayDup(templ: Template): string {....raises: [Exception], + tags: [RootEffect], forbids: [].}
template genSubstitute(M; Key; sym; doExc) {.dirty.}
Lib/sys
orig_argv = newPyListOfCap(argc)
float_repr_style = "short"
hexversion = 51577072
implementation = ("pynim", (0, 9, 11, "alpha", 0), 51577072, false)
platform = "linux"
and haiku/netbsd appended with major version instead of "unknown". In short, this won't be "unknown" as Python does.
+ + Source +Edit + +version_info = (3, 13, 0, "final", 0)
proc getdefaultencoding(): PyStr {....raises: [], tags: [], forbids: [].}
proc getfilesystemencoding(): PyStr {....raises: [], tags: [], forbids: [].}
template addaudithook(hook: HookProc)
template executable(): PyStr
When not defined(release) or defined(pylibSysAudit), audit will be enabled. Otherwise, it will be disabled.
+config_should_audit = false
template whenAuditEnabled(body)
template whenAuditEnabledOr[T](exp, elseExp: T): T
template addaudithook(hook: HookProc)
template PySys_AddAuditHook(hook: HookProc; userData = default Any)
template PySys_Audit(event: string; args: varargs[typed])
float_info = (max: 1.7976931348623157e+308, max_exp: 1024, max_10_exp: 308, + min: 2.2250738585072014e-308, min_exp: -1021, min_10_exp: -307, + dig: 15, mant_dig: 53, epsilon: 2.220446049250313e-16, radix: 2)
float_repr_style = "short"
flags = (debug: debug, inspect: inspect, interactive: interactive, + isolated: isolated, optimize: optimize, + dont_write_bytecode: dont_write_bytecode, no_user_site: no_user_site, + no_site: no_site, ignore_environment: ignore_environment, + verbose: verbose, bytes_warning: bytes_warning, quiet: quiet, + hash_randomization: hash_randomization, dev_mode: dev_mode, + utf8_mode: utf8_mode, safe_path: safe_path, + int_max_str_digits: int_max_str_digits, + warn_default_encoding: warn_default_encoding)
PYTHON* environment variables will be loaded iif pylibUsePyEnv is defined.
+bytes_warning {.intdefine: bytes_warning.toCfgName.} = 0
dont_write_bytecode {.intdefine: dont_write_bytecode.toCfgName.} = 1
hash_randomization {.intdefine: hash_randomization.toCfgName.} = 0
ignore_environment {.intdefine: ignore_environment.toCfgName.} = 0
int_max_str_digits {.intdefine: int_max_str_digits.toCfgName.} = 4300
interactive {.intdefine: interactive.toCfgName.} = 0
no_user_site {.intdefine: no_user_site.toCfgName.} = 0
warn_default_encoding {.intdefine: warn_default_encoding.toCfgName.} = 0
macro genFlagsObj()
macro redefineFlags(kws: varargs[untyped])
dont_write_bytecode = ib_b(toPyEnv("dont_write_bytecode"), dont_write_bytecode)
int_max_str_digits = ib_i(toPyEnv("int_max_str_digits"), int_max_str_digits)
no_user_site = ib_b(toPyEnv("no_user_site"), no_user_site)
warn_default_encoding = ib_e(toPyEnv("warn_default_encoding"), + warn_default_encoding)
proc getdefaultencoding(): string {....raises: [], tags: [], forbids: [].}
Return the current default encoding used by the Unicode implementation.
+Always "utf-8" in Nim
+ + Source +Edit + +proc getfilesystemencoding(): string {....raises: [], tags: [], forbids: [].}
stderr = newNoEncTextIO(stderr, "<stderr>", DefNewLine)
stdin = newNoEncTextIO(stdin, "<stdin>", DefNewLine)
stdout = newNoEncTextIO(stdout, "<stdout>", DefNewLine)
dunder_stderr = stderr
dunder_stdin = stdin
dunder_stdout = stdout
weirdTarget = false
proc gettempdir(): PyStr {....raises: [ValueError, OSError, NotImplementedError, + FileNotFoundError], tags: [ReadEnvEffect], + forbids: [].}
proc gettempdirb(): PyBytes {....raises: [ValueError, OSError, NotImplementedError, + FileNotFoundError], + tags: [ReadEnvEffect], forbids: [].}
proc gettempprefix(): PyStr {....raises: [ValueError, OSError, NotImplementedError, + FileNotFoundError], + tags: [ReadEnvEffect], forbids: [].}
proc gettempprefixb(): PyBytes {....raises: [ValueError, OSError, + NotImplementedError, FileNotFoundError], tags: [ReadEnvEffect], forbids: [].}
template name(self: TemporaryFileWrapper): PyStr
time
+Currently the implementation is n_time module . The following is its doc:
+DefaultTimeFormat = "%a %b %d %H:%M:%S %Y"
proc asctime(): PyStr {....raises: [], tags: [TimeEffect], forbids: [].}
func asctime(t: Some_struct_time): PyStr
Example:
+assert asctime(gmtime(0)) == "Thu Jan 1 00:00:00 1970"+ Source +Edit + +
proc strptime(s: PyStr; format = DefaultTimeFormat): struct_time {. + ...raises: [ValueError, TimeParseError, TimeFormatParseError], + tags: [TimeEffect], forbids: [].}
func dtToStructTime(dt: DateTime; res: var struct_time) {....raises: [], tags: [], + forbids: [].}
func struct_time(tup`gensym0: struct_time_tuple): struct_time {....raises: [], + tags: [], forbids: [].}
func struct_time(tup`gensym2: struct_time_tuple10): struct_time {....raises: [], + tags: [], forbids: [].}
func struct_time(tup`gensym4: struct_time_tuple11): struct_time {....raises: [], + tags: [], forbids: [].}
func structTimeToDt(st: struct_time; res: var DateTime) {....raises: [], tags: [], + forbids: [].}
converter toTuple(st: struct_time): struct_time_tuple {....raises: [], tags: [], + forbids: [].}
func monotonic_ns(): int64 {....raises: [], tags: [TimeEffect], forbids: [].}
func perf_counter(): float {....raises: [], tags: [TimeEffect], forbids: [].}
func perf_counter_ns(): int64 {....raises: [], tags: [TimeEffect], forbids: [].}
func process_time(): float {....raises: [], tags: [TimeEffect], forbids: [].}
strftime, strptime
+platform independent implementation.
+ +NotImplDirectives = {'y', 'Z'}
Here are their concrete meanings in Python, as well as some notes about why they cannot be directly mapped to Nim's DateTime.format/parse.
+The direct alternative value when formatting in Nim, if any, is introduced by <-:
+Following are strftime only currently:
+proc strptime(dt: var DateTime; s: string; format_with_sp_asis: string) {. + ...raises: [ValueError, TimeParseError, TimeFormatParseError], + tags: [TimeEffect], forbids: [].}
macro addFields(res: string; obj: typed; noMoreThan: static[int] = int.high)
obj is of object or ref object. when obj is of object and noMoreThan is not given, it's roughly equal to:
+let startLen = res.len +for k, v in o.fieldPairs: + res.addSep(sep=", ", startLen = startLen) + res.add k & '=' & repr v+ + Source +Edit + +
macro asgSeqToObj(tup, obj: typed)
macro cmpOnField(a, b: typed): int
macro declTupleWithNFieldsFrom(name: untyped; Cls: typedesc; n: static[int]; + exported: static[bool] = true)
macro mixinOrderOnFields(lhs, rhs: typed; cmpOp; + cmpStragy: static[CmpStragy] = csEq): bool
cmpOnFields but a b can be of different types.
+e.g. a is tuple and b is object; or a, b are different objects.
+ + Source +Edit + +macro orderOnFields[T](a, b: T; cmpOp): bool
mainly for checking if ref objects are equal on fields
+when for object/tuple and cmpOp is ==, roughly equal to: a == b
+but system.== for ref just compare the address.
+ + Source +Edit + +func strftime(format: string; st: Some_struct_time_tuple): string
func strftime(format: string; st: struct_time): string {....raises: [], tags: [], + forbids: [].}
func strftime[S](format: S; st: struct_time): S
proc strptime(s: string; f: string): struct_time {. + ...raises: [ValueError, TimeParseError, TimeFormatParseError], + tags: [TimeEffect], forbids: [].}
funcs about struct_time
+its initializer, and a inverse function mktime
+ +proc gmtime(): struct_time {....raises: [], tags: [TimeEffect], forbids: [].}
proc gmtime(secs: float): struct_time {....raises: [], tags: [], forbids: [].}
proc gmtime(secs: int64): struct_time {....raises: [], tags: [], forbids: [].}
proc localtime(): struct_time {....raises: [], tags: [TimeEffect], forbids: [].}
proc localtime(secs: float): struct_time {....raises: [], tags: [], forbids: [].}
proc localtime(secs: int64): struct_time {....raises: [], tags: [], forbids: [].}
func mktime(t: struct_time): float {....raises: [], tags: [], forbids: [].}
func mktime(tup: struct_time_tuple): typeof(mktime do: + bind struct_time + struct_time(tm_year: 1900, tm_mon: 1, tm_mday: 1, tm_yday: 1, tm_isdst: -1)) {. + ...raises: [], tags: [], forbids: [].}
Some_struct_time = struct_time | Some_struct_time_tuple
Some_struct_time_tuple = struct_time_tuple | struct_time_tuple10 | + struct_time_tuple11
struct_time = ref object + tm_year*: int + tm_mon*: range[1 .. 12] + tm_mday*: MonthdayRange + tm_hour*: HourRange + tm_min*: MinuteRange + tm_sec*: range[0 .. 61] + tm_wday*: range[0 .. 6] + tm_yday*: range[1 .. 366] + tm_isdst*: int + tm_zone*: string ## .. warning:: curently is only "LOCAL" or "Etc/UTC" + tm_gmtoff*: int
struct_time_tuple = tuple[tm_year: int, tm_mon: range[1 .. 12], + tm_mday: range[1 .. 31], tm_hour: range[0 .. 23], + tm_min: range[0 .. 59], tm_sec: range[0 .. 61], + tm_wday: range[0 .. 6], tm_yday: range[1 .. 366], + tm_isdst: int]
struct_time_tuple10 = tuple[tm_year: int, tm_mon: range[1 .. 12], + tm_mday: range[1 .. 31], tm_hour: range[0 .. 23], + tm_min: range[0 .. 59], tm_sec: range[0 .. 61], + tm_wday: range[0 .. 6], tm_yday: range[1 .. 366], + tm_isdst: int, tm_zone: string]
struct_time_tuple11 = tuple[tm_year: int, tm_mon: range[1 .. 12], + tm_mday: range[1 .. 31], tm_hour: range[0 .. 23], + tm_min: range[0 .. 59], tm_sec: range[0 .. 61], + tm_wday: range[0 .. 6], tm_yday: range[1 .. 366], + tm_isdst: int, tm_zone: string, tm_gmtoff: int]
func `<`(a, b: struct_time): bool {....raises: [], tags: [], forbids: [].}
func `<`(a: struct_time; b: struct_time_tuple11): bool {....raises: [], tags: [], + forbids: [].}
func `<`(a: struct_time_tuple11; b: struct_time): bool {....raises: [], tags: [], + forbids: [].}
func `<`(st: struct_time; t: tuple): bool
func `<`(t: tuple; st: struct_time): bool
func `<=`(a, b: struct_time): bool {....raises: [], tags: [], forbids: [].}
func `<=`(a: struct_time; b: struct_time_tuple11): bool {....raises: [], tags: [], + forbids: [].}
func `<=`(a: struct_time_tuple11; b: struct_time): bool {....raises: [], tags: [], + forbids: [].}
func `<=`(st: struct_time; t: tuple): bool
func `<=`(t: tuple; st: struct_time): bool
func `==`(a, b: struct_time): bool {....raises: [], tags: [], forbids: [].}
func `==`(a: struct_time; b: struct_time_tuple11): bool {....raises: [], tags: [], + forbids: [].}
func `==`(a: struct_time_tuple11; b: struct_time): bool {....raises: [], tags: [], + forbids: [].}
func `==`(st: struct_time; t: tuple): bool {.inline.}
func `==`(t: tuple; st: struct_time): bool {.inline.}
func repr(st: struct_time): string {....raises: [], tags: [], forbids: [].}
struct_time.__repr__
+returns string starting with "time.struct_time" with 9 fields.
+ + Source +Edit + +template initStructTime(): struct_time
template initStructTime(year, mon, mday, hour, min, sec, wday, yday, isdst, + zone, gmtoff): struct_time
template isUtcZone(st: struct_time): bool
default_timer = pysince(3.3, perf_counter, default_timer)
default_repeat = 5
TimeItUseTime {.booldefine: "timeit.usetime".} = true
template repeat(self: Timer; repeat = pysince(3.7, 5, 3); + number = default_number): PyList[float]
template repeat(stmt: TimeitParam = NullStmt; setup: TimeitParam = NullStmt; + timer = default_timer; repeat = pysince(3.7, 5, 3); + number = default_number): PyList[float]
Example:
+assert len(repeat(repeat=0)) == 0+ Source +Edit + +
OptionalObj[T] = distinct Option[T]
proc isNone[T](self: OptionalObj[T]): bool
proc isSome[T](self: OptionalObj[T]): bool
proc newOptionalObj[T](): OptionalObj[T]
proc newOptionalObj[T](x: T): OptionalObj[T]
converter unsafeGet[T](self: OptionalObj[T]): T
converter unsafeToNone[T](self: OptionalObj[T]): NoneType
template expOptObjCvt()
proc newStrOptionalObj(x: string): OptionalObj[PyStr] {....raises: [], tags: [], + forbids: [].}
+ + +Welcome to NimPyLib 0.9.11
+ +Just write Python code in Nim!
The mostly suggested style is
+import pkg/pylib+
However, omitting the pkg/ prefix shall be fine at most cases:
+import pylib+ +
Cheatsheet for rough alternative between pylib and Python
+Nim pylib | Python |
---|---|
from pylib/Lib/LIB import nil | import LIB |
import pylib/Lib/LIB | from LIB import * |
from pylib/Lib/LIB import XXX | import LIB; from LIB import XXX |
Wondering how many libs are available in NimPylib?
+Here are the Lib Docs.
++ + +Welcome to NimPyLib 0.9.11
+ +Just write Python code in Nim!
The mostly suggested style is
+import pkg/pylib+
However, omitting the pkg/ prefix shall be fine at most cases:
+import pylib+ +
Cheatsheet for rough alternative between pylib and Python
+Nim pylib | Python |
---|---|
from pylib/Lib/LIB import nil | import LIB |
import pylib/Lib/LIB | from LIB import * |
from pylib/Lib/LIB import XXX | import LIB; from LIB import XXX |
Wondering how many libs are available in NimPylib?
+Here are the Lib Docs.
+EADDRINUSE {.importc, header: "<errno.h>".}: cint
EADDRNOTAVAIL {.importc, header: "<errno.h>".}: cint
EAFNOSUPPORT {.importc, header: "<errno.h>".}: cint
ECONNABORTED {.importc, header: "<errno.h>".}: cint
ECONNREFUSED {.importc, header: "<errno.h>".}: cint
ECONNRESET {.importc, header: "<errno.h>".}: cint
EDESTADDRREQ {.importc, header: "<errno.h>".}: cint
EHOSTUNREACH {.importc, header: "<errno.h>".}: cint
EINPROGRESS {.importc, header: "<errno.h>".}: cint
EKEYEXPIRED {.importc, header: "<errno.h>".}: cint
EKEYREJECTED {.importc, header: "<errno.h>".}: cint
EKEYREVOKED {.importc, header: "<errno.h>".}: cint
EMEDIUMTYPE {.importc, header: "<errno.h>".}: cint
ENAMETOOLONG {.importc, header: "<errno.h>".}: cint
ENETUNREACH {.importc, header: "<errno.h>".}: cint
ENOPROTOOPT {.importc, header: "<errno.h>".}: cint
ENOTRECOVERABLE {.importc, header: "<errno.h>".}: cint
EOPNOTSUPP {.importc, header: "<errno.h>".}: cint
EOWNERDEAD {.importc, header: "<errno.h>".}: cint
EPFNOSUPPORT {.importc, header: "<errno.h>".}: cint
EPROTONOSUPPORT {.importc, header: "<errno.h>".}: cint
EPROTOTYPE {.importc, header: "<errno.h>".}: cint
ESOCKTNOSUPPORT {.importc, header: "<errno.h>".}: cint
ETOOMANYREFS {.importc, header: "<errno.h>".}: cint
EWOULDBLOCK {.importc, header: "<errno.h>".}: cint
EXT. stable
+ +template prepareROErrno() {.dirty.}
template prepareRWErrno() {.dirty.}
template setErrnoRaw(v: cint)
Errno {.pure.} = enum + E_SUCCESS = "success", ## inner. unstable. + E2BIG = "Argument list too long", EACCES = "Permission denied", + EADDRINUSE = "Address already in use", + EADDRNOTAVAIL = "Cannot assign requested address", EADV = "Advertise error", + EAFNOSUPPORT = "Address family not supported by protocol", + EAGAIN = "Resource temporarily unavailable", + EALREADY = "Operation already in progress", EBADE = "Invalid exchange", + EBADF = "Bad file descriptor", EBADFD = "File descriptor in bad state", + EBADMSG = "Bad message", EBADR = "Invalid request descriptor", + EBADRQC = "Invalid request code", EBADSLT = "Invalid slot", + EBFONT = "Bad font file format", EBUSY = "Device or resource busy", + ECANCELED = "Operation canceled", ECHILD = "No child processes", + ECHRNG = "Channel number out of range", ECOMM = "Communication error on send", + ECONNABORTED = "Software caused connection abort", + ECONNREFUSED = "Connection refused", ECONNRESET = "Connection reset by peer", + EDEADLK = "Resource deadlock avoided", + EDEADLOCK = "Resource deadlock avoided", + EDESTADDRREQ = "Destination address required", + EDOM = "Numerical argument out of domain", EDOTDOT = "RFS specific error", + EDQUOT = "Disk quota exceeded", EEXIST = "File exists", + EFAULT = "Bad address", EFBIG = "File too large", EHOSTDOWN = "Host is down", + EHOSTUNREACH = "No route to host", EIDRM = "Identifier removed", + EILSEQ = "Invalid or incomplete multibyte or wide character", + EINPROGRESS = "Operation now in progress", EINTR = "Interrupted system call", + EINVAL = "Invalid argument", EIO = "Input/output error", + EISCONN = "Transport endpoint is already connected", + EISDIR = "Is a directory", EISNAM = "Is a named type file", + EKEYEXPIRED = "Key has expired", EKEYREJECTED = "Key was rejected by service", + EKEYREVOKED = "Key has been revoked", EL2HLT = "Level 2 halted", + EL2NSYNC = "Level 2 not synchronized", EL3HLT = "Level 3 halted", + EL3RST = "Level 3 reset", ELIBACC = "Can not access a needed shared library", + ELIBBAD = "Accessing a corrupted shared library", + ELIBEXEC = "Cannot exec a shared library directly", + ELIBMAX = "Attempting to link in too many shared libraries", + ELIBSCN = ".lib section in a.out corrupted", + ELNRNG = "Link number out of range", + ELOOP = "Too many levels of symbolic links", + EMEDIUMTYPE = "Wrong medium type", EMFILE = "Too many open files", + EMLINK = "Too many links", EMSGSIZE = "Message too long", + EMULTIHOP = "Multihop attempted", ENAMETOOLONG = "File name too long", + ENAVAIL = "No XENIX semaphores available", ENETDOWN = "Network is down", + ENETRESET = "Network dropped connection on reset", + ENETUNREACH = "Network is unreachable", + ENFILE = "Too many open files in system", ENOANO = "No anode", + ENOBUFS = "No buffer space available", ENOCSI = "No CSI structure available", + ENODATA = "No data available", ENODEV = "No such device", + ENOENT = "No such file or directory", ENOEXEC = "Exec format error", + ENOKEY = "Required key not available", ENOLCK = "No locks available", + ENOLINK = "Link has been severed", ENOMEDIUM = "No medium found", + ENOMEM = "Cannot allocate memory", ENOMSG = "No message of desired type", + ENONET = "Machine is not on the network", ENOPKG = "Package not installed", + ENOPROTOOPT = "Protocol not available", ENOSPC = "No space left on device", + ENOSR = "Out of streams resources", ENOSTR = "Device not a stream", + ENOSYS = "Function not implemented", ENOTBLK = "Block device required", + ENOTCONN = "Transport endpoint is not connected", ENOTDIR = "Not a directory", + ENOTEMPTY = "Directory not empty", ENOTNAM = "Not a XENIX named type file", + ENOTRECOVERABLE = "State not recoverable", + ENOTSOCK = "Socket operation on non-socket", + ENOTSUP = "Operation not supported", + ENOTTY = "Inappropriate ioctl for device", + ENOTUNIQ = "Name not unique on network", ENXIO = "No such device or address", + EOPNOTSUPP = "Operation not supported", + EOVERFLOW = "Value too large for defined data type", + EOWNERDEAD = "Owner died", EPERM = "Operation not permitted", + EPFNOSUPPORT = "Protocol family not supported", EPIPE = "Broken pipe", + EPROTO = "Protocol error", EPROTONOSUPPORT = "Protocol not supported", + EPROTOTYPE = "Protocol wrong type for socket", + ERANGE = "Numerical result out of range", EREMCHG = "Remote address changed", + EREMOTE = "Object is remote", EREMOTEIO = "Remote I/O error", + ERESTART = "Interrupted system call should be restarted", + ERFKILL = "Operation not possible due to RF-kill", + EROFS = "Read-only file system", + ESHUTDOWN = "Cannot send after transport endpoint shutdown", + ESOCKTNOSUPPORT = "Socket type not supported", ESPIPE = "Illegal seek", + ESRCH = "No such process", ESRMNT = "Srmount error", + ESTALE = "Stale file handle", ESTRPIPE = "Streams pipe error", + ETIME = "Timer expired", ETIMEDOUT = "Connection timed out", + ETOOMANYREFS = "Too many references: cannot splice", + ETXTBSY = "Text file busy", EUCLEAN = "Structure needs cleaning", + EUNATCH = "Protocol driver not attached", EUSERS = "Too many users", + EWOULDBLOCK = "Resource temporarily unavailable", + EXDEV = "Invalid cross-device link", EXFULL = "Exchange full"
ErrnoCount = 133
macro initErrorcodeMap(K, V; res: untyped; initFunc: typed)
template declErrorcodeWith[K, V](initFunc: typed)
NOTE: not support js currently +
Its param: closefd, opener is not implemented yet
+ +There is difference that Python's TextIOBase.seek will reset state of encoder at some conditions, while Nim doesn't have access to encoder's state Therefore, seek here doesn't change that
+ +Python's __next__ will yield newline as part of result but Nim's iterator lines does not
+ +BufferedIOBase = ref object of IOBase
BufferedRandom = ref object of BufferedIOBase
BufferedReader = ref object of BufferedIOBase
BufferedWriter = ref object of BufferedIOBase
NoEncTextIOBase = ref object of IOBase
NoEncTextIOWrapper = ref object of NoEncTextIOBase + name*: PyStr + mode*: PyStr
TextIOWrapper = ref object of NoEncTextIOWrapper + ## do not use string, so is always valid
UnsupportedOperation = object of PyOSError
DEFAULT_BUFFER_SIZE = 8192
DefEncoding = ""
DefNewLine = "None"
LocaleEncoding = "locale"
func encoding(s: TextIOWrapper): PyStr {....raises: [], tags: [], forbids: [].}
func errors(s: TextIOWrapper): PyStr {....raises: [], tags: [], forbids: [].}
proc initBufAsPy(nfile: var File; buf: int) {....raises: [], tags: [], forbids: [].}
proc newNoEncTextIO(file: File; name: string; newline = DefNewLine): NoEncTextIOWrapper {. + ...raises: [ValueError], tags: [], forbids: [].}
proc read(self: NoEncTextIOWrapper): PyStr {....raises: [IOError], + tags: [ReadIOEffect], forbids: [].}
proc read(self: NoEncTextIOWrapper; size: int): PyStr {....raises: [IOError], + tags: [ReadIOEffect], forbids: [].}
proc read(self: RawIOBase): PyBytes {....raises: [IOError], tags: [ReadIOEffect], + forbids: [].}
proc read(self: RawIOBase; size: int): PyBytes {....raises: [IOError], + tags: [ReadIOEffect], forbids: [].}
proc read(self: TextIOWrapper): PyStr {....raises: [IOError, Exception], + tags: [ReadIOEffect, RootEffect], + forbids: [].}
proc read(self: TextIOWrapper; size: int): PyStr {....raises: [IOError, Exception], + tags: [ReadIOEffect, RootEffect], forbids: [].}
proc readline(self: NoEncTextIOWrapper): PyStr {....raises: [IOError], + tags: [ReadIOEffect], forbids: [].}
proc readline(self: NoEncTextIOWrapper; size: int): PyStr {....raises: [IOError], + tags: [ReadIOEffect], forbids: [].}
proc readline(self: RawIOBase): PyBytes {....raises: [IOError], + tags: [ReadIOEffect], forbids: [].}
proc readline(self: RawIOBase; size: Natural): PyBytes {....raises: [IOError], + tags: [ReadIOEffect], forbids: [].}
proc readline(self: TextIOWrapper): PyStr {....raises: [IOError, Exception], + tags: [ReadIOEffect, RootEffect], forbids: [].}
Example:
+import std/strutils +const fn = "tempfiletest" +proc check(ls: varargs[string], newline: string) = + var f = open(fn, newline=newline) + for l in ls: + let s = f.readline() + assert s == l, + "expected $#, but got $#, with newline=$#" % [l.repr, s.repr, newline.repr] + + f.close() + +writeFile fn, "abc\r\n123\n-\r_" + +check "abc\n", "123\n", "-\n", "_", newline=DefNewLine +check "abc\r\n", "123\n", "-\r", "_", newline="" +check "abc\r", "\n123\n-\r", "_", newline="\r" +check "abc\r\n", "123\n", "-\r_", newline="\n" +check "abc\r\n", "123\n-\r_", newline="\r\n"+ Source +Edit + +
proc readline(self: TextIOWrapper; size: Natural): PyStr {. + ...raises: [IOError, Exception], tags: [ReadIOEffect, RootEffect], forbids: [].}
proc write(self: NoEncTextIOWrapper; s: PyStr): int {.discardable, + ...raises: [Exception], tags: [RootEffect], forbids: [].}
proc write(self: RawIOBase; s: PyBytes): int {.discardable, ...raises: [IOError], + tags: [WriteIOEffect], forbids: [].}
proc write(self: TextIOWrapper; s: PyStr): int {.discardable, + ...raises: [Exception], tags: [RootEffect], forbids: [].}
Writes the s to the stream and return the number of characters written
+The following is from Python's doc of open: if newline is None, any 'n' characters written are translated to the system default line separator, os.linesep. If newline is "" or 'n', no translation takes place. If newline is any of the other legal values, any 'n' characters written are translated to the given string.
+ +Example:
+const fn = "tempfiletest" +proc checkW(s, dest: string, newline=DefNewLine, encoding=DefEncoding; + writeLen=dest.len # dest.len returns bytes size + ) = + var f = open(fn, 'w', newline=newline, encoding=encoding) + assert writeLen == f.write s + f.close() + let res = readFile fn + assert dest == res, "expected "&dest.repr&" but got "&res.repr +checkW "1\n2", when defined(windows): "1\r\n2" else: "1\n2" +checkW "1\n2", "1\p2" # same as above +checkW "1\n2", "1\r2", newline="\r" +checkW "我", "我", encoding="utf-8", writeLen=1+ Source +Edit + +
method close(self: IOBase) {.base, ...raises: [], tags: [], forbids: [].}
method close(self: TextIOWrapper) {....raises: [Exception], tags: [RootEffect], + forbids: [].}
method seek(f: IOBase; cookie: int64; whence = SEEK_SET): int64 {.base, + discardable, ...raises: [IOError], tags: [], forbids: [].}
method seek(self: TextIOWrapper; cookie: int64; whence = SEEK_SET): int64 {. + discardable, + ...raises: [ValueError, UnsupportedOperation, IOError, PyOSError, Exception], + tags: [RootEffect], forbids: [].}
Example:
+var f = open("tempfiletest", 'w') +doAssertRaises UnsupportedOperation: + f.seek(1, SEEK_CUR) +f.close()+ Source +Edit + +
template open(file: int; mode: static[string | char] = "r"; buffering: int = -1; + encoding: string = DefEncoding; errors: string = DefErrors; + newline: string | char = DefNewLine): untyped
template open[S](file: PathLike[S]; mode: static[string | char] = "r"; + buffering: int = -1; encoding: string = DefEncoding; + errors: string = DefErrors; newline: string | char = DefNewLine): untyped
Example:
+const fn = "tempfiletest" +const nonfn = r" \:/ $&* " +doAssertRaises LookupError: + # raise LookupError instead of FileNotFoundError (like Python) + discard open(nonfn, encoding="this is a invalid enc") +doAssertRaises FileNotFoundError: + discard io.open(nonfn) # an invalid filename, never existing +block Write: + var f = open(fn, "w", encoding="utf-8") + let ret = f.write("123\r\n") + when defined(windows): + assert ret == 6 # Universal Newline, written "123\r\r\n" + else: + assert ret == 5 # written "123\r\n" + assert not f.closed + f.close() + assert f.closed + assert readFile(fn) == (when defined(windows):"123\r\r\n" else:"123\r\n") +block Read: + var f = open(fn, 'r') + let uniLineRes = f.read() # Universal Newline, "123\r\n\n" -> "123\n\n" + assert uniLineRes == (when defined(windows):"123\n\n" else:"123\n") + f.close()+ Source +Edit + +
Lib/math
+Wrapper around Lib/n_math, and raises exceptions when math error occurs as CPython behaves.
+ +template dist[T](p, q: (Iterable[T] and not openArray[T])): float
template dist[T](p, q: ClosureIter[T]): float
template sumprod[T](p, q: (Iterable[T] and not openArray[T])): float
template sumprod[T](p, q: ClosureIter[T]): float
from https://www.netlib.org/cephes/ cmath.tgz cbrt.c And single.tgz cbrtf.c
+Cube root
+DESCRIPTION:
+Returns the cube root of the argument, which may be negative.
+Range reduction involves determining the power of 2 of the argument. A polynomial of degree 2 applied to the mantissa, and multiplication by the cube root of 1, 2, or 4 approximates the root to within about 0.1%. Then Newton's iteration is used three times to converge to an accurate result.
+ACCURACY:
+Relative error:+
arithmetic domain # trials peak rms DEC -10,10 200000 1.8e-17 6.2e-18 IEEE 0,1e308 30000 1.5e-16 5.0e-17
+cbrt.c
+Cephes Math Library Release 2.8: June, 2000 Copyright 1984, 1991, 2000 by Stephen L. Moshier
+cbrt.nim Copyright litlighilit 2024
+ + + + +template GET_FLOAT_WORD(word: var uint32; x: float32)
template GET_FLOAT_WORD(x: float32): uint32
template getLowWord(x: float32): uint16
template getLowWord(x: float64): uint32
template setHighWord(x: float; hi)
compiletime/expm1.nim 10/19/2024:
---
+@(#)s_expm1.c 1.5 04/04/22 And s_expm1f.c
+==================================================== Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved. Copyright (C) 2024 by litlighilit. All rights reserved.
+Permission to use, copy, modify, and distribute this software is freely granted, provided that this notice is preserved. ==================================================== expm1(x) Returns exp(x)-1, the exponential of x minus 1.
++Method + 1. Argument reduction: + Given x, find r and integer k such that + + x = k*ln2 + r, |r| <= 0.5*ln2 ~ 0.34658 + + Here a correction term c will be computed to compensate + the error in r when rounded to a floating-point number. + + 2. Approximating expm1(r) by a special rational function on + the interval [0,0.34658]: + Since + r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 - r^4/360 + ... + we define R1(r*r) by + r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 * R1(r*r) + That is, + R1(r**2) = 6/r *((exp(r)+1)/(exp(r)-1) - 2/r) + = 6/r * ( 1 + 2.0*(1/(exp(r)-1) - 1/r)) + = 1 - r^2/60 + r^4/2520 - r^6/100800 + ... + We use a special Remes algorithm on [0,0.347] to generate + a polynomial of degree 5 in r*r to approximate R1. The + maximum error of this polynomial approximation is bounded + by 2**-61. In other words, + R1(z) ~ 1.0 + Q1*z + Q2*z**2 + Q3*z**3 + Q4*z**4 + Q5*z**5 + where Q1 = -1.6666666666666567384E-2, + Q2 = 3.9682539681370365873E-4, + Q3 = -9.9206344733435987357E-6, + Q4 = 2.5051361420808517002E-7, + Q5 = -6.2843505682382617102E-9; + (where z=r*r, and the values of Q1 to Q5 are listed below) + with error bounded by + | 5 | -61 + | 1.0+Q1*z+...+Q5*z - R1(z) | <= 2 + | | + + expm1(r) = exp(r)-1 is then computed by the following + specific way which minimize the accumulation rounding error: + 2 3 + r r [ 3 - (R1 + R1*r/2) ] + expm1(r) = r + --- + --- * [--------------------] + 2 2 [ 6 - r*(3 - R1*r/2) ] + + To compensate the error in the argument reduction, we use + expm1(r+c) = expm1(r) + c + expm1(r)*c + ~ expm1(r) + c + r*c + Thus c+r*c will be added in as the correction terms for + expm1(r+c). Now rearrange the term to avoid optimization + screw up: + ( 2 2 ) + ({ ( r [ R1 - (3 - R1*r/2) ] ) } r ) + expm1(r+c)~r - ({r*(--- * [--------------------]-c)-c} - --- ) + ({ ( 2 [ 6 - r*(3 - R1*r/2) ] ) } 2 ) + ( ) + + = r - E + 3. Scale back to obtain expm1(x): + From step 1, we have + expm1(x) = either 2^k*[expm1(r)+1] - 1 + = or 2^k*[expm1(r) + (1-2^-k)] + 4. Implementation notes: + (A). To save one multiplication, we scale the coefficient Qi + to Qi*2^i, and replace z by (x^2)/2. + (B). To achieve maximum accuracy, we compute expm1(x) by + (i) if x < -56*ln2, return -1.0, (raise inexact if x!=inf) + (ii) if k=0, return r-E + (iii) if k=-1, return 0.5*(r-E)-0.5 + (iv) if k=1 if r < -0.25, return 2*((r+0.5)- E) + else return 1.0+2.0*(r-E); + (v) if (k<-2||k>56) return 2^k(1-(E-r)) - 1 (or exp(x)-1) + (vi) if k <= 20, return 2^k((1-2^-k)-(E-r)), else + (vii) return 2^k(1-((E+2^-k)-r)) + +Special cases: + expm1(INF) is INF, expm1(NaN) is NaN; + expm1(-INF) is -1, and + for finite argument, only expm1(0)=0 is exact. + +Accuracy: + according to an error analysis, the error is always less than + 1 ulp (unit in the last place). + +Misc. info. + For IEEE double + if x > 7.09782712893383973096e+02 then expm1(x) overflow ++
Constants: The hexadecimal values are the intended ones for the following constants. The decimal values may be used, provided that the compiler will convert from decimal to binary accurately enough to produce the hexadecimal values shown.
+ + + + + +compiletime/log1p.nim 2024/10/19:
@(#)s_log1p.c 1.3 95/01/18 +Along with: +s_log1pf.c -- float version of s_log1p.c. +Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + + +==================================================== +Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. +Copyright (C) 2024 by litlighilit. All rights reserved. + +Developed at SunSoft, a Sun Microsystems, Inc. business. +Permission to use, copy, modify, and distribute this +software is freely granted, provided that this notice +is preserved. +==================================================== + +double log1p(double x) + +Method : + 1. Argument Reduction: find k and f such that + 1+x = 2^k * (1+f), + where sqrt(2)/2 < 1+f < sqrt(2) . + + Note. If k=0, then f=x is exact. However, if k!=0, then f + may not be representable exactly. In that case, a correction + term is need. Let u=1+x rounded. Let c = (1+x)-u, then + log(1+x) - log(u) ~ c/u. Thus, we proceed to compute log(u), + and add back the correction term c/u. + (Note: when x > 2**53, one can simply return log(x)) + + 2. Approximation of log1p(f). + Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s) + = 2s + 2/3 s**3 + 2/5 s**5 + ....., + = 2s + s*R + We use a special Reme algorithm on [0,0.1716] to generate + a polynomial of degree 14 to approximate R The maximum error + of this polynomial approximation is bounded by 2**-58.45. In + other words, + 2 4 6 8 10 12 14 + R(z) ~ Lp1*s +Lp2*s +Lp3*s +Lp4*s +Lp5*s +Lp6*s +Lp7*s + (the values of Lp1 to Lp7 are listed in the program) + and + | 2 14 | -58.45 + | Lp1*s +...+Lp7*s - R(z) | <= 2 + | | + Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2. + In order to guarantee error in log below 1ulp, we compute log + by + log1p(f) = f - (hfsq - s*(hfsq+R)). + + 3. Finally, log1p(x) = k*ln2 + log1p(f). + = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo))) + Here ln2 is split into two floating point number: + ln2_hi + ln2_lo, + where n*ln2_hi is always exact for |n| < 2000. + +Special cases: + log1p(x) is NaN with signal if x < -1 (including -INF) ; + log1p(+INF) is +INF; log1p(-1) is -INF with signal; + log1p(NaN) is that NaN with no signal. + +Accuracy: + according to an error analysis, the error is always less than + 1 ulp (unit in the last place). + +Constants: +The hexadecimal values are the intended ones for the following +constants. The decimal values may be used, provided that the +compiler will convert from decimal to binary accurately enough +to produce the hexadecimal values shown. + + +Note: Assuming log() return accurate answer, the following + algorithm can be used to compute log1p(x) to within a few ULP: + + u = 1+x; + if(u==1.0) return x ; else + return log(u)*(x/(u-1.0)); + + See HP-15C Advanced Functions Handbook, p.193. ++ + + + +
template genWithArg(sym, v32, v64) {.dirty.}
template genWithBracket(sym, v32, v64)
template genWithBracket(sym, v32, v64, Ret) {.dirty.}
GammaError = enum + geOk, geDom = "x in {0, -1, -2, ...}", ## when . + ## Infinity discontinuity, + ## which shall produce `Complex Infinity` in SymPy and + ## means domain error + geOverFlow = "x > MAX_GAMMA_X, result overflow as inf", + geUnderFlow = "x < MIN_GAMMA_X, result underflow as `-0.0` or `0.0`.", geZeroCantDetSign = "`x < -maxSafeInteger`(exclude -inf), " & + "can\'t detect result\'s sign", ## `x` losing unit digit, often not regard as an error + geGotNegInf = "x == -inf" ## this is made as a enumerate item as different languages' + ## implementation has different treatment towards -inf
func mapRaiseGammaErr(err: GammaError) {....raises: [ValueError], tags: [], + forbids: [].}
template raiseDomainErr()
template raiseDomainErr(details: string)
template raiseRangeErr()
template raiseRangeErr(details: string)
c_log1p(x) = 1.09861228866811 ct_log1p.log1p(x) = 1.09861228866811 relative_tol = -2.021137094636221e-16
+ +c_log1p(x) = 2.639057329615258 ct_log1p.log1p(x) = 2.639057329615259 relative_tol = 1.682756963505621e-16
+ +c_log1p(x) = 3.871201010907891 ct_log1p.log1p(x) = 3.871201010907891 relative_tol = -1.147161329516994e-16
+ +c_log1p(x) = 4.30406509320417 ct_log1p.log1p(x) = 4.304065093204169 relative_tol = -2.063580360581673e-16
+ +Thus in fact, these constants are no need to be very accurate, just to ensure they're greater than the actual value is enough.
+But as such a short-cur is introduced, I think it better to make it accurate.
+The values are calcuated from tools/math/gamma_x_range.py
+ +35.040096282958984'f32 0b01000010_00001100_00101001_00001111'f32
+ +0b11000010_00011010_01100111_11011000'f32
+ +171.6243769563027'f64 0b01000000_01100101_01110011_11111010_11100101_01100001_11110110_01000111'f64
+ +0b11000000_01100110_00111000_11111011_10001100_00011011_11010100_01000111'f64
+ +I found stdlib-js/gamma uses following values: 171.61447887182298
+But what I tested using SymPy was different. If SymPy is right and my method is so, then the old values are uncorrect and shall not be used, as the old checking range for zero/inf result is bigger. (it doesn't matter if that was smaller) So I change to use current values.
+ +template MAX_GAMMA_X[F](_: typedesc[F]): F
template MIN_GAMMA_X[F](_: typedesc[F]): F
compileLittleEndian = true
func isLittleEndian(): bool {.compileTime, ...raises: [], tags: [], forbids: [].}
maxExponent F - 1 = (MAX - 1) - BIAS = 254 - BIAS = 127 or 2046 - BIAS = 10230b1_00000000_1111111 => 32895 0b1_00000000000_11111111111111111111 => 2148532223mask whose exponent is equal to 126, 1022 a.k.a. (BIAS-1): 0b0_01111110_0000000 => 16256 0b0_01111111110_00000000000000000000 => 1071644672HIGH_WORD_EXPONENT_MASK: 0b0_11111111_0000000 0b0_11111111111_00000000000000000000mantissaDigits F - 1
+template CLEAR_EXP_MASK[F](): untyped
template HighWordFracBits[F](): untyped
template MantissaDigits[F](): untyped
template MAX_EXPONENT[F](_: typedesc[F]): F
template MAX_SUBNORMAL_EXPONENT[F](_: typedesc[F]): F
template MIN_SUBNORMAL_EXPONENT[F](_: typedesc[F]): F
template SET_EXP_MASK[F](): untyped
for JS and C-like backends
+Not for nimvm, see {to,from}Words for impl for nimvm backend
+ +template init32FloatView(FLOAT32_VIEW, UINT16_VIEW)
template init64FloatView(FLOAT64_VIEW, UINT32_VIEW)
253 - 1 224 - 1
+SQRT_TWO_PI = 2.5066282746310007
template maxSafeInteger[F](_: typedesc[F]): F
c_fma means compatible fma, using <math.h> fma when for C
+UNRELIABLE_FMA = true
Stirling's formula for the gamma function gamma(x) = sqrt(2 pi) x^(x-.5) exp(-x) ( 1 + 1/x P(1/x) )
+For float32: .028 < 1/x < .1 relative error < 1.9e-11
+ +func gamma[F: SomeFloat](x: F): F
Example:
+template chkValueErr(arg) = + doAssertRaises ValueError: discard gamma arg +chkValueErr NegInf +chkValueErr 0.0 +# Currently +-0.0 result is not consistent with CPython; +# assert NegInf == 1.0/gamma(-180.5)+ Source +Edit + +
func gamma[T: SomeFloat](x: T; res: var T): GammaError
func stdlibJsGamma[F: SomeFloat](x: F): F {....raises: [].}
template MAX_STIRLING[F](_: typedesc[F]): F
template UseSmallApprox[F](_: typedesc[F]): F
+
This module was hand-translated from FreeBSD's lgamma implementation;
+and with some modification:
+The following copyright, license, and long comment were part of the original implementation available as part of FreeBSD
+Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + +Developed at SunPro, a Sun Microsystems, Inc. business. +Permission to use, copy, modify, and distribute this +software is freely granted, provided that this notice +is preserved.+ + +
func lgamma[F: SomeFloat](x: F): F
Evaluates the natural logarithm of the absolute value of gamma function.
+The following was formatted as Nim-Favor Markdown from FreeBSD `lgamma` source with some minor amendment.
+ +Since gamma(1+s)=s*gamma(s), for x in [0,8], we may +reduce x to a number in [1.5,2.5] by + lgamma(1+s) = log(s) + lgamma(s) +for example, + lgamma(7.3) = log(6.3) + lgamma(6.3) + = log(6.3*5.3) + lgamma(5.3) + = log(6.3*5.3*4.3*3.3*2.3) + lgamma(2.3)+ +
Create a polynomial approximation of lgamma around its minimun ymin=1.461632144968362245 to maintain monotonicity.
+On [ymin-0.23, ymin+0.27] (i.e., [1.23164,1.73163]), use + Let z = x-ymin; + lgamma(x) = -1.214862905358496078218 + z^2*poly(z) +where + poly(z) is a 14 degree polynomial.+ +
We use the following approximation: + s = x-2.0; + lgamma(x) = 0.5*s + s*P(s)/Q(s) +with accuracy + |P/Q - (lgamma(x)-0.5s)| < 2**-61.71 +Our algorithms are based on the following observation + + zeta(2)-1 2 zeta(3)-1 3 +lgamma(2+s) = s*(1-Euler) + --------- * s - --------- * s + ... + 2 3+
where Euler = 0.5771... is the Euler constant, which is very close to 0.5.
+ +For x>=8, we have + lgamma(x) ~ (x-0.5)log(x)-x+0.5*log(2pi)+1/(12x)-1/(360x**3)+.... + +(better formula: + lgamma(x) ~ (x-0.5)*(log(x)-1)-.5*(log(2pi)-1) + ...) + +Let z = 1/x, then we approximation + f(z) = lgamma(x) - (x-0.5)(log(x)-1) +by + 3 5 11 + w = w0 + w1*z + w2*z + w3*z + ... + w6*z +where + |w - f(z)| < 2**-58.74+ +
For negative x, since (G is gamma function) + -x*G(-x)*G(x) = pi/sin(pi*x), +we have + G(x) = pi/(sin(pi*x)*(-x)*G(-x)) +since G(-x) is positive, sign(G(x)) = sign(sin(pi*x)) for x<0 +Hence, for x<0, signgam = sign(sin(pi*x)) and + lgamma(x) = log(|Gamma(x)|) + = log(pi/(|x*sin(pi*x)|)) - lgamma(-x);+
lgamma(2+s) ~ s*(1-Euler) for tiny s + lgamma(1) = lgamma(2) = 0 + lgamma(x) ~ -log(|x|) for tiny x + lgamma(0) = lgamma(neg.integer) = inf and raise divide-by-zero + lgamma(inf) = inf + lgamma(-inf) = inf # see belowFor lgamma(-inf), +
and C/C++ returns +inf; which is not suitable, as gamma(x) where x < about -200 is always truncated to 0.0 at ieee754 float domain. This behavior was said for bug compatible with C99, and is readlly documented by POSIX man and cppreference.com
+In my option, ln(|gamma(-oo)|) -[ieee754 float trunc]-> ln(0+) -> -inf
+But in this function it returns +inf to keep consistent with Python,
+ +Example:
+from std/math import isNaN +assert lgamma(1.0) == 0.0 +assert lgamma(Inf) == Inf +assert lgamma(NaN).isNaN+ Source +Edit + +
func lgamma[F: SomeFloat](x: F; res: var F): GammaError
func scipyGammaLn[F: SomeFloat](x: F): F {....raises: [].}
func stdlibJsLgamma[F: SomeFloat](x: F): F {....raises: [].}
translated from https://github.com/scijs/nextafter/blob/master/nextafter.js
+And add respect to the sign of zero, e.g.
+nextafter(-0.0, 0.0) == 0.0 nextafter(0.0, -0.0) == -0.0
+ + + + +The implementation uses Horner's rule for more efficient computation.
+ClosureIter[T] = iterator (): T
OpenarrayOrNimIter[T] = openArray[T] or ClosureIter[T]
func dist_checkedSameLen[T](p, q: T): int {.inline.}
template openarray_Check(x): bool
template toNimIterator[T](x): ClosureIter[T]
DoubleLength = object + hi*: float + lo*: float
proc dl_mul(x: float; y: float): DoubleLength {....raises: [], tags: [], + forbids: [].}
func dl_sum(a, b: float): DoubleLength {....raises: [], tags: [], forbids: [].}
func sumprod[P, Q](p: openArray[P]; q: openArray[Q]): float
func sumprod[P, Q](p_it: ClosureIter[P]; q_it: ClosureIter[Q]): float
Nim's Python-like math, but raises no catchable exception, using errno to report math error. a.k.a. non will be raised (but not for Defects)
+which allows fast code.
+For Python-like error handler (exception-based), see Lib/math
+Also this is not just a module that wraps Nim's std/math,
+but also providing some extensions that Nim's std/math lacks, for example:
+And fix some non-C99 behavior on some systems, e.g. log(-ve) -> -Inf on Solaris
+NOTE: Currently int is not acceptable when it comes to float about functions
+ +func comb(n, k: int): int {....raises: [], tags: [], forbids: [].}
func isqrtPositive(n: Positive): int {.inline, ...raises: [], tags: [], forbids: [].}
func math_is_error(x: SomeFloat; exc: var ref Exception): bool
inner usage (used by Lib/math).
+Call this when errno != 0, and where x is the result libm returned. This will usually set up an exception and return true, but may return false without setting up an exception.
+ + Source +Edit + +template py_math_isclose_impl(abs)
inner use. Implementation of isclose.
+mixin a, b, isinf, rel_tol, abs_tol
+ + Source +Edit + +orig_argv = newSeqOfCap(argc)
hexversion = 51577072
implementation = ("pynim", (0, 9, 11, "alpha", 0), 51577072, + (val: "", has: false))
platform = "linux"
and haiku/netbsd appended with major version instead of "unknown". In short, this won't be "unknown" as Python does.
+ + Source +Edit + +version_info = (major: 3, minor: 13, patch: 0, releaselevel: "final", serial: 0)
template executable(): string
+
the only difference with Python's is where some types in time is str, there is string in n_time's.
+e.g. n_time.ctime() returns a string
+ +Currently, tm_name is either "LOCAL" or "Etc/UTC", due to std/times only returning those two.
+DefaultTimeFormat = "%a %b %d %H:%M:%S %Y"
proc asctime(): string {....raises: [], tags: [TimeEffect], forbids: [].}
func asctime(t: struct_time): string {....raises: [], tags: [], forbids: [].}
func asctime(tup: struct_time_tuple): typeof(asctime do: + bind struct_time + struct_time(tm_year: 1900, tm_mon: 1, tm_mday: 1, tm_yday: 1, tm_isdst: -1)) {. + ...raises: [], tags: [], forbids: [].}
func asctime(tup: struct_time_tuple10): typeof(asctime do: + bind struct_time + struct_time(tm_year: 1900, tm_mon: 1, tm_mday: 1, tm_yday: 1, tm_isdst: -1)) {. + ...raises: [], tags: [], forbids: [].}
func asctime(tup: struct_time_tuple11): typeof(asctime do: + bind struct_time + struct_time(tm_year: 1900, tm_mon: 1, tm_mday: 1, tm_yday: 1, tm_isdst: -1)) {. + ...raises: [], tags: [], forbids: [].}
proc strptime(s: string): struct_time {....raises: [ValueError, TimeParseError, + TimeFormatParseError], tags: [TimeEffect], forbids: [].}
n_timeit: timeit for Nim.
+see Lib/timeit for python compatiable APIs
+ +NullaryFunc = concept self + self()
TimeitParam = string | NullaryFunc
default_timer = default_timer_defval
default_number = 1000000
default_repeat = 5
proc newTimer(stmt: TimeitParam = NullStmt; setup: TimeitParam = NullStmt; + timer = default_timer; number = default_number): Timer
template repeat(self: Timer; repeat = default_repeat; number = default_number): seq[ + float]
template repeat(stmt: TimeitParam = NullStmt; setup: TimeitParam = NullStmt; + timer = default_timer; repeat = default_repeat; + number = default_number): seq[float]
template timeit(repetitions: int; statements: untyped)
EXT. unstable.
+returns nothing but send output to stdout.
+output shows more information than Pythons.
+ +Example:
+var i = 0 +timeit(10): + i.inc +assert i == 10+ Source +Edit + +
template timeit(stmt: TimeitParam = NullStmt; setup: TimeitParam = NullStmt; + timer = default_timer; number = default_number): float
timeit(stmt, setup, number=1000000) with globals is globals()|locals()
+stmt, setup are Callable or str literal
+ +Example:
+discard timeit("i.inc", "var i = 0") +assert i != 0 + +proc f() = discard +discard timeit(f) +proc retf(): int = 1 +discard timeit(retf)+ Source +Edit + +
EXT. Nim's codec. not the same as Python's codec
+EncErrors {.pure.} = enum + strict, ## - raise a ValueError error (or a subclass) + ignore, ## - ignore the character and continue with the next + replace, ## - replace with a suitable replacement character; + ## Python will use the official U+FFFD REPLACEMENT + ## CHARACTER for the builtin Unicode codecs on + ## decoding and "?" on encoding. + surrogateescape, ## - replace with private code points U+DCnn. + xmlcharrefreplace, ## - Replace with the appropriate XML + ## character reference (only for encoding). + backslashreplace, ## - Replace with backslashed escape sequences. + namereplace ## - Replace with \N{...} escape sequences + ## (only for encoding).
NCodecInfo = object + name*: string + errors*: string + encode*, decode*: EncoderCvt + close*: EncoderClose
func initNCodecInfo(encoding: string; errors = DefErrors): NCodecInfo {. + ...raises: [LookupError], tags: [], forbids: [].}
SEEK_* is in ./posix_like/seek_c
+O_NONBLOCK {.importc: "O_NONBLOCK", header: "<fcntl.h>".}: cint
used by Lib/os and Lib/platform
+platform.system = "Linux"
proc ac_md_release(): string {....raises: [OSError, IOError], + tags: [ExecIOEffect, ReadIOEffect, RootEffect], + forbids: [].}
proc platform.version(): string {....raises: [OSError, IOError], tags: [ + ExecIOEffect, ReadIOEffect, RootEffect], forbids: [].}
proc uname_release_major(): string {....raises: [OSError, IOError], tags: [ + ExecIOEffect, ReadIOEffect, RootEffect], forbids: [].}
proc toCSighandler(p: PySigHandler): CSigHandler {....raises: [], tags: [], + forbids: [].}
proc toPySighandler(p: CSigHandler | NimSigHandler): PySigHandler
proc getFrameOrNil(): PFrame {....raises: [], tags: [], forbids: [].}
proc getFrameOrNil(up: int): PFrame {....raises: [], tags: [], forbids: [].}
template Py_atomic_load[T](obj: T): T
template Py_atomic_load_ptr[T](obj: ptr T): T
template Py_atomic_store[T](obj: T; value: T)
template Py_atomic_store_ptr[T](obj: ptr T; value: T)
XXX: FIXED-NIM-BUG: though nimAllowNonVarDestructor is defined at least since 2.0.6, it still cannot be compiled till abour 2.1.1
+signal_state_t = object + handlers*: array[Py_NSIG, handler] + when DWin: + sigint_event*: Handle + default_handler*, ignore_handler*: PySigHandler
proc get_handler(i: cint): PySigHandler {....raises: [], tags: [], forbids: [].}
proc initPySignal(install_signal_handlers: bool) {....raises: [], tags: [], + forbids: [].}
proc PySignal_Fini() {....raises: [], tags: [], forbids: [].}
proc set_handler(i: cint; fn: PySigHandler) {....raises: [], tags: [], forbids: [].}
template signal_global_state(): signal_state_t
Lib/sys
orig_argv = newPyListOfCap(argc)
float_repr_style = "short"
hexversion = 51577072
implementation = ("pynim", (0, 9, 11, "alpha", 0), 51577072, false)
platform = "linux"
and haiku/netbsd appended with major version instead of "unknown". In short, this won't be "unknown" as Python does.
+ + Source +Edit + +version_info = (3, 13, 0, "final", 0)
proc getdefaultencoding(): PyStr {....raises: [], tags: [], forbids: [].}
proc getfilesystemencoding(): PyStr {....raises: [], tags: [], forbids: [].}
template addaudithook(hook: HookProc)
template executable(): PyStr
When not defined(release) or defined(pylibSysAudit), audit will be enabled. Otherwise, it will be disabled.
+config_should_audit = false
template whenAuditEnabled(body)
template whenAuditEnabledOr[T](exp, elseExp: T): T
template newStmtWithAudit(event: static string; vargs: varargs[untyped]): NimNode
template addaudithook(hook: HookProc)
template PySys_AddAuditHook(hook: HookProc; userData = default Any)
template PySys_Audit(event: string; args: varargs[typed])
float_info = (max: 1.7976931348623157e+308, max_exp: 1024, max_10_exp: 308, + min: 2.2250738585072014e-308, min_exp: -1021, min_10_exp: -307, + dig: 15, mant_dig: 53, epsilon: 2.220446049250313e-16, radix: 2)
float_repr_style = "short"
flags = (debug: debug, inspect: inspect, interactive: interactive, + isolated: isolated, optimize: optimize, + dont_write_bytecode: dont_write_bytecode, no_user_site: no_user_site, + no_site: no_site, ignore_environment: ignore_environment, + verbose: verbose, bytes_warning: bytes_warning, quiet: quiet, + hash_randomization: hash_randomization, dev_mode: dev_mode, + utf8_mode: utf8_mode, safe_path: safe_path, + int_max_str_digits: int_max_str_digits, + warn_default_encoding: warn_default_encoding)
PYTHON* environment variables will be loaded iif pylibUsePyEnv is defined.
+bytes_warning {.intdefine: bytes_warning.toCfgName.} = 0
dont_write_bytecode {.intdefine: dont_write_bytecode.toCfgName.} = 1
hash_randomization {.intdefine: hash_randomization.toCfgName.} = 0
ignore_environment {.intdefine: ignore_environment.toCfgName.} = 0
int_max_str_digits {.intdefine: int_max_str_digits.toCfgName.} = 4300
interactive {.intdefine: interactive.toCfgName.} = 0
no_user_site {.intdefine: no_user_site.toCfgName.} = 0
warn_default_encoding {.intdefine: warn_default_encoding.toCfgName.} = 0
macro genFlagsObj()
macro redefineFlags(kws: varargs[untyped])
dont_write_bytecode = ib_b(toPyEnv("dont_write_bytecode"), dont_write_bytecode)
int_max_str_digits = ib_i(toPyEnv("int_max_str_digits"), int_max_str_digits)
no_user_site = ib_b(toPyEnv("no_user_site"), no_user_site)
warn_default_encoding = ib_e(toPyEnv("warn_default_encoding"), + warn_default_encoding)
proc getdefaultencoding(): string {....raises: [], tags: [], forbids: [].}
Return the current default encoding used by the Unicode implementation.
+Always "utf-8" in Nim
+ + Source +Edit + +proc getfilesystemencoding(): string {....raises: [], tags: [], forbids: [].}
stderr = newNoEncTextIO(stderr, "<stderr>", DefNewLine)
stdin = newNoEncTextIO(stdin, "<stdin>", DefNewLine)
stdout = newNoEncTextIO(stdout, "<stdout>", DefNewLine)
dunder_stderr = stderr
dunder_stdin = stdin
dunder_stdout = stdout
weirdTarget = false
time
+Currently the implementation is n_time module . The following is its doc:
+DefaultTimeFormat = "%a %b %d %H:%M:%S %Y"
proc asctime(): PyStr {....raises: [], tags: [TimeEffect], forbids: [].}
func asctime(t: Some_struct_time): PyStr
Example:
+assert asctime(gmtime(0)) == "Thu Jan 1 00:00:00 1970"+ Source +Edit + +
proc strptime(s: PyStr; format = DefaultTimeFormat): struct_time {. + ...raises: [ValueError, TimeParseError, TimeFormatParseError], + tags: [TimeEffect], forbids: [].}
func dtToStructTime(dt: DateTime; res: var struct_time) {....raises: [], tags: [], + forbids: [].}
func struct_time(tup`gensym0: struct_time_tuple): struct_time {....raises: [], + tags: [], forbids: [].}
func struct_time(tup`gensym2: struct_time_tuple10): struct_time {....raises: [], + tags: [], forbids: [].}
func struct_time(tup`gensym4: struct_time_tuple11): struct_time {....raises: [], + tags: [], forbids: [].}
func structTimeToDt(st: struct_time; res: var DateTime) {....raises: [], tags: [], + forbids: [].}
converter toTuple(st: struct_time): struct_time_tuple {....raises: [], tags: [], + forbids: [].}
func monotonic_ns(): int64 {....raises: [], tags: [TimeEffect], forbids: [].}
func perf_counter(): float {....raises: [], tags: [TimeEffect], forbids: [].}
func perf_counter_ns(): int64 {....raises: [], tags: [TimeEffect], forbids: [].}
func process_time(): float {....raises: [], tags: [TimeEffect], forbids: [].}
strftime, strptime
+platform independent implementation.
+ +NotImplDirectives = {'y', 'Z'}
Here are their concrete meanings in Python, as well as some notes about why they cannot be directly mapped to Nim's DateTime.format/parse.
+The direct alternative value when formatting in Nim, if any, is introduced by <-:
+Following are strftime only currently:
+proc strptime(dt: var DateTime; s: string; format_with_sp_asis: string) {. + ...raises: [ValueError, TimeParseError, TimeFormatParseError], + tags: [TimeEffect], forbids: [].}
macro addFields(res: string; obj: typed; noMoreThan: static[int] = int.high)
obj is of object or ref object. when obj is of object and noMoreThan is not given, it's roughly equal to:
+let startLen = res.len +for k, v in o.fieldPairs: + res.addSep(sep=", ", startLen = startLen) + res.add k & '=' & repr v+ + Source +Edit + +
macro asgSeqToObj(tup, obj: typed)
macro cmpOnField(a, b: typed): int
macro declTupleWithNFieldsFrom(name: untyped; Cls: typedesc; n: static[int]; + exported: static[bool] = true)
macro mixinOrderOnFields(lhs, rhs: typed; cmpOp; + cmpStragy: static[CmpStragy] = csEq): bool
cmpOnFields but a b can be of different types.
+e.g. a is tuple and b is object; or a, b are different objects.
+ + Source +Edit + +macro orderOnFields[T](a, b: T; cmpOp): bool
mainly for checking if ref objects are equal on fields
+when for object/tuple and cmpOp is ==, roughly equal to: a == b
+but system.== for ref just compare the address.
+ + Source +Edit + +func strftime(format: string; st: Some_struct_time_tuple): string
func strftime(format: string; st: struct_time): string {....raises: [], tags: [], + forbids: [].}
func strftime[S](format: S; st: struct_time): S
proc strptime(s: string; f: string): struct_time {. + ...raises: [ValueError, TimeParseError, TimeFormatParseError], + tags: [TimeEffect], forbids: [].}
funcs about struct_time
+its initializer, and a inverse function mktime
+ +proc gmtime(): struct_time {....raises: [], tags: [TimeEffect], forbids: [].}
proc gmtime(secs: float): struct_time {....raises: [], tags: [], forbids: [].}
proc gmtime(secs: int64): struct_time {....raises: [], tags: [], forbids: [].}
proc localtime(): struct_time {....raises: [], tags: [TimeEffect], forbids: [].}
proc localtime(secs: float): struct_time {....raises: [], tags: [], forbids: [].}
proc localtime(secs: int64): struct_time {....raises: [], tags: [], forbids: [].}
func mktime(t: struct_time): float {....raises: [], tags: [], forbids: [].}
func mktime(tup: struct_time_tuple): typeof(mktime do: + bind struct_time + struct_time(tm_year: 1900, tm_mon: 1, tm_mday: 1, tm_yday: 1, tm_isdst: -1)) {. + ...raises: [], tags: [], forbids: [].}
Some_struct_time = struct_time | Some_struct_time_tuple
Some_struct_time_tuple = struct_time_tuple | struct_time_tuple10 | + struct_time_tuple11
struct_time = ref object + tm_year*: int + tm_mon*: range[1 .. 12] + tm_mday*: MonthdayRange + tm_hour*: HourRange + tm_min*: MinuteRange + tm_sec*: range[0 .. 61] + tm_wday*: range[0 .. 6] + tm_yday*: range[1 .. 366] + tm_isdst*: int + tm_zone*: string ## .. warning:: curently is only "LOCAL" or "Etc/UTC" + tm_gmtoff*: int
struct_time_tuple = tuple[tm_year: int, tm_mon: range[1 .. 12], + tm_mday: range[1 .. 31], tm_hour: range[0 .. 23], + tm_min: range[0 .. 59], tm_sec: range[0 .. 61], + tm_wday: range[0 .. 6], tm_yday: range[1 .. 366], + tm_isdst: int]
struct_time_tuple10 = tuple[tm_year: int, tm_mon: range[1 .. 12], + tm_mday: range[1 .. 31], tm_hour: range[0 .. 23], + tm_min: range[0 .. 59], tm_sec: range[0 .. 61], + tm_wday: range[0 .. 6], tm_yday: range[1 .. 366], + tm_isdst: int, tm_zone: string]
struct_time_tuple11 = tuple[tm_year: int, tm_mon: range[1 .. 12], + tm_mday: range[1 .. 31], tm_hour: range[0 .. 23], + tm_min: range[0 .. 59], tm_sec: range[0 .. 61], + tm_wday: range[0 .. 6], tm_yday: range[1 .. 366], + tm_isdst: int, tm_zone: string, tm_gmtoff: int]
func `<`(a, b: struct_time): bool {....raises: [], tags: [], forbids: [].}
func `<`(a: struct_time; b: struct_time_tuple11): bool {....raises: [], tags: [], + forbids: [].}
func `<`(a: struct_time_tuple11; b: struct_time): bool {....raises: [], tags: [], + forbids: [].}
func `<`(st: struct_time; t: tuple): bool
func `<`(t: tuple; st: struct_time): bool
func `<=`(a, b: struct_time): bool {....raises: [], tags: [], forbids: [].}
func `<=`(a: struct_time; b: struct_time_tuple11): bool {....raises: [], tags: [], + forbids: [].}
func `<=`(a: struct_time_tuple11; b: struct_time): bool {....raises: [], tags: [], + forbids: [].}
func `<=`(st: struct_time; t: tuple): bool
func `<=`(t: tuple; st: struct_time): bool
func `==`(a, b: struct_time): bool {....raises: [], tags: [], forbids: [].}
func `==`(a: struct_time; b: struct_time_tuple11): bool {....raises: [], tags: [], + forbids: [].}
func `==`(a: struct_time_tuple11; b: struct_time): bool {....raises: [], tags: [], + forbids: [].}
func `==`(st: struct_time; t: tuple): bool {.inline.}
func `==`(t: tuple; st: struct_time): bool {.inline.}
func repr(st: struct_time): string {....raises: [], tags: [], forbids: [].}
struct_time.__repr__
+returns string starting with "time.struct_time" with 9 fields.
+ + Source +Edit + +template initStructTime(): struct_time
template initStructTime(year, mon, mday, hour, min, sec, wday, yday, isdst, + zone, gmtoff): struct_time
template isUtcZone(st: struct_time): bool
default_timer = pysince(3.3, perf_counter, default_timer)
default_repeat = 5
TimeItUseTime {.booldefine: "timeit.usetime".} = true
template repeat(self: Timer; repeat = pysince(3.7, 5, 3); + number = default_number): PyList[float]
template repeat(stmt: TimeitParam = NullStmt; setup: TimeitParam = NullStmt; + timer = default_timer; repeat = pysince(3.7, 5, 3); + number = default_number): PyList[float]
Example:
+assert len(repeat(repeat=0)) == 0+ Source +Edit + +
proc Py_SetLocaleFromEnv(category: cint): cstring {.discardable, ...raises: [], + tags: [], forbids: [].}
proc setenvOverwrite(key, val: string): bool {....raises: [], + tags: [WriteEnvEffect], forbids: [].}
proc Py_DecodeLocaleEx(arg: cstring; wstr: var ptr wchar_t; wlen: ptr csize_t; + reason: var cstring; current_locale: bool; + errors: Py_error_handler): int {....raises: [], tags: [], + forbids: [].}
Decode a byte string from the locale encoding.
+Use the strict error handler if 'surrogateescape' is zero. Use the surrogateescape error handler if 'surrogateescape' is non-zero: undecodable bytes are decoded as characters in range U+DC80..U+DCFF. If a byte sequence can be decoded as a surrogate character, escape the bytes using the surrogateescape error handler instead of decoding them.
+On success, return 0 and write the newly allocated wide character string into wstr (use PyMem_RawFree() to free the memory). If wlen is not NULL, write the number of wide characters excluding the null character into wlen.
+On memory allocation failure, return -1.
+On decoding error, return -2. Write the start of invalid byte sequence in the input string into wlen. If reason is not NULL, write the decoding error message into reason.
+Return -3 if the error handler 'errors' is not supported.
+Use the Py_EncodeLocaleEx() function to encode the character string back to a byte string.
+ + Source +Edit + +proc Py_GetLocaleEncoding(): string {....raises: [], tags: [], forbids: [].}
See also config_get_locale_encoding()
+ + Source +Edit + +Py_FORCE_UTF8_FS_ENCODING = false
Py_FORCE_UTF8_LOCALE = false
proc check_force_ascii(): bool {....raises: [], tags: [], forbids: [].}
proc Py_GetForceASCII(): bool {....raises: [], tags: [], forbids: [].}
proc Py_ResetForceASCII() {....raises: [], tags: [], forbids: [].}
template force_ascii(): untyped
Py_error_handler = enum + Py_ERROR_UNKNOWN = "unknown", Py_ERROR_STRICT = "strict", + Py_ERROR_SURROGATEESCAPE = "surrogateescape", Py_ERROR_REPLACE = "replace", + Py_ERROR_IGNORE = "ignore", Py_ERROR_BACKSLASHREPLACE = "backslashreplace", + Py_ERROR_SURROGATEPASS = "surrogatepass", + Py_ERROR_XMLCHARREFREPLACE = "xmlcharrefreplace", Py_ERROR_OTHER = "other"
proc Py_GetErrorHandler(errors: string): Py_error_handler {....raises: [], + tags: [], forbids: [].}
proc PyOS_getsig(sig: cint): CSigHandler {....raises: [], tags: [], forbids: [].}
proc PyOS_setsig(sig: cint; handler: CSigHandler): CSigHandler {....raises: [], + tags: [], forbids: [].}
XXX: posix/winlean's a2 cannot be nil (a var Sigaction)
+ITIMER_PROF {.importc, header: "<sys/time.h>".}: cint
ITIMER_REAL {.importc, header: "<sys/time.h>".}: cint
ITIMER_VIRTUAL {.importc, header: "<sys/time.h>".}: cint
HAVE_BROKEN_PTHREAD_SIGMASK = false
HAVE_SIGSET_T = true
PYPTHREAD_SIGMASK = true
proc c_signal(a1: cint; a2: CSigHandler): CSigHandler {.importc: "signal", + header: "<signal.h>", ...raises: [], tags: [], forbids: [].}
CSigHandler = proc (signalnum: cint) {.noconv.}
NimSigHandler = proc (signalnum: int) {.nimcall.}
PySigHandler = proc (signalnum: int; frame: PFrame) {.closure.}
Mask to quickly check whether a C 'size_t' contains a non-ASCII, UTF8-encoded char.10xxxxxx
+ALIGNOF_SIZE_T = 8
ASCII_CHAR_MASK = 0x80808080'u
func getMaxChar[C](): C
proc utf8_decode[STRINGLIB_CHAR](inptr: var (cstring | ptr char); + end: (cstring | ptr char); + dest: ptr STRINGLIB_CHAR; + outpos: var Py_ssize_t): Py_UCS4
template IS_CONTINUATION_BYTE(ch: untyped): untyped
template Py_IS_ALIGNED(p: cstring | ptr; a: typeof(ALIGNOF_SIZE_T)): bool
MaxWStrLen = 2305843009213693951
proc Py_DecodeUTF8Ex(orig_s: cstring; size: csize_t; wstr: var ptr wchar_t; + wlen: ptr csize_t; reason: var cstring; + errors: Py_error_handler): int {....raises: [], tags: [], + forbids: [].}
UTF-8 decoder: use surrogateescape error handler if 'surrogateescape' is non-zero, use strict error handler otherwise.
+On success, write a pointer to a newly allocated wide character string into wstr (use PyMem_RawFree() to free the memory) and write the output length (in number of wchar_t units) into wlen (if wlen is set).
+On memory allocation failure, return -1.
+On decoding error (if surrogateescape is zero), return -2. If wlen is non-NULL, write the start of the illegal byte sequence into wlen. If reason is not NULL, write the decoding error message into reason.
+ + Source +Edit + +DECODE_ERROR = -1
HAVE_MBRTOWC = true
INCOMPLETE_CHARACTER = -2
MAX_UNICODE_val = 0x0010FFFF
proc is_valid_wide_char(ch: wchar_t): bool {....raises: [], tags: [], forbids: [].}
proc Py_mbrtowc(wc: PWc; src: cstring; n: csize_t; mbs: var mbstate_t): csize_t
proc Py_mbstowcs(dest: ptr wchar_t; src: cstring; n: csize_t): csize_t {. + ...raises: [], tags: [], forbids: [].}
template allocWcharArr[I](n: I): ptr wchar_t
template deallocWcArr(p: ptr wchar_t)
template Py_UNICODE_IS_SURROGATE(ch: wchar_t): bool
func pyasciiImpl(us: string): string {....raises: [], tags: [], forbids: [].}
Python's ascii impl
+Note this assumes us is already processed by repr i.e., this only escape the non-ASCII characters in us using x, u, or U escapes and doesn't touch ASCII characters.
+ + Source +Edit + +builtins.complex and its operators/methods.
+Use toNimComplex and pycomplex to convert between PyComplex and Complex
+ +Example:
+import src/pylib/builtins/complex +assert complex(1, 3) == complex("1.0+3.0J") +assert complex(1, 3) == 1 + 3.J + +# complex only stores floats, not int, +# just as Python's +assert not (type(complex(1, 2).real) is int)+
PyComplex = PyTComplex[float]
PyTComplex[T] = distinct Complex[T]
func `$`(z: PyTComplex): string
func `'j`(s: static string): PyComplex
Consider using complex or j instead, which are totaly Python syntax compatiable.
+ +Example:
+assert 1+3'j == 1.0+3.0'J+ Source +Edit + +
func `**=`[T](self: var PyTComplex[T]; + x: ComplexPowSecondParamType[T] | SomeInteger)
func abs[T](z: PyTComplex[T]): T
func complex(s: string): PyComplex {....raises: [ValueError], tags: [], forbids: [].}
func complex[T: SomeFloat](real: T = 0.0; imag: T = 0.0): PyTComplex[T]
func conjugate[T](z: PyTComplex[T]): PyTComplex[T]
func repr(z: PyTComplex): string
Example:
+assert repr(complex(0.0, 3.0)) == "3j" # not "(0+3j)", as in Python +assert repr(complex(-0.0, 3.0)) == "(-0+3j)" # not "3j", as in Python + +assert repr(complex(1.0, 2.0)) == "(1+2j)" # '.0' is removed as Python's+ Source +Edit + +
template `*`[T](a: PyTComplex[T]; b: PyTComplex[T]): untyped
template `*`[T](a: PyTComplex[T]; b: SomeInteger): untyped
template `*`[T](a: PyTComplex[T]; b: T): untyped
template `*`[T](a: SomeInteger; b: PyTComplex[T]): untyped
template `*`[T](a: T; b: PyTComplex[T]): untyped
template `**`[T](a: PyTComplex[T]; b: PyTComplex[T]): untyped
template `**`[T](a: PyTComplex[T]; b: T): untyped
template `**`[T](a: SomeInteger; b: PyTComplex[T]): untyped
template `**`[T](a: T; b: PyTComplex[T]): untyped
template `**`[T](self: PyTComplex[T]; x: SomeInteger): PyTComplex[T]
template `**`[T](self: PyTComplex[T]; x: static Natural): PyTComplex[T]
template `*=`[T](a: PyTComplex[T]; b: PyTComplex[T]): untyped
template `*=`[T](a: PyTComplex[T]; b: SomeInteger): untyped
template `*=`[T](a: PyTComplex[T]; b: T): untyped
template `+`[T](a: PyTComplex[T]; b: PyTComplex[T]): untyped
template `+`[T](a: PyTComplex[T]; b: SomeInteger): untyped
template `+`[T](a: PyTComplex[T]; b: T): untyped
template `+`[T](a: SomeInteger; b: PyTComplex[T]): untyped
template `+`[T](a: T; b: PyTComplex[T]): untyped
template `+=`[T](a: PyTComplex[T]; b: PyTComplex[T]): untyped
template `+=`[T](a: PyTComplex[T]; b: SomeInteger): untyped
template `+=`[T](a: PyTComplex[T]; b: T): untyped
template `-`[T](a: PyTComplex[T]; b: PyTComplex[T]): untyped
template `-`[T](a: PyTComplex[T]; b: SomeInteger): untyped
template `-`[T](a: PyTComplex[T]; b: T): untyped
template `-`[T](a: SomeInteger; b: PyTComplex[T]): untyped
template `-`[T](a: T; b: PyTComplex[T]): untyped
template `-=`[T](a: PyTComplex[T]; b: PyTComplex[T]): untyped
template `-=`[T](a: PyTComplex[T]; b: SomeInteger): untyped
template `-=`[T](a: PyTComplex[T]; b: T): untyped
template `/`[T](a: PyTComplex[T]; b: PyTComplex[T]): untyped
template `/`[T](a: PyTComplex[T]; b: SomeInteger): untyped
template `/`[T](a: PyTComplex[T]; b: T): untyped
template `/`[T](a: SomeInteger; b: PyTComplex[T]): untyped
template `/`[T](a: T; b: PyTComplex[T]): untyped
template `/=`[T](a: PyTComplex[T]; b: PyTComplex[T]): untyped
template `/=`[T](a: PyTComplex[T]; b: SomeInteger): untyped
template `/=`[T](a: PyTComplex[T]; b: T): untyped
template `==`[T](a: PyTComplex[T]; b: PyTComplex[T]): untyped
template `==`[T](a: PyTComplex[T]; b: SomeInteger): untyped
template `==`[T](a: PyTComplex[T]; b: T): untyped
template `==`[T](a: SomeInteger; b: PyTComplex[T]): untyped
template `==`[T](a: T; b: PyTComplex[T]): untyped
template imag[T](z: PyTComplex[T]): T
template imag=[T](z: PyTComplex[T]; _: T) {. + error: "AttributeError: readonly attribute".}
template pow[T](a: PyTComplex[T]; b: PyTComplex[T]): untyped
template pow[T](a: PyTComplex[T]; b: T): untyped
template pow[T](a: SomeInteger; b: PyTComplex[T]): untyped
template pow[T](a: T; b: PyTComplex[T]): untyped
template pow[T](self: ComplexPowSecondParamType[T] | SomeInteger; + x: PyTComplex[T]; _: NoneType): PyTComplex[T]
template pow[T](self: PyTComplex[T]; + x: ComplexPowSecondParamType[T] | SomeInteger; _: NoneType): PyTComplex[ + T]
template pow[T](self: PyTComplex[T]; x: SomeInteger): PyTComplex[T]
template pow[T](self: PyTComplex[T]; x: static Natural): PyTComplex[T]
template pycomplex[T](re: T; im = T(0)): PyTComplex[T]
template pycomplex[T](z: Complex[T]): PyTComplex[T]
template real[T](z: PyTComplex[T]): T
template real=[T](z: PyTComplex[T]; _: T) {. + error: "AttributeError: readonly attribute".}
template toNimComplex[T](z: PyTComplex[T]): Complex[T]
PyDictItemView[K; V] = object of PyDictView + mapping*: PyDict[K, V]
PyDictKeyView[T] = object of PyDictView + mapping*: PyDict[T, auto]
PyDictValueView[T] = object of PyDictView + mapping*: PyDict[auto, T]
PyDictView = object of RootObj
SomePyDictView = PyDictKeyView | PyDictValueView | PyDictItemView
SomeSinglePyDictView[T] = PyDictValueView[T] | PyDictKeyView[T]
func contains[K, V](t: PyDictItemView[K, V]; x: (K, V)): bool
func contains[T](t: PyDictKeyView[T]; x: T): bool
func contains[T](t: PyDictValueView[T]; x: T): bool
func items[K, V](self: PyDict[K, V]): PyDictItemView[K, V]
func iter[K, V](self: PyDict[K, V]): PyIterator[K]
func keys[K, V](self: PyDict[K, V]): PyDictKeyView[K]
proc len(view: SomePyDictView): int
func setdefault[K, V](self: PyDict[K, V]; key: K; default = V.default)
func values[K, V](self: PyDict[K, V]): PyDictValueView[V]
iterator iter[K, V](self: PyDict[K, V]): K
Example:
+let d = dict(a=1) +for i in iter(d): + assert i == "a" +for i in d: + assert i[0] == "a" and i[1] == 1+ Source +Edit + +
template `$`(self: PyDictItemView): string
template `$`(self: PyDictKeyView): string
template `$`(self: PyDictValueView): string
template items(view: SomePyDictView): untyped
template iter(view: SomePyDictView): untyped
template repr(self: PyDictItemView): string {.dirty.}
template repr(self: PyDictKeyView): string {.dirty.}
template repr(self: PyDictValueView): string {.dirty.}
func emptyPyDict[K, V](): PyDict[K, V]
proc getOrDefault[A, B](t: PyDict[A, B]; key: A): B
func toNimTable[K, V](self: PyDict[K, V]): var OrderedTable[K, V]
template newPyDictImpl[K, V](x: int): untyped {. + ...deprecated: "use newPyDict, to be removed since 0.10".}
template newPyDictImpl[K, V](x: openArray[(K, V)] = []): untyped {. + ...deprecated: "use newPyDict, to be removed since 0.10".}
builtins.iter
+PyIterator[T] = ref object
func iter[T](x: Iterable[T]): PyIterator[T]
func iter[T](x: Iterator[T]): PyIterator[T]
func newPyIterator[T](it: iterator (): T): PyIterator[T]
proc next[T](self: PyIterator[T]): T
proc nextImpl[T](self: PyIterator[T]): Option[T] {.inline.}
proc nextImpl[T](self: PyIterator[T]; res: var T): bool {.inline.}
iterator items[T](self: PyIterator[T]): T
Some iterable in builtins
+XXX: For JS backend: Currently due to Nim's inner buys, using of some iterable functions in this modules may result in Error: ...:
+For details, trace:
+PreBreakCb = proc (i: NimNode): NimNode {.closure.}
preferredGenIterResName {.strdefine.} = "gen_iter_res"
proc addEachIter(loopBody: NimNode; nIt: int; itors, res: NimNode; + preBreakCb: PreBreakCb = noopPreBreakCb) {....raises: [Exception], + tags: [RootEffect], forbids: [].}
proc addLoopEach(loopBody: NimNode; parent: NimNode; + iterables: NimNode | seq[NimNode]; + res = ident preferredGenIterResName; + preBreakCb: PreBreakCb = noopPreBreakCb): NimNode {.discardable.}
proc addResDecl(body: NimNode; iterables: NimNode | seq[NimNode]; + res = ident preferredGenIterResName; + iters = genSym(nskLet, "iters")): NimNode {.discardable.}
proc newNullaryLambdaIter(body: NimNode; resType = ident"auto"): NimNode {. + ...raises: [], tags: [], forbids: [].}
func noInitVarDecl(name, Type: NimNode): NimNode {....raises: [], tags: [], + forbids: [].}
proc mapIterBodyImpl(f: NimNode; iterables: NimNode; res = genSym(nskVar, "res")): NimNode {. + ...raises: [Exception], tags: [RootEffect], forbids: [].}
func raiseZipBound(ordLonger: int) {.inline, ...raises: [ValueError], tags: [], + forbids: [].}
proc zipIterBodyImpl(iterables: NimNode | seq[NimNode]; strict: NimNode): NimNode
Python's list with its methods and sorted buitin
+LIMIT: slice literal is not supported. ls[1:3] has to be rewritten as ls[1..2]
+ +converter nimArrayAsList[T; I](arr: array[I, T]): PyList[T]
func newPyList(a: sink openArray[char]): PyList[char] {.inline, ...raises: [], + tags: [], forbids: [].}
func newPyList(a: sink openArray[float]): PyList[float] {.inline, ...raises: [], + tags: [], forbids: [].}
func newPyListOfCap[T](cap = 0): PyList[T] {.inline.}
func newPyListOfStr(a: openArray[string]): PyList[PyStr] {.inline, ...raises: [], + tags: [], forbids: [].}
template checkLenientOps(A, B)
func pow(base, exp, modulo: float): int {.error: "TypeError: pow() 3rd argument not allowed unless all arguments are integers".}
func pow(base: int; exp: Natural): int {....raises: [], tags: [], forbids: [].}
Therefore for pow(base, exp), exp cannot be negative.
+ + Source +Edit + +Comparable = concept ab + a < b is bool
func max[C: Comparable](a, b: C; key: NoneType): C
proc max[C: Comparable](it: Iterable[C]; default: C; key = None): C
proc max[C: Comparable](it: Iterable[C]; key = None): C
func min[C: Comparable](a, b: C; key: NoneType): C
proc min[C: Comparable](it: Iterable[C]; default: C; key = None): C
proc min[C: Comparable](it: Iterable[C]; key = None): C
func pow(base, exp, modulo: int): int {....raises: [ValueError], tags: [], + forbids: [].}
Example:
+assert pow(10, 20, 3) == 1 # 10^20 is bigger than `high int64` +assert pow(7, 2, 13) == 10 +assert pow(7, 20, 13) == 3 +doAssertRaises ValueError: + discard pow(1000, -2, 2) + # base is not invertible for the given modulus +assert pow(1234, 20, 73) == 9+ Source +Edit + +
template isinstance(obj, class_or_tuple): bool
Example:
+assert isinstance(1, int) +assert isinstance(1.0, (int, float)) +assert not isinstance('c', bool)+ Source +Edit + +
template issubclass(obj, class_or_tuple): bool
why this module doesn't use pow in std/complex (we call it ncomplex.pow below):
which produce more precious result than ncomplex.pow
+Only used for ./ncomplex_pow.nim
+For other of CPython/Include/internal/pycore_pymath.h, see pylib/pyconfig/pycore/pymath.nim
+ +proc Py_ADJUST_ERANGE1(x: float) {.inline, ...raises: [], tags: [], forbids: [].}
proc Py_ADJUST_ERANGE2(x, y: float) {.inline, ...raises: [], tags: [], forbids: [].}
template genDollarRepr(Coll; start, stop: char | string; linear = false; + useIter = true) {.dirty.}
template genDollarRepr(Coll; start, stop: char | string; strProc: typed; + linear = false; useIter = true) {.dirty.}
template strIterImpl(it: typed{atom}; strProc; start, stop: char | string; + linear = false; useIter = true): string
template strIterImpl(itExpr: typed{~atom}; strProc; start, stop: char | string; + linear = false; useIter = true): string
proc hash(x: PyDict): int {.error: "TypeError: unhashable type: PyDict".}
proc hash(x: PyList): int {.error: "TypeError: unhashable type: PyList".}
proc hash(x: PySet): int {.error: "TypeError: unhashable type: PySet".}
proc hash(x: PyTComplex): int
func pyreprbImpl(s: string): string {....raises: [], tags: [], forbids: [].}
func pyreprImpl(s: string; escape127: static[bool] = false): string
Python's repr but returns Nim's string.
+nim's Escape Char feature can be enabled via -d:useNimCharEsc, in which 'e' (i.e.'x1B' in Nim) will be replaced by "\e"
+ +Example:
+# NOTE: string literal's `repr` is `system.repr`, as following. +assert repr("\"") == "\"\\\"\"" # string literal of "\"" +# use pyrepr for any StringLike and returns a PyStr +assert pyreprImpl("\"") == "'\"'"+ Source +Edit + +
template import_dtoa()
template import_obmalloc()
template import_pyconfig()
proc round(x: F; ndigit: int): F {....raises: [], tags: [], forbids: [].}
variant whose F is float32 is not implemented, and won't be unless https://netlib.org/fp/ftoa.c is implemented ( none as of 2025-02-17)
+ + Source +Edit + +set and its methods. +
set[T] is still for system.set[T], with its restriction of only allowing small ordinal as elements. PySet[T] is used to minic Python's.
+ +Something like {1,2} shall be rewritten as pyset([1,2]), please note either pyset((1,2)) or pyset({1,2}) doesn't mean the same.
+ +proc `-`[H](self: PyFrozenSet[H]; o: SomePySet[H]): PyFrozenSet[H]
proc `-`[H](self: PySet[H]; o: PyFrozenSet[H]): PyFrozenSet[H]
proc difference[H; Self: SomePySet[H]; S: not PySet[H]](self: Self; s: S): Self
proc difference[H; Self: SomePySet[H]; S](self: Self; s1: auto; s2: auto; + x: varargs[S]): Self
proc difference[H](self, o: PySet[H]): PySet[H]
proc difference[H](self: PyFrozenSet[H]; o: SomePySet[H]): PyFrozenSet[H]
proc difference[H](self: PySet[H]; o: PyFrozenSet[H]): PyFrozenSet[H]
proc difference_update[H; I: Iterable[H]](self: var SomePySet[H]; i: I)
proc frozenset[H](): PyFrozenSet[H]
proc frozenset[H](arr: openArray[H]): PyFrozenSet[H]
proc frozenset[H](it: Iterable[H]): PyFrozenSet[H]
proc frozenset[H](s: HashSet[H]): PyFrozenSet[H]
proc frozenset[H](s: SomePySet[H]): PyFrozenSet[H]
proc intersection[H; Self: SomePySet[H]; S: not PySet[H]](self: Self; s: S): Self
proc intersection[H; Self: SomePySet[H]; S](self: Self; s1: auto; s2: auto; + x: varargs[S]): Self
proc intersection[H](self, o: PySet[H]): PySet[H]
proc intersection[H](self: PyFrozenSet[H]; o: SomePySet[H]): PyFrozenSet[H]
proc intersection[H](self: PySet[H]; o: PyFrozenSet[H]): PyFrozenSet[H]
proc intersection_update[H; I: Iterable[H]](self: var SomePySet[H]; i: I)
func isdisjoint[H, S](self: SomePySet[H]; s: S): bool
proc issuperset[H, S](self, o: SomePySet[H]; s: S): bool
proc symmetric_difference[H; Self: SomePySet[H]; S: not PySet[H]](self: Self; + s: S): Self
proc symmetric_difference[H; Self: SomePySet[H]; S](self: Self; s1: auto; + s2: auto; x: varargs[S]): Self
proc symmetric_difference[H](self, o: PySet[H]): PySet[H]
proc symmetric_difference[H](self: PyFrozenSet[H]; o: SomePySet[H]): PyFrozenSet[ + H]
proc symmetric_difference[H](self: PySet[H]; o: PyFrozenSet[H]): PyFrozenSet[H]
proc union[H; Self: SomePySet[H]; S: not PySet[H]](self: Self; s: S): Self
proc union[H; Self: SomePySet[H]; S](self: Self; s1: auto; s2: auto; + x: varargs[S]): Self
proc union[H](self: PyFrozenSet[H]; o: SomePySet[H]): PyFrozenSet[H]
proc union[H](self: PySet[H]; o: PyFrozenSet[H]): PyFrozenSet[H]
PyFrozenSet[H] = frozenset[H]
func hash[H](self: PyFrozenSet[H]): int
func newPyFrozenSet[H](h: HashSet[H]): PyFrozenSet[H]
func newPyFrozenSet[H](initialSize = defaultInitialSize): PyFrozenSet[H]
template `$`(self: PyFrozenSet): string
+
ref pep of `Coroutines with async and await syntax`, Future-like object is just an alias of Awaitable
+V = 1 +async def f(): + return V + +c: Coroutine[None, None, int] = f() + +try: c.send(None) +except StopIteraion as s: assert V == s.value + +try: c.send(None) +except RuntimeError as e: assert str(e) == "cannot reuse already awaited coroutine" + +# Also: V == await f()+
pep for Asynchronous Generators
+ +V = 1 +async def f(): yield V +ag = f() + +ag_asend_obj = ag.asend(None) # or `anext(ag)` +try: ag_asend_obj.send(None) +except StopIteration as s: assert V == s.value + + +ag_asend_obj = ag.asend(None) # or `anext(ag, defval)` if wanting +# the next `send` raises `StopIteration` and its value to be `defval` + +try: ag_asend_obj.send(None) +except StopAsyncIteration: pass # iteration end + ++
for ag_asend_obj, ref link of PyAsyncGenASend:
++PyAsyncGenASend is a coroutine-like object...
+ +PyAsyncGenAThrow is very similar to PyAsyncGenASend. The only difference is that PyAsyncGenAThrow.send(), when called first time, throws an exception into the parent agen object (instead of pushing a value into it.)
AsyncGenerator[Yield; Send] = concept selfof AsyncIterator[Yield] + self.asend(Send) is Awaitable[Yield] + self.athrow(CatchableError) is Awaitable[void]
AsyncIterable[T] = concept self + aiter(self) is AsyncIterator[T]
AsyncIterator[T] = concept selfof AsyncIterable[T] + anext(self) is Awaitable[T]
proc aclose(self: AsyncGenerator): owned(Future[void]) {....stackTrace: false.}
proc anext[T](self: AsyncGenerator[T]): Awaitable[T] {.inline.}
proc anext[T](self: AsyncGenerator[T]; default: T): Awaitable[T] {.inline.}
Mapping[K; V] = concept selfof Collection[K] + K + V + self[K] is V
MutableSequence[T] = concept selfof Sequence[T] + T + self[int] = T + self.delitem(int) + self.insert(int, T) ## insert item before index
Sequence[T] = concept selfof Collection[T] + T + self[int] is T
func append[T](ms: MutableSequence[T]; x: T)
func clear(ms: MutableSequence)
func extend[T](ms: MutableSequence[T]; it: Iterable[T])
func pop[T](ms: MutableSequence[T]; index = -1): T
func remove[T](ms: MutableSequence[T]; x: T)
func reverse(ms: MutableSequence)
Generator[YieldType; SendType; ReturnType] = concept selfof Iterator[YieldType] + try: + self.send(SendType) is YieldType + except StopIterationT[ReturnType]: + discard + self.throw(CatchableError)
We use origin dtoa.c over Python's
+proc ACQUIRE_DTOA_LOCK(n: cint) {.exportc, ...raises: [], tags: [], forbids: [].}
proc dtoa_r(dd: cdouble; mode, ndigits: cint; decpt, sign: var cint; + rve: var cstring; buf: cstring; blen: csize_t): cstring {. + importc: "dtoa_r", cdecl, discardable, ...raises: [], tags: [], forbids: [].}
char* dtoa_r(double dd, int mode, int ndigits, int *decpt, int *sign, char **rve, char *buf, size_t blen)+ Source +Edit + +
proc FREE_DTOA_LOCK(n: cint) {.exportc, ...raises: [], tags: [], forbids: [].}
proc getThreadId(): cint {.exportc: "dtoa_get_threadno", ...raises: [], tags: [], + forbids: [].}
NOTE: not support js currently +
Its param: closefd, opener is not implemented yet
+ +There is difference that Python's TextIOBase.seek will reset state of encoder at some conditions, while Nim doesn't have access to encoder's state Therefore, seek here doesn't change that
+ +Python's __next__ will yield newline as part of result but Nim's iterator lines does not
+ + + + +CanIOOpenT[T] = int | PathLike[T]
proc `$`(p: CanIOOpenT): string
template mapPathLike[T](nexpr): T
template mapPathLike[T](s: PathLike[T]; nimProc): T
As Python's MutableSequence does not mixin these we place them here.
+template bodySetItem(Arr) {.dirty.}
template genDelItem(Arr) {.dirty.}
template genGenericSetItem(Arr, Arr2) {.dirty.}
template genNonGenericSetItem(Arr, Arr2) {.dirty.}
JsBigInt64Option = true
NimVersionTuple = (2, 2, 4)
func as_integer_ratio(self: float; n = halfHigh(int)): (int, int) {. + ...raises: [ValueError], tags: [], forbids: [].}
func as_someinteger_ratio[I: SomeInteger](self: float; n = halfHigh(I)): (I, I)
EXT. Calculates the best rational approximation of x, where the denominator is smaller than n (default is the largest possible I for maximal resolution),
+The algorithm is from toRational of std/rationals, based on the theory of continued fractions. David Eppstein / UC Irvine / 8 Aug 1993 , but raises ValueError or OverflowDefect if x is NaN or Infinity.
+func checked_as_integer_ratio(self: float): (int, int) {....raises: [ValueError], + tags: [], forbids: [].}
func float_fromhex(s: string): float {....raises: [ValueError, Exception], + tags: [], forbids: [].}
func is_integer(self: float): bool {....raises: [], tags: [], forbids: [].}
func parse_inf_or_nan(ori_s: openArray[char]; res: var float): int {....raises: [], + tags: [], forbids: [].}
func parse_inf_or_nan(res: var float; ori_s: openArray[char]): bool {. + ...raises: [], tags: [], forbids: [].}
returns if successfully parses returns false when there are chars left after parsed in ori_s
+XXX: don't use parseFloat in std/strutils currently as it does not respect sign bit of NaNs.
+ + Source +Edit + +func parsePyFloat(a: openArray[char]; res: var BiggestFloat): int {....raises: [], + tags: [], forbids: [].}
template bit_length(self: NimInt): NimInt
template is_integer(_: NimInt): bool
func add_from_bytes(res: var NimInt; bytes: PyBytes; byteorder: Endianness; + signed = false) {....raises: [], tags: [], forbids: [].}
TODO: later may allow to switch to bigints when compile
+ +template long(a: bool): int {....deprecated: """long(a.k.a. PyLong) is not supported, +currently it's just a alias of BiggestInt (e.g. int64 on 64bit system)""".}
template long(a: char): BiggestInt {....deprecated: """long(a.k.a. PyLong) is not supported, +currently it's just a alias of BiggestInt (e.g. int64 on 64bit system)""".}
used by ./int_bytes
+ +func stripAsRange(s: openArray[char]; leading: static[bool] = true; + trailing: static[bool] = true; + runes: openArray[Rune] = unicodeSpaces): tuple[ + first, last: int]
+
For
+template `/=`*(x: var SomeInteger, y: SomeInteger)+
Nim is static-typed, but /= will cause lhs convert from int to float
+ +func `//`[A, B: SomeFloat | SomeInteger](a: A; b: B): SomeNumber {.inline.}
Example:
+assert 13 // -3 == -5 +assert 13 div -3 == -4+ Source +Edit + +
template `**`[T: SomeInteger](a: T; b: static[int]): T | float
power for static int b
+so that result type can be inferred:
+For non-static int b, `**`(a: T; b: Natural) is used.
+ +Example:
+const f = 5 ** -1 # only when the rhs is static[int] +assert f == 0.2 +const i = 5 ** 2 +assert i == int(25)+ Source +Edit + +
template `**`[T](a: T; b: Natural): T
power for b is a non-static integer:
+only Natural is acceptable unless b is static, see `**`(a: T; b: static[int])
+ +Example:
+var i = -1 +doAssertRaises RangeDefect: + discard (5 ** i) + ## this runs iff `i` is of static[int] + ## e.g. `5 ** -1`+ Source +Edit + +
CompileBackend {.pure.} = enum + c = "C", cpp = "C++", objc = "Object-C", js = "JavaScript", + nimscript = "NimScript"
template noBackends(backends: untyped; def)
template noJsBackend(def)
template noNimsBackend(def)
template noWeirdBackend(def)
proc encodings.normalize_encoding(encoding: string): string {....raises: [], + tags: [], forbids: [].}
Normalize an encoding name.
+Normalization works as follows: all non-alphanumeric characters except the dot used for Python package names are collapsed and replaced with a single underscore, e.g. ' -;#' becomes '_'. Leading and trailing underscores are removed.
+Note that encoding names should be ASCII only.
+ + Source +Edit + +proc Py_normalize_encoding(encoding: string): string {....raises: [], tags: [], + forbids: [].}
func inspect.cleandoc(doc: openArray[char]): string {....raises: [], tags: [], + forbids: [].}
Clean up indentation from docstrings.
+Any whitespace that can be uniformly removed from the second line onwards is removed.
+compiled. no need to keep the leading adn tailing blank lines like Python/compile.c: _PyCompile_CleanDoc does.
+ + Source +Edit + +func `==`(b: bool; self: PyBool): PyBool {.borrow, ...raises: [], tags: [], + forbids: [].}
func `and`(b: bool; self: PyBool): PyBool {.borrow, ...raises: [], tags: [], + forbids: [].}
func `and`(self: PyBool; b: bool): PyBool {.borrow, ...raises: [], tags: [], + forbids: [].}
func `or`(b: bool; self: PyBool): PyBool {.borrow, ...raises: [], tags: [], + forbids: [].}
func `or`(self: PyBool; b: bool): PyBool {.borrow, ...raises: [], tags: [], + forbids: [].}
converter pybool(x: bool): PyBool {....raises: [], tags: [], forbids: [].}
converter pybool[T](x: T): PyBool
Converts any to PyBool
+NOTE: In Nim, "implicit converter chain is not support". (See manual.html). Therefore any type can be implicitly converted to PyBool, not bool, which, however, is desired, as if any is convertible to bool, then there'll be ## compile-error for repr(<list>)
+ + Source +Edit + +BytesLike = PyByteArray | PyBytes
PyByteArray = ref object
func `$`(self: PyByteArray): string {....raises: [], tags: [], forbids: [].}
func `*=`(mself: PyByteArray; n: int) {....raises: [], tags: [], forbids: [].}
bytearray.__imul__
+Python: if n < 1: self.clear()
+ + Source +Edit + +func `+=`(mself: PyByteArray; other: BytesLike)
func `<`(self: PyByteArray; other: PyByteArray): bool {....raises: [], tags: [], + forbids: [].}
func `<`(self: PyByteArray; other: PyBytes): bool {....raises: [], tags: [], + forbids: [].}
func `<=`(self: PyByteArray; other: PyByteArray): bool {....raises: [], tags: [], + forbids: [].}
func `<=`(self: PyByteArray; other: PyBytes): bool {....raises: [], tags: [], + forbids: [].}
func `==`(self: PyByteArray; other: PyByteArray): bool {....raises: [], tags: [], + forbids: [].}
func `==`(self: PyByteArray; other: PyBytes): bool {....raises: [], tags: [], + forbids: [].}
func `[]`(self: PyByteArray; i: HSlice[int, BackwardsIndex]): PyByteArray {. + ...raises: [], tags: [], forbids: [].}
func `[]`(self: PyByteArray; i: Slice[int]): PyByteArray {....raises: [], tags: [], + forbids: [].}
func `[]=`(ms: var PyByteArray; indices: Slice[int]; o: Sequence[int])
func `[]=`(mself: PyByteArray; i: HSlice[int, BackwardsIndex]; val: BytesLike)
func `[]=`(mself: PyByteArray; i: int; val: int) {....raises: [], tags: [], + forbids: [].}
func `[]=`(mself: PyByteArray; i: Slice[int]; val: BytesLike)
func append(mself: PyByteArray; val: int) {....raises: [ValueError], tags: [], + forbids: [].}
func bytearray(): PyByteArray {....raises: [], tags: [], forbids: [].}
func bytearray(it: Iterable[char]): PyByteArray
func bytearray(it: Iterable[int]): PyByteArray
func bytearray(nbytes: int): PyByteArray {....raises: [ValueError], tags: [], + forbids: [].}
func bytearray(o: BytesLike): PyByteArray
func bytearray(s: string): PyByteArray {....raises: [], tags: [], forbids: [].}
func bytes(self: sink PyByteArray): PyBytes {.inline, ...raises: [], tags: [], + forbids: [].}
func clear(mself: PyByteArray) {....raises: [], tags: [], forbids: [].}
func copy(self: PyByteArray): PyByteArray {....raises: [], tags: [], forbids: [].}
func delitem(ms: var PyByteArray; indices: PySlice) {....raises: [], tags: [], + forbids: [].}
func delitem(ms: var PyByteArray; indices: Slice[int]) {....raises: [], tags: [], + forbids: [].}
func delitem(mself: PyByteArray; i: int) {....raises: [], tags: [], forbids: [].}
func extend(mself: PyByteArray; other: BytesLike)
func getChar(self: PyByteArray; i: Natural): char {....raises: [], tags: [], + forbids: [].}
func getCharPtr(self: PyByteArray; i: Natural | Natural): ptr char
func insert(mself: PyByteArray; i: int; val: int) {....raises: [ValueError], + tags: [], forbids: [].}
func len(self: PyByteArray): int {....raises: [], tags: [], forbids: [].}
func newPyByteArray(): PyByteArray {.inline, ...raises: [], tags: [], forbids: [].}
func newPyByteArray(len: int): PyByteArray {.inline, ...raises: [], tags: [], + forbids: [].}
func newPyByteArray(s: sink string): PyByteArray {.inline, ...raises: [], tags: [], + forbids: [].}
func pop(mself: PyByteArray): int {....raises: [], tags: [], forbids: [].}
func remove(mself: PyByteArray; val: int) {....raises: [ValueError], tags: [], + forbids: [].}
func reverse(mself: PyByteArray) {....raises: [], tags: [], forbids: [].}
func toNimString(self: PyByteArray): string {....raises: [], tags: [], forbids: [].}
func toNimString(self: var PyByteArray): var string {....raises: [], tags: [], + forbids: [].}
iterator chars(self: PyByteArray): char {....raises: [], tags: [], forbids: [].}
iterator items(self: PyByteArray): int {....raises: [], tags: [], forbids: [].}
converter toPyBytes(self: PyByteArray): PyBytes {....raises: [], tags: [], + forbids: [].}
func `+`(o: char; self: PyBytes): PyBytes {....raises: [], tags: [], forbids: [].}
func `+`(o: string; self: PyBytes): PyBytes {....raises: [], tags: [], forbids: [].}
func `+`(self: PyBytes; o: char): PyBytes {....raises: [], tags: [], forbids: [].}
func `[]`(self: PyBytes; i: HSlice[int, BackwardsIndex]): PyBytes {....raises: [], + tags: [], forbids: [].}
func bytes(nLen: int): PyBytes {....raises: [], tags: [], forbids: [].}
func bytes(s: openArray[char | uint8]): PyBytes
EXT.
+Python has no concept of openArray
+ + Source +Edit + +func bytes(s: sink string): PyBytes {.inline, ...raises: [], tags: [], forbids: [].}
func bytes(self: PyBytes): PyBytes {....raises: [], tags: [], forbids: [].}
func getCharPtr(self: PyBytes; i: Natural | BackwardsIndex): ptr char
converter toNimString(self: PyBytes): string {....raises: [], tags: [], forbids: [].}
func capitalize(a: PyBytes): PyBytes {....raises: [], tags: [], forbids: [].}
func count(a: PyBytes; sub: int): int {....raises: [ValueError], tags: [], + forbids: [].}
func count(a: PyBytes; sub: int; start = 0; end: int): int {. + ...raises: [ValueError], tags: [], forbids: [].}
func count(a: PyBytes; sub: int; start: int): int {....raises: [ValueError], + tags: [], forbids: [].}
func count(a: PyBytes; sub: PyBytes): int {....raises: [], tags: [], forbids: [].}
func endsWith(a: PyBytes; suffix: char): bool {....raises: [], tags: [], + forbids: [].}
func endsWith(a: PyBytes; suffix: int): bool {....raises: [ValueError], tags: [], + forbids: [].}
func endsWith[Suf: PyBytes | tuple](a: PyBytes; suffix: Suf; start, end: int): bool
func expandtabs(a: PyBytes; tabsize = 8): PyBytes {....raises: [], tags: [], + forbids: [].}
func startsWith(a: PyBytes; suffix: char): bool {....raises: [], tags: [], + forbids: [].}
func startsWith(a: PyBytes; suffix: int): bool {....raises: [ValueError], tags: [], + forbids: [].}
func startsWith[Suf: PyBytes | tuple](a: PyBytes; suffix: Suf; start, end: int): bool
func startsWith[Suf: PyBytes | tuple](a: PyBytes; suffix: Suf; start: int): bool
func startsWith[Tup: tuple](a: PyBytes; suffix: Tup): bool
--- HAVE_PY_SET_53BIT_PRECISION macro ------------------------------------Inline assembly for getting and setting the 387 FPU control word on GCC/x86.ifdef _Py_MEMORY_SANITIZERendif
+ +DOUBLE_IS_ARM_MIXED_ENDIAN_IEEE754 = false
DOUBLE_IS_BIG_ENDIAN_IEEE754 = false
DOUBLE_IS_LITTLE_ENDIAN_IEEE754 = true
HAVE_GCC_ASM_FOR_MC68881 = false
HAVE_GCC_ASM_FOR_X87 = true
X87_double_rounding = false
template HAVE_PY_SET_53BIT_PRECISION(): bool
template Py_SET_53BIT_PRECISION_END()
template Py_SET_53BIT_PRECISION_HEADER() {.dirty.}
template Py_SET_53BIT_PRECISION_START()
O_DIRECTORY = 65536'i32
O_NOFOLLOW = 131072'i32
ref https://nim-lang.org/docs/manual.html#types-preminusdefined-floatingminuspoint-types Nim's float XX shall always follows IEEE754 --- _PY_SHORT_FLOAT_REPR macro -------------------------------------------
+WORDS_BIGENDIAN = false
WORDS_LITTLEENDIAN = true
HAVEgetitimer = true
HAVEpthread_kill = true
HAVEpthread_sigmask = true
HAVEsetitimer = true
HAVEsigaction = true
HAVEsigfillset = true
HAVEsiginterrupt = true
HAVEsigpending = true
HAVEsigtimedwait = true
HAVEsigwait = true
HAVEsigwaitinfo = true
HAVEstrsignal = true
macro AC_CHECK_FUNCS(xs: varargs[untyped]): untyped
macro AC_CHECK_HEADER(header)
macro AC_CHECK_HEADER_THEN_FUNCS(header; functions)
macro AC_CHECK_HEADERS(xs: varargs[untyped]): untyped
macro from_c_int_expr(cExpr: static[string]; defval: int): int
macro from_c_int_underlined(variable: static[string]; defval: int): int
template AC_CHECK_FUNC(function)
template AC_CHECK_FUNC(res, function)
template AC_CHECK_HEADER(res, header)
template AC_LINK_IFELSE(variable, defval, code)
template AC_RUN_IFELSE(variable, defval, code)
template AX_C_FLOAT_WORDS_BIGENDIAN(id; doIfTrue, doIfFalse, doIfUnknown) {. + dirty.}
template AX_C_FLOAT_WORDS_BIGENDIAN_def(defIfTrue, defIfFalse, doIfUnknown)
template from_c_int(variable; defval: int; precode): int
template from_c_int(variable; defvar: int): int
template from_c_int(variable; includeFile: static[string]; defval = low(int)): int
ArithmeticError = object of CatchableError
ZeroDivisionError = object of ArithmeticError
See CPython's Objects/exceptions.c
+OSError_new(a.k.a. OSError.__new__) will returns a subclass of OSError, via lookup in state->errnomap, which is initialized by _PyExc_InitState,
+where key-value pairs are inserted via ADD_ERRNO macro.
+ +proc raiseErrno(errno = getErrno()) {....raises: [PyOSError], tags: [], forbids: [].}
proc raiseErrnoT[T: PyOSError](errno = getErrno())
proc raiseErrnoWithPath[T](p: PathLike[T]; errno = getErrno())
func raiseExcWithPath(fp: PathLike; exc: typedesc; err: OSErrorCode; + additionalInfo: string)
proc raiseExcWithPath(fp: PathLike; exc: typedesc; err: OSErrorCode; + osErrorMsgCb: proc = osErrorMsg)
proc raiseExcWithPath(p: PathLike) {.sideEffect.}
proc raiseExcWithPath(p: PathLike; errCode: OSErrorCode) {.sideEffect.}
proc raiseExcWithPath2(src, dst: PathLike)
template noWeirdTarget(def)
template osErrorMsgWithPath(fp: PathLike; err: OSErrorCode): string
template osErrorMsgWithPath(fp: PathLike; err: OSErrorCode; osErrorMsgCb): string
proc default_oserror(): ref PyOSError {.nimcall, noSideEffect, ...raises: [], + tags: [], forbids: [].}
template decl_c_int(name, includeFile; defval)
proc BlockingIOError(myerrno: cint; strerr: string; filename = 0; + winerror: cint = 0; filename2 = ""): ref PyOSError {. + ...raises: [], tags: [], forbids: [].}
proc BlockingIOError(strerr: string = ""): ref PyOSError {....raises: [], tags: [], + forbids: [].}
proc newBlockingIOError(myerrno: cint; strerr: string; filename = 0; + winerror: cint = 0; filename2 = ""): ref PyOSError {. + ...raises: [], tags: [], forbids: [].}
proc newBlockingIOError(strerr: string = ""): ref PyOSError {....raises: [], + tags: [], forbids: [].}
proc newPyOSError(myerrno: cint; strerr: string; filename = ""; + winerror: cint = 0; filename2 = ""): ref PyOSError {. + ...raises: [], tags: [], forbids: [].}
proc newPyOSError(strerr: string = ""): ref PyOSError {....raises: [], tags: [], + forbids: [].}
Where a function has a single filename, such as open() or some of the os module functions, PyErr_SetFromErrnoWithFilename() is called, giving a third argument which is the filename. But, so that old code using in-place unpacking doesn't break, e.g.:
+except OSError, (errno, strerror):
+we hack args so that it only contains two items. This also means we need our own __str__() which prints out the filename when it was supplied.
+(If a function has two filenames, such as rename(), symlink(), or copy(), PyErr_SetFromErrnoWithFilenameObjects() is called, which allows passing in a second filename.)
+ +OSErrorArgs[third] = tuple[errno: cint, strerror: string, filename: third, + winerror: cint, filename2: string]
proc init[E: PyOSError](self: ref E; args: OSErrorArgs)
proc OSError_new[E: PyOSError](myerrno: cint; strerr: string; + filename: string | int = ""; winerror: cint = 0; + filename2 = ""; fillMsg: static[bool] = true): ref PyOSError
template oserror_use_init[E: PyOSError](self): bool
When __init__ is defined in an OSError subclass, we want any extraneous argument to __new__ to be ignored. The only reasonable solution, given __new__ takes a variable number of arguments, is to defer arg parsing and initialization to __init__.
+But when __new__ is overridden as well, it should call our __new__ with the right arguments.
+(see http://bugs.python.org/issue12555#msg148829 )
+ + Source +Edit + +BlockingIOError = object of oserror_decl.PyOSError
BrokenPipeError = object of ConnectionError
ChildProcessError = object of oserror_decl.PyOSError
ConnectionAbortedError = object of ConnectionError
ConnectionError = object of oserror_decl.PyOSError
ConnectionRefusedError = object of ConnectionError
ConnectionResetError = object of ConnectionError
FileExistsError = object of oserror_decl.PyOSError
FileNotFoundError = object of oserror_decl.PyOSError
InterruptedError = object of oserror_decl.PyOSError
IsADirectoryError = object of oserror_decl.PyOSError
NotADirectoryError = object of oserror_decl.PyOSError
PermissionError = object of oserror_decl.PyOSError
ProcessLookupError = object of oserror_decl.PyOSError
TimeoutError = object of oserror_decl.PyOSError
KeyboardInterrupt = object of CatchableError
NotImplementedError = object of RuntimeError
RuntimeError = object of CatchableError
GeneratorExit = object of CatchableError
StopAsyncIteration = object of CatchableError
StopIteration = StopIterationT[NoneType]
StopIterationT[T] = object of CatchableError + value*: T ## generator return value
func `$`(self: StopIteration): string {....raises: [], tags: [], forbids: [].}
func `$`(self: StopIterationT): string
func msg(self: StopIteration): string {....raises: [], tags: [], forbids: [].}
func msg(self: StopIterationT): string
func newStopIteration(): ref StopIteration {....raises: [], tags: [], forbids: [].}
func newStopIteration[T](value: T): ref StopIterationT[T]
UnicodeDecodeError = object of UnicodeError
UnicodeError = object of ValueError
func newUnicodeDecodeError(codec: string; src: char; start, stop: int; + reason: string): ref UnicodeDecodeError {. + ...raises: [ValueError], tags: [], forbids: [].}
func newUnicodeDecodeError(codec: string; src: string; start, stop: int; + reason: string): ref UnicodeDecodeError {. + ...raises: [ValueError], tags: [], forbids: [].}
unicodeSpaces = [9'i32, 10'i32, 11'i32, 12'i32, 13'i32, 28'i32, 29'i32, 30'i32, + 31'i32, 32'i32, 133'i32, 160'i32, 5760'i32, 8192'i32, 8193'i32, + 8194'i32, 8195'i32, 8196'i32, 8197'i32, 8198'i32, 8199'i32, + 8200'i32, 8201'i32, 8202'i32, 8232'i32, 8233'i32, 8239'i32, + 8287'i32, 12288'i32]
f-string
+a string literal with a prefix of fr, Fr, rf of Rf behaves as if with a prefix of strformat.fmt.
+and f"xxx" is different, where the escaped literals in string will be interpreted.
+ +Example:
+import src/pylib/pystring/fstring +assert fr"\n" == "\\n" +assert f"\n" == "\n" + +let s = "asd" + +assert f"[{s}]" == "[asd]" +assert not compiles(fr s)+
template f(s: string{lit}): PyStr
Python F-String.
+Not the same as Nim's fmt"xxx" as that's equal to fmt r"xxx", a.k.a fr"xx" in Python
+Any escape-translation error is reported at compile-time, with information of filename and line number
+ +\Uhhhhhhhh is supported as Python's, while Nim's \U{...} is unsupported but \u{...} is reserved
+ +\\[0-7]{1,3} in f-string will be interpreted as octal digit as Python,
+instead of decimal as Nim.
+ +the following shows the deature of Nim's multiline string which is different from Python's
+assert "" == """ +""" + +## Unicode Names +`\N{name}` is not supported yet. ++ +
Example:
+assert f"\n" == "\n" +assert f"123{'a'}\n456" == "123a\n456" + +assert f"\U0001f451" == "👑" + +assert f"\10" == "\x08" # nim's "\10" means chr(10) + +assert f"""\t123 +""" == "\t123\n" # even if the source code's newline is crlf.+ Source +Edit + +
func ascii(us: string): PyStr {....raises: [], tags: [], forbids: [].}
Example:
+assert ascii("𐀀") == r"'\U00010000'" +assert ascii("đ") == r"'\u0111'" +assert ascii("和") == r"'\u548c'" +let s = ascii("v我\n\e") +when not defined(useNimCharEsc): + let rs = r"'v\u6211\n\x1b'" +else: + let rs = r"'v\u6211\n\e'" +assert s == rs +assert ascii("\"") == "'\"'" +assert ascii("\"'") == "'\"\\''" +let s2 = ascii("'") +when not defined(singQuotedStr): + let rs2 = "\"'\"" +else: + let rs2 = r"'\''" +assert s2 == rs2+ Source +Edit + +
func pyrepr(s: StringLike): PyStr
Example:
+# NOTE: string literal's `repr` is `system.repr`, as following. +assert repr("\"") == "\"\\\"\"" # string literal of "\"" +# use pyrepr for any StringLike and returns a PyStr +assert pyrepr("\"") == "'\"'"+ Source +Edit + +
func repr(x: PyStr): string {....raises: [], tags: [], forbids: [].}
Overwites system.repr for PyStr
+The same as proc ascii except for unicode chars being remained AS-IS, and returns Nim's string.
+ + Source +Edit + +StringLike = string | char | PyStr
func `==`(o: string; self: PyStr): bool {.borrow, ...raises: [], tags: [], + forbids: [].}
func `[]`(self: PyStr; i: HSlice[int, BackwardsIndex]): PyStr {....raises: [], + tags: [], forbids: [].}
converter toNimString(self: PyStr): string {....raises: [], tags: [], forbids: [].}
func capitalize(a: PyStr): PyStr {....raises: [], tags: [], forbids: [].}
make the first character have title/upper case and the rest lower case.
+changed when Python 3.8: the first character will have title case.
+while Nim's unicode.capitalize only make the first character upper-case.
+ + Source +Edit + +func casefold(a: PyStr): PyStr {....raises: [], tags: [], forbids: [].}
str.casefold()
+str.lower() is used for most characters, but, for example, Cherokee letters is casefolded to their uppercase counterparts, and some will be converted to their normal case, e.g. "ß" -> "ss"
+ + Source +Edit + +func count(a: PyStr; sub: PyStr): int {....raises: [], tags: [], forbids: [].}
func endsWith(a: char; suffix: PyStr): bool {....raises: [], tags: [], forbids: [].}
func endsWith(a: PyStr; suffix: char): bool {....raises: [], tags: [], forbids: [].}
func endsWith[Suf: PyStr | tuple](a: PyStr; suffix: Suf; start, end: int): bool
func expandtabs(a: PyStr; tabsize = 8): PyStr {....raises: [], tags: [], + forbids: [].}
func lower(a: PyStr): PyStr {....raises: [], tags: [], forbids: [].}
str.lower
+not the same as Nim's unicode.toLower, see examples
+ +Example:
+import std/unicode +let dotI = Rune 0x0130 # İ (LATIN CAPITAL LETTER I WITH DOT ABOVE) +assert str(dotI).lower() == "i\u0307" ## i̇ (\u0207 is a upper dot) +assert dotI.toLower() == Rune('i')+ Source +Edit + +
func startsWith(a: char; suffix: PyStr): bool {....raises: [], tags: [], + forbids: [].}
func startsWith(a: PyStr; suffix: char): bool {....raises: [], tags: [], + forbids: [].}
func startsWith[Suf: PyStr | tuple](a: PyStr; suffix: Suf; start, end: int): bool
func startsWith[Suf: PyStr | tuple](a: PyStr; suffix: Suf; start: int): bool
func startsWith[Tup: tuple](a: PyStr; suffix: Tup): bool
func title(a: PyStr): PyStr {....raises: [], tags: [], forbids: [].}
str.title()
+not the same as title proc in std/unicode, see example.
+ +Example:
+let s = "lj" # \u01c9 +let u = str(s) +assert u.title() == "Lj" # \u01c8 +import std/unicode +assert unicode.title(s) == "LJ" # \u01c7+ Source +Edit + +
func upper(a: PyStr): PyStr {....raises: [], tags: [], forbids: [].}
str.upper
+not the same as Nim's unicode.toUpper, see examples
+ +Example:
+import std/unicode +let a = "ᾷ" +# GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI +assert str(a).upper() == "Α͂Ι" # 3 chars +assert a.toUpper() == a # Nim just maps it as-is. +# There is more examples... (101 characters in total)+ Source +Edit + +
template `*`(a: StringLike; i: int): PyStr
template `*`(i: int; a: StringLike): PyStr
str.translate
NOTE: Nim's KeyError is a subclass of ValueError instead of LookupError. Therefore when writing a custom TranslateTableABC or TypedTranslateTableABC for translate, beware a Nim's KeyError is not considered as a sign to leave such a character untouched, but will be just raised outside.
+However, TranslateTable or StrTypedTranslateTable is handled via overload. Using them as translate table is fine.
+ +StrTypedTranslateTable = TableRef[int, PyStr]
TranslateAction {.pure.} = enum + skip, aOrd, aChr, aStr
TranslateTable = TableRef[int, TranslateTableVal]
TranslateTableABC = concept self + self[int] is TranslateTableVal
TranslateTableVal = object + case + of skip: + nil + of aOrd: + i*: int + of aChr: + c*: char + of aStr: + s*: PyStr
TranslateValType = int | PyStr | char | NoneType
TypedTranslateTableABC[V] = concept self + V + self[int] is V
func repr(table: TranslateTable): string {....raises: [], tags: [], forbids: [].}
proc translate(s: PyStr; table: StrTypedTranslateTable): PyStr {. + ...raises: [TypeError], tags: [], forbids: [].}
proc translate(s: PyStr; table: TranslateTable): PyStr {. + ...raises: [TypeError, ValueError, KeyError], tags: [], forbids: [].}
proc translate[K: TranslateValType](s: PyStr; table: TypedTranslateTableABC[K]): PyStr
macro maketrans(_: typedesc[PyStr]; mapOrLit: untyped): TranslateTable
Example:
+let tbl = PyStr.maketrans({"a": None, "b": "123"}) +assert "axb".translate(tbl) == "x123"+ Source +Edit + +
template `$`(table: TranslateTable): string
macro del(seqIdx: untyped)
dynamically deleting object's attributes is not allowed.
+for more details.
+PyDedentDocString = true
PySignatureSupportGenerics = true
func parserWithDefCfg(): PyAsgnRewriter {....raises: [], tags: [], forbids: [].}
python's def and async def
+support:
+limits:
+unsupport:
+see codes in runnableExamples for more details
+ +macro async(defsign, body): untyped
Example:
+import std/async +async def af(): + discard "no restype mean Future[void]" +async def afi() -> Future[int]: + return 3 +when defined(js): + await af() + echo await afi() +else: + import std/asyncdispatch + waitFor af() + assert 3 == waitFor(afi())+ Source +Edit + +
macro def(signature, body): untyped
Example:
+def add(a,b): return a + b # use auto as argtype and restype +def addi(a: int, b = 1) -> int: return add(a, b) +assert addi(3) == 4 +def nested(a): + def closure(): + return a + return closure +assert nested(3)() == 3 +def max(a, b, *args): + "This is doc-str: a python-like `max`" + def max2(a,b): + if a>b: return a + else: return b + result = max2(a, b) + for i in args: + result = max2(result, i) + return result +assert max(1,4,2,5,0) == 5 +when PySignatureSupportGenerics: # pysince 3.13 + def sub[T](a: T, b: T) -> T: + return a - b + assert sub(4, 5) == -1 + + def f2[A, B](a: A, b: B) -> A: + return a + A(b) + assert int(2) == f2(1, 1.0)+ Source +Edit + +
macro define(signature, body): untyped
almost the same as def, but is for template instead of proc
+XXX: nesting define is not supported. If wanting, use template. however, def in define is allowed.
+ +Example:
+define templ(a): a+1 # note template has no implicit `result` variable +assert templ(3) == 4+ Source +Edit + +
proc expandChainImpl(cExp: NimNode): NimNode {....raises: [], tags: [], forbids: [].}
macro expandChain(cExp): bool
proc classImpl(parser: var PySyntaxProcesser; obj, body: NimNode; + topLevel = true): NimNode
minic Python's class.
+support def for method with nested def/class supported and super(...).method
+ +Now the implement assume each def in each child class overwrite parent class's def, which is surely not always true,
+What's more, it will be false in some less-noted cases:
+class O: +def f(self): return 1 +class O1(O): +def f(self): return 1.0The above code will cause Warning: use {.base.} for base methods; baseless methods are deprecated [UseBase] +
as the rettype of previous one is int, while the latter is float, thus no override and no dynamic dispatch is performed.
+ +Now support super([self[,SubCls]]).f([arg,...])
+However, only support the one usage above.
+That's, neither a=super() nor super().a is supported
+For the precious one, as now super is implemented via Nim's procCall, it's not easy to bind super()(aka. a SupCls instance) to a variable.
+For the latter one, as Nim doesn't allow override SupCls's attr (lead to a compile-error), so if wantting the attr inherited from SupCls, just write it as-is (e.g. self.a) (Technologically, it can be implemented via std/macros owner)
+ + Source +Edit + +proc init_subclass[T: ref](cls: typedesc[T])
proc recReplaceSuperCall(n: NimNode; defSupCls: NimNode; start = 0; + methKind = mkNorm): NimNode {....raises: [], tags: [], + forbids: [].}
super(...).f(...) to procCall(<SuperClass>(self).f(...))
+The AST map:
+Call +DotExpr +Call + Ident "super" + [<SuperClass>] + [Ident "self"] +Ident "f" +<args> + +| +| +v + +Command +Ident "procCall" +Call +DotExpr + Call + <SuperClass> + Ident "self" + Ident "f" +<args>+ +
super(...).new/init_subclass(...) to <SuperClass>.new/init_subclass(...)
+ +Example:
+import std/[macros, strutils] +macro checkSupSub(resStr: static string; b) = + let res = recReplaceSuperCall(b, ident"SupCls") + assert resStr == repr(res).strip(), repr(res) + result = newStmtList() +checkSupSub("procCall(SupCls(self).f())"): + super().f() +checkSupSub("procCall(SS(self).f(a, b))"): + super(SS, self).f(a, b) +checkSupSub("a = procCall(SupCls(self).f(a, b))"): + a = super().f(a, b) +checkSupSub("a = procCall(SupCls(self).f(procCall(SupCls(self).m()), b))"): + a = super().f(super().m(), b) +checkSupSub("echo(1)"): echo(1) + +# NOTE: the following is not supported, so left unchanged +checkSupSub("super()"): super() +checkSupSub("super().a"): super().a+ Source +Edit + +
Literal[a, b] cannot be implemented in Nim's type system (i.e. via type Literal[...)
+proc parseDeclWithType(def: NimNode): tuple[name, typ, val: NimNode] {. + ...raises: [], tags: [], forbids: [].}
proc rewriteDeclInStmtAux(variable, oriTyp, val: NimNode; + typId = oriTyp.ensureType): NimNode {....raises: [], + tags: [], forbids: [].}
template rewriteDeclAux(variable, oriTyp, val: NimNode; + typId = oriTyp.ensureType; + doLiteral: DoXxx = newConstStmtWithType; + doFinal: DoXxx = nnkLetSection.newDecl; + doElse: DoXxx = nnkVarSection.newDecl): NimNode
proc consumeDecorator(mparser; procDef: NimNode): NimNode {....raises: [], + tags: [], forbids: [].}
gen:
+block: + `procDef` + decorator(... (`procDef`))+ + Source +Edit + +
proc extractDottedCalledDecorator(decorator: NimNode): NimNode {....raises: [], + tags: [], forbids: [].}
proc pushDecorator(mparser; item: NimNode) {....raises: [], tags: [], forbids: [].}
proc tryHandleDecorator(mparser; statement: NimNode): bool {....raises: [], + tags: [], forbids: [].}
proc callToPyExpr(mparser; e: NimNode): NimNode {....raises: [Exception], + tags: [RootEffect], forbids: [].}
proc toPyExprNoList(mparser; atm: NimNode): NimNode {....raises: [Exception], + tags: [RootEffect], forbids: [].}
Stack Frame
+Decorator = ref object + name*: NimNode + case called*: bool + of true: + args*: seq[NimNode] + of false: + nil
PyAsgnFrame = ref object
PyAsgnRewriter = object + dedentDoc*: bool + supportGenerics*: bool + classes*: seq[NimNode] ## class type, + ## empty if outside a `class` definition + globals*: seq[string]
proc decorators(mparser): var seq[Decorator] {....raises: [], tags: [], forbids: [].}
proc newPyAsgnFrame(): PyAsgnFrame {....raises: [], tags: [], forbids: [].}
proc newPyAsgnRewriter(supportGenerics = false; dedentDoc = false): PyAsgnRewriter {. + ...raises: [], tags: [], forbids: [].}
proc nonlocalAdd(mparser; ident: string) {....raises: [], tags: [], forbids: [].}
proc nonlocalContains(mparser; ident: string): bool {....raises: [], tags: [], + forbids: [].}
proc onceDeclInFrames(ident: string; mparser): bool {....raises: [], tags: [], + forbids: [].}
func newGenericsTree(): NimNode {....raises: [], tags: [], forbids: [].}
func parseBracketGenericParams(generics: var NimNode; params: NimNode): NimNode {. + ...raises: [], tags: [], forbids: [].}
func parseGenericParams(generics: var NimNode; params: NimNode): NimNode {. + ...raises: [], tags: [], forbids: [].}
proc parseSignature(generics: var NimNode; signature: NimNode; + deftype = ident"untyped"): tuple[name: NimNode, + params: seq[NimNode]] {....raises: [], tags: [], forbids: [].}
proc parseSignatureNoGenerics(signature: NimNode; deftype = ident"untyped"): tuple[ + name: NimNode, params: seq[NimNode]] {....raises: [], tags: [], forbids: [].}
proc asyncImpl(defsign, body: NimNode; parser: var PySyntaxProcesser; + procType = nnkProcDef): NimNode
proc defAux(signature, body: NimNode; deftype = ident"untyped"; + parser: var PySyntaxProcesser; procType = nnkTemplateDef; + pragmas = emptyn): NimNode
proc defImpl(signature, body: NimNode; parser: var PySyntaxProcesser; + pragmas = emptyn; deftype = ident"auto"; procType = nnkProcDef): NimNode
proc parseSignatureMayGenerics(parser: var PySyntaxProcesser; + generics: var NimNode; signature: NimNode; + deftype = ident"untyped"): tuple[name: NimNode, + params: seq[NimNode]]
Implement NOTE: We cannot define a macro or function called raise, as in Nim, raise, a keyword, will be parsed as part of nnkRaiseStmt.
+proc rewriteRaise(rStmt: NimNode): NimNode {....raises: [], tags: [], forbids: [].}
assume rStmt is nnkRaiseStmt
+ + Source +Edit + ++
In Python using global/nonlocal to declare a new variable is allowed, but here it may be impossible to implement, as Nim is statically-typed, we must know its type when declaring a variable, while getting a type from AST whose type is untyped is almostly impossible.
+ +proc parsePyBody(mparser; body: NimNode): NimNode {....raises: [Exception], + tags: [RootEffect], forbids: [].}
proc parsePyBodyWithDoc(mparser; body: NimNode): NimNode {....raises: [Exception], + tags: [RootEffect], forbids: [].}
proc parsePyBodyWithDoc(mparser; body: NimNode; docNode: var NimNode): NimNode {. + ...raises: [Exception], tags: [RootEffect], forbids: [].}
proc parsePyExpr(mparser; exp: NimNode): NimNode {....raises: [Exception], + tags: [RootEffect], forbids: [].}
proc parsePyStmt(mparser; statement: NimNode): NimNode {....raises: [Exception], + tags: [RootEffect], forbids: [].}
Rewrites statement from Python-favor to Nim
+statement shall not be nnkStmtList
+ + Source +Edit + +template parsePyBody(body: NimNode): NimNode
PySyntaxProcesser = concept var self + parsePyBodyWithDoc(self, NimNode) is NimNode + parsePyBodyWithDoc(self, NimNode, var NimNode) is NimNode + parsePyExpr(self, NimNode) is NimNode + self.supportGenerics is bool + self.dedentDoc is bool
proc unpackImpl(data: NimNode; symbols: NimNode): NimNode {....raises: [], + tags: [], forbids: [].}
proc unpackWithLenImpl(data: NimNode; len2unpack: Positive): NimNode {. + ...raises: [], tags: [], forbids: [].}
template unpackImplRec(data: NimNode; symbols: NimNode; res: var NimNode; + receiver) {.dirty.}
macro tonim(body): untyped
Example:
+var GLOBAL = 1 +tonim: + (a, b) = (1, 2) # NOTE these parentheses cannot omitted, unlike Python + assert (a, b) == (1, 2) + (_, a) = (1, 2) + assert a == 2 + (b, *_, a) = [1,2,3] + assert a == 3 + # see doc of unpack in ./stmt/unpack.nim for details + + num = 8 + global GLOBAL + GLOBAL = 3 + doAssertRaises ValueError: raise ValueError + doAssertRaises ValueError: raise ValueError() + doAssertRaises ValueError: raise ValueError("msg") + doAssertRaises ValueError: + # Nim-favor is remained. + raise newException(ValueError,"msg") +assert GLOBAL == 3+ Source +Edit + +
macro unpack(data: untyped; values: varargs[untyped]): untyped
Example:
+# Simple unpacking - you need to provide the length to unpack +let (a, b, c) = @[1, 2, 3, 4].unpack(3) +doAssert (a + b + c) == 6 + +# When unpacking with length you get a tuple so you can assign it +# to something like let (a, b, ...) = x later +doAssert @[1, 2, 3, 5].unpack(2) == (1, 2) + +# You can call unpack with variable names so you don't have to provide +# the length to unpack +# You can also optionally use `_` for values you don't want to get +@[1, 2, 3, 5, 6].unpack(g, x, _, _, z) +doAssert (g + x + z) == 9 + +# Finally, this macro supports Python-like star expressions +# for variables: +let data = @[1, 2, 3, 4, 5, 6] +data.unpack(valA, valB, valC, *valY, valG) +doAssert (valA + valB + valC + valG) == 12 +# For star expressions you get sequences +doAssert valY == @[4, 5] + +data.unpack(start, *ends) +doAssert start == 1 +doAssert ends == @[2, 3, 4, 5, 6] + +# *_ means "ignore al values until the next variable" +data.unpack(k, r, *_, f) +doAssert k == 1 +doAssert r == 2 +doAssert f == 6 + +# You're not limited to simple expressions, you can call this +# macro with somewhat complex expressions or variables +let values = @[3, 2, 5, 7] +doAssert values.unpack(4) == (3, 2, 5, 7) + +import std/strutils +"how are you".split().unpack(ca, cb, cc) + +doAssert @[ca, cb, cc].join(", ") == "how, are, you"+ Source +Edit + +
str.format
+NOTE: only str in Python has format method, not bytes nor bytearray.
+ + +proc pyformatImplAux(s: string; args: seq[NimNode]; kw: Kw): NimNode {. + ...raises: [ValueError, KeyError], tags: [], forbids: [].}
if -d:pylibUseFormatValue, use formatValue instead of format for formatting.
+Convertion is not supported yet (like !r).
+ + Source +Edit + +func removeprefix[S](a: S; suffix: S): S
func removesuffix[S](a: S; suffix: S): S
func rpartition[S](a: S; sep: S): tuple[before, sep, after: S]
func startsWith[S; Suf: S | tuple](a: S; suffix: Suf; start, end: int): bool
func startsWith[S; Suf: S | tuple](a: S; suffix: Suf; start: int): bool
func startsWith[S; Tup: tuple](a: S; suffix: Tup): bool
template expandtabsImpl[S](a: S; tabsize: int; strByteLen: int; iter): string
template istitleImpl(a, isupper, islower: typed; iter, firstItemGetter)
template startsWith[S](a: char; suffix: S): bool
template startsWith[S](a: S; suffix: char): bool
DefSplitCap = 12
STRINGLIB_MUTABLE = false
func norm_maxsplit(maxsplit: int; str_len, sep_len: int): int {....raises: [], + tags: [], forbids: [].}
template norm_maxsplit(maxsplit: int; str_len): int
template PREPARE_CAP(maxcount): int
proc rsplit_whitespace[S](pystr: S; maxsplit = -1): PyList[S]
proc split_whitespace[S](pystr: S; maxsplit = -1): PyList[S]
iterator split_whitespace[S](pystr: S; maxsplit = -1): S
We cannot just use strutils.splitLines for str.splitlines, even nor for bytes.splitlines, as Python uses Univeral NewLine as sep.
+See https://docs.python.org/3/glossary.html#term-universal-newlines
+For a table of all Universal Newlines, see https://docs.python.org/3/library/stdtypes.html#str.splitlines
+ + +iterator splitlines[S](self: S; keepends = false): S
func translateEscape(pattern: string): string {....raises: [], tags: [], + forbids: [].}
macro translateEscapeWithErr(pattern: string): string
macro templWrapExportSincePy(major, minor: static int; sym: typed)
macro wrapExportSincePy(major, minor: static int; sym: typed)
template exportSincePy(major, minor: int; sym: typed)
to be imported by ./version
+PyReleaseLevelEnum {.pure.} = enum + alpha = 10, beta = 11, gamma = 12, final = 15
PyReleaseLevel = PyReleaseLevelEnum.final
ReleaseLevel = "alpha"