rapydscript-ns 0.9.1 → 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/.agignore +1 -1
  2. package/.github/workflows/ci.yml +38 -38
  3. package/=template.pyj +5 -5
  4. package/CHANGELOG.md +3 -1
  5. package/HACKING.md +103 -103
  6. package/LICENSE +24 -24
  7. package/README.md +1 -1
  8. package/TODO.md +117 -0
  9. package/add-toc-to-readme +2 -2
  10. package/bin/export +75 -75
  11. package/bin/rapydscript +70 -70
  12. package/bin/web-repl-export +102 -102
  13. package/build +2 -2
  14. package/language-service/index.js +7 -7
  15. package/language-service/language-service.d.ts +1 -1
  16. package/package.json +6 -2
  17. package/publish.py +37 -37
  18. package/release/compiler.js +245 -230
  19. package/release/signatures.json +22 -22
  20. package/session.vim +4 -4
  21. package/setup.cfg +2 -2
  22. package/src/compiler.pyj +36 -36
  23. package/src/errors.pyj +30 -30
  24. package/src/lib/aes.pyj +646 -646
  25. package/src/lib/copy.pyj +120 -120
  26. package/src/lib/elementmaker.pyj +83 -83
  27. package/src/lib/encodings.pyj +126 -126
  28. package/src/lib/gettext.pyj +569 -569
  29. package/src/lib/itertools.pyj +580 -580
  30. package/src/lib/math.pyj +193 -193
  31. package/src/lib/operator.pyj +11 -11
  32. package/src/lib/pythonize.pyj +20 -20
  33. package/src/lib/random.pyj +118 -118
  34. package/src/lib/react.pyj +74 -74
  35. package/src/lib/traceback.pyj +63 -63
  36. package/src/lib/uuid.pyj +77 -77
  37. package/src/monaco-language-service/diagnostics.js +2 -2
  38. package/src/monaco-language-service/dts.js +550 -550
  39. package/src/monaco-language-service/index.js +2 -2
  40. package/src/output/comments.pyj +45 -45
  41. package/src/output/exceptions.pyj +201 -201
  42. package/src/output/jsx.pyj +164 -164
  43. package/src/output/loops.pyj +9 -0
  44. package/src/output/treeshake.pyj +182 -182
  45. package/src/output/utils.pyj +72 -72
  46. package/src/string_interpolation.pyj +72 -72
  47. package/src/unicode_aliases.pyj +576 -576
  48. package/src/utils.pyj +192 -192
  49. package/test/_import_one.pyj +37 -37
  50. package/test/_import_two/__init__.pyj +11 -11
  51. package/test/_import_two/level2/deep.pyj +4 -4
  52. package/test/_import_two/other.pyj +6 -6
  53. package/test/_import_two/sub.pyj +13 -13
  54. package/test/aes_vectors.pyj +421 -421
  55. package/test/annotations.pyj +80 -80
  56. package/test/decorators.pyj +77 -77
  57. package/test/docstrings.pyj +39 -39
  58. package/test/elementmaker_test.pyj +45 -45
  59. package/test/functions.pyj +151 -151
  60. package/test/generators.pyj +41 -41
  61. package/test/generic.pyj +370 -370
  62. package/test/imports.pyj +72 -72
  63. package/test/internationalization.pyj +73 -73
  64. package/test/lint.pyj +164 -164
  65. package/test/loops.pyj +85 -85
  66. package/test/numpy.pyj +734 -734
  67. package/test/omit_function_metadata.pyj +20 -20
  68. package/test/repl.pyj +121 -121
  69. package/test/scoped_flags.pyj +76 -76
  70. package/test/unit/index.js +66 -0
  71. package/test/unit/language-service-dts.js +543 -543
  72. package/test/unit/language-service-hover.js +455 -455
  73. package/test/unit/language-service.js +1 -1
  74. package/tools/compiler.d.ts +367 -0
  75. package/tools/completer.js +131 -131
  76. package/tools/gettext.js +185 -185
  77. package/tools/ini.js +65 -65
  78. package/tools/msgfmt.js +187 -187
  79. package/tools/repl.js +223 -223
  80. package/tools/test.js +118 -118
  81. package/tools/utils.js +128 -128
  82. package/tools/web_repl.js +95 -95
  83. package/try +41 -41
  84. package/web-repl/env.js +196 -196
  85. package/web-repl/index.html +163 -163
  86. package/web-repl/prism.css +139 -139
  87. package/web-repl/prism.js +113 -113
  88. package/web-repl/rapydscript.js +224 -224
  89. package/web-repl/sha1.js +25 -25
@@ -1,118 +1,118 @@
1
- ###########################################################
2
- # RapydScript Standard Library
3
- # Author: Alexander Tsepkov
4
- # Copyright 2013 Pyjeon Software LLC
5
- # License: Apache License 2.0
6
- # This library is covered under Apache license, so that
7
- # you can distribute it with your RapydScript applications.
8
- ###########################################################
9
-
10
-
11
- # basic implementation of Python's 'random' library
12
-
13
- # JavaScript's Math.random() does not allow seeding its random generator, to bypass that, this module implements its own
14
- # version that can be seeded. I decided on RC4 algorithm for this.
15
-
16
- # please don't mess with this from the outside
17
-
18
- ρσ_seed_state = {
19
- 'key': [],
20
- 'key_i': 0,
21
- 'key_j': 0
22
- }
23
-
24
- ρσ_get_random_byte = def():
25
- ρσ_seed_state.key_i = (ρσ_seed_state.key_i + 1) % 256
26
- ρσ_seed_state.key_j = (ρσ_seed_state.key_j + ρσ_seed_state.key[ρσ_seed_state.key_i]) % 256
27
- ρσ_seed_state.key[ρσ_seed_state.key_i], ρσ_seed_state.key[ρσ_seed_state.key_j] = \
28
- ρσ_seed_state.key[ρσ_seed_state.key_j], ρσ_seed_state.key[ρσ_seed_state.key_i]
29
- return ρσ_seed_state.key[(ρσ_seed_state.key[ρσ_seed_state.key_i] + \
30
- ρσ_seed_state.key[ρσ_seed_state.key_j]) % 256]
31
-
32
- def seed(x=Date().getTime()):
33
- ρσ_seed_state.key_i = ρσ_seed_state.key_j = 0
34
- if jstype(x) is 'number':
35
- x = x.toString()
36
- elif jstype(x) is not 'string':
37
- raise TypeError("unhashable type: '" + jstype(x) + "'")
38
- for i in range(256):
39
- ρσ_seed_state.key[i] = i
40
- j = 0
41
- for i in range(256):
42
- j = (j + ρσ_seed_state.key[i] + x.charCodeAt(i % x.length)) % 256
43
- ρσ_seed_state.key[i], ρσ_seed_state.key[j] = ρσ_seed_state.key[j], ρσ_seed_state.key[i]
44
- seed()
45
-
46
- def random():
47
- n = 0
48
- m = 1
49
- for i in range(8):
50
- n += ρσ_get_random_byte() * m
51
- m *= 256
52
- return v'n / 0x10000000000000000'
53
-
54
- def randrange():
55
- if arguments.length is 1:
56
- return randbelow(int(arguments[0]))
57
- start = int(arguments[0])
58
- stop = int(arguments[1])
59
- if arguments.length < 3:
60
- step = 1
61
- else:
62
- step = int(arguments[2])
63
- width = stop - start
64
- if step is 1:
65
- if width > 0:
66
- return start + randbelow(width)
67
- raise ValueError("empty range for randrange()")
68
- if step > 0:
69
- n = (width + step - 1) // step
70
- elif step < 0:
71
- n = (width + step + 1) // step
72
- else:
73
- raise ValueError("zero step for randrange()")
74
- if n <= 0:
75
- raise ValueError(f"empty range in randrange({start}, {stop}, {step})")
76
- return start + step * randbelow(n)
77
-
78
-
79
- def randint(a, b):
80
- return int(random()*(b-a+1) + a)
81
-
82
- def uniform(a, b):
83
- return random()*(b-a) + a
84
-
85
- def randbelow(n):
86
- return Math.floor(random()*n)
87
-
88
- def choice(seq):
89
- if seq.length > 0:
90
- return seq[randbelow(seq.length)]
91
- else:
92
- raise IndexError()
93
-
94
- # uses Fisher-Yates algorithm to shuffle an array
95
- def shuffle(x, random_f=random):
96
- for i in range(x.length):
97
- j = Math.floor(random_f() * (i+1))
98
- x[i], x[j] = x[j], x[i]
99
- return x
100
-
101
- # similar to shuffle, but only shuffles a subset and creates a copy
102
- def sample(population, k):
103
- x = population.slice()
104
- for i in range(population.length-1, population.length-k-1, -1):
105
- j = Math.floor(random() * (i+1))
106
- x[i], x[j] = x[j], x[i]
107
- return x.slice(population.length-k)
108
-
109
-
110
- #import stdlib
111
- #a = range(50)
112
- #random.seed(5)
113
- #print(random.choice(a))
114
- #print(random.shuffle(a))
115
- #print(random.randrange(10))
116
- #print(random.randint(1,5))
117
- #print(random.uniform(1,5))
118
- #print(random.sample(range(20),5))
1
+ ###########################################################
2
+ # RapydScript Standard Library
3
+ # Author: Alexander Tsepkov
4
+ # Copyright 2013 Pyjeon Software LLC
5
+ # License: Apache License 2.0
6
+ # This library is covered under Apache license, so that
7
+ # you can distribute it with your RapydScript applications.
8
+ ###########################################################
9
+
10
+
11
+ # basic implementation of Python's 'random' library
12
+
13
+ # JavaScript's Math.random() does not allow seeding its random generator, to bypass that, this module implements its own
14
+ # version that can be seeded. I decided on RC4 algorithm for this.
15
+
16
+ # please don't mess with this from the outside
17
+
18
+ ρσ_seed_state = {
19
+ 'key': [],
20
+ 'key_i': 0,
21
+ 'key_j': 0
22
+ }
23
+
24
+ ρσ_get_random_byte = def():
25
+ ρσ_seed_state.key_i = (ρσ_seed_state.key_i + 1) % 256
26
+ ρσ_seed_state.key_j = (ρσ_seed_state.key_j + ρσ_seed_state.key[ρσ_seed_state.key_i]) % 256
27
+ ρσ_seed_state.key[ρσ_seed_state.key_i], ρσ_seed_state.key[ρσ_seed_state.key_j] = \
28
+ ρσ_seed_state.key[ρσ_seed_state.key_j], ρσ_seed_state.key[ρσ_seed_state.key_i]
29
+ return ρσ_seed_state.key[(ρσ_seed_state.key[ρσ_seed_state.key_i] + \
30
+ ρσ_seed_state.key[ρσ_seed_state.key_j]) % 256]
31
+
32
+ def seed(x=Date().getTime()):
33
+ ρσ_seed_state.key_i = ρσ_seed_state.key_j = 0
34
+ if jstype(x) is 'number':
35
+ x = x.toString()
36
+ elif jstype(x) is not 'string':
37
+ raise TypeError("unhashable type: '" + jstype(x) + "'")
38
+ for i in range(256):
39
+ ρσ_seed_state.key[i] = i
40
+ j = 0
41
+ for i in range(256):
42
+ j = (j + ρσ_seed_state.key[i] + x.charCodeAt(i % x.length)) % 256
43
+ ρσ_seed_state.key[i], ρσ_seed_state.key[j] = ρσ_seed_state.key[j], ρσ_seed_state.key[i]
44
+ seed()
45
+
46
+ def random():
47
+ n = 0
48
+ m = 1
49
+ for i in range(8):
50
+ n += ρσ_get_random_byte() * m
51
+ m *= 256
52
+ return v'n / 0x10000000000000000'
53
+
54
+ def randrange():
55
+ if arguments.length is 1:
56
+ return randbelow(int(arguments[0]))
57
+ start = int(arguments[0])
58
+ stop = int(arguments[1])
59
+ if arguments.length < 3:
60
+ step = 1
61
+ else:
62
+ step = int(arguments[2])
63
+ width = stop - start
64
+ if step is 1:
65
+ if width > 0:
66
+ return start + randbelow(width)
67
+ raise ValueError("empty range for randrange()")
68
+ if step > 0:
69
+ n = (width + step - 1) // step
70
+ elif step < 0:
71
+ n = (width + step + 1) // step
72
+ else:
73
+ raise ValueError("zero step for randrange()")
74
+ if n <= 0:
75
+ raise ValueError(f"empty range in randrange({start}, {stop}, {step})")
76
+ return start + step * randbelow(n)
77
+
78
+
79
+ def randint(a, b):
80
+ return int(random()*(b-a+1) + a)
81
+
82
+ def uniform(a, b):
83
+ return random()*(b-a) + a
84
+
85
+ def randbelow(n):
86
+ return Math.floor(random()*n)
87
+
88
+ def choice(seq):
89
+ if seq.length > 0:
90
+ return seq[randbelow(seq.length)]
91
+ else:
92
+ raise IndexError()
93
+
94
+ # uses Fisher-Yates algorithm to shuffle an array
95
+ def shuffle(x, random_f=random):
96
+ for i in range(x.length):
97
+ j = Math.floor(random_f() * (i+1))
98
+ x[i], x[j] = x[j], x[i]
99
+ return x
100
+
101
+ # similar to shuffle, but only shuffles a subset and creates a copy
102
+ def sample(population, k):
103
+ x = population.slice()
104
+ for i in range(population.length-1, population.length-k-1, -1):
105
+ j = Math.floor(random() * (i+1))
106
+ x[i], x[j] = x[j], x[i]
107
+ return x.slice(population.length-k)
108
+
109
+
110
+ #import stdlib
111
+ #a = range(50)
112
+ #random.seed(5)
113
+ #print(random.choice(a))
114
+ #print(random.shuffle(a))
115
+ #print(random.randrange(10))
116
+ #print(random.randint(1,5))
117
+ #print(random.uniform(1,5))
118
+ #print(random.sample(range(20),5))
package/src/lib/react.pyj CHANGED
@@ -1,74 +1,74 @@
1
- # vim:fileencoding=utf-8
2
- # License: BSD
3
- # RapydScript bindings for React.
4
- #
5
- # Supported: all standard hooks (useState, useEffect, useContext, useReducer,
6
- # useCallback, useMemo, useRef, useImperativeHandle, useLayoutEffect,
7
- # useDebugValue, useId, useTransition, useDeferredValue), core classes
8
- # (Component, PureComponent), special elements (Fragment, StrictMode,
9
- # Suspense, Profiler), and utilities (createElement, cloneElement,
10
- # createContext, createRef, forwardRef, isValidElement, memo, lazy).
11
- #
12
- # Requires React to be available as a global variable. Load it via a CDN
13
- # <script> tag, a bundler global shim, or any other mechanism before your
14
- # compiled script runs.
15
- #
16
- # Usage:
17
- # from __python__ import jsx
18
- # from react import useState, useEffect, useRef
19
- #
20
- # def Counter():
21
- # count, setCount = useState(0)
22
- # def handleClick():
23
- # setCount(count + 1)
24
- # return <button onClick={handleClick}>{count}</button>
25
- #
26
- # For class components extend React.Component directly (no import needed):
27
- #
28
- # class MyComponent(React.Component):
29
- # def render(self):
30
- # return <div>{self.props.title}</div>
31
-
32
- # ── Hooks (React 16.8+) ───────────────────────────────────────────────────────
33
-
34
- useState = React.useState
35
- useEffect = React.useEffect
36
- useContext = React.useContext
37
- useReducer = React.useReducer
38
- useCallback = React.useCallback
39
- useMemo = React.useMemo
40
- useRef = React.useRef
41
- useImperativeHandle = React.useImperativeHandle
42
- useLayoutEffect = React.useLayoutEffect
43
- useDebugValue = React.useDebugValue
44
-
45
- # ── Hooks (React 18+) ────────────────────────────────────────────────────────
46
-
47
- useId = React.useId
48
- useTransition = React.useTransition
49
- useDeferredValue = React.useDeferredValue
50
- useSyncExternalStore = React.useSyncExternalStore
51
- useInsertionEffect = React.useInsertionEffect
52
-
53
- # ── Core classes ─────────────────────────────────────────────────────────────
54
-
55
- Component = React.Component
56
- PureComponent = React.PureComponent
57
-
58
- # ── Special elements ─────────────────────────────────────────────────────────
59
-
60
- Fragment = React.Fragment
61
- StrictMode = React.StrictMode
62
- Suspense = React.Suspense
63
- Profiler = React.Profiler
64
-
65
- # ── Utilities ────────────────────────────────────────────────────────────────
66
-
67
- createElement = React.createElement
68
- cloneElement = React.cloneElement
69
- createContext = React.createContext
70
- createRef = React.createRef
71
- forwardRef = React.forwardRef
72
- isValidElement = React.isValidElement
73
- memo = React.memo
74
- lazy = React.lazy
1
+ # vim:fileencoding=utf-8
2
+ # License: BSD
3
+ # RapydScript bindings for React.
4
+ #
5
+ # Supported: all standard hooks (useState, useEffect, useContext, useReducer,
6
+ # useCallback, useMemo, useRef, useImperativeHandle, useLayoutEffect,
7
+ # useDebugValue, useId, useTransition, useDeferredValue), core classes
8
+ # (Component, PureComponent), special elements (Fragment, StrictMode,
9
+ # Suspense, Profiler), and utilities (createElement, cloneElement,
10
+ # createContext, createRef, forwardRef, isValidElement, memo, lazy).
11
+ #
12
+ # Requires React to be available as a global variable. Load it via a CDN
13
+ # <script> tag, a bundler global shim, or any other mechanism before your
14
+ # compiled script runs.
15
+ #
16
+ # Usage:
17
+ # from __python__ import jsx
18
+ # from react import useState, useEffect, useRef
19
+ #
20
+ # def Counter():
21
+ # count, setCount = useState(0)
22
+ # def handleClick():
23
+ # setCount(count + 1)
24
+ # return <button onClick={handleClick}>{count}</button>
25
+ #
26
+ # For class components extend React.Component directly (no import needed):
27
+ #
28
+ # class MyComponent(React.Component):
29
+ # def render(self):
30
+ # return <div>{self.props.title}</div>
31
+
32
+ # ── Hooks (React 16.8+) ───────────────────────────────────────────────────────
33
+
34
+ useState = React.useState
35
+ useEffect = React.useEffect
36
+ useContext = React.useContext
37
+ useReducer = React.useReducer
38
+ useCallback = React.useCallback
39
+ useMemo = React.useMemo
40
+ useRef = React.useRef
41
+ useImperativeHandle = React.useImperativeHandle
42
+ useLayoutEffect = React.useLayoutEffect
43
+ useDebugValue = React.useDebugValue
44
+
45
+ # ── Hooks (React 18+) ────────────────────────────────────────────────────────
46
+
47
+ useId = React.useId
48
+ useTransition = React.useTransition
49
+ useDeferredValue = React.useDeferredValue
50
+ useSyncExternalStore = React.useSyncExternalStore
51
+ useInsertionEffect = React.useInsertionEffect
52
+
53
+ # ── Core classes ─────────────────────────────────────────────────────────────
54
+
55
+ Component = React.Component
56
+ PureComponent = React.PureComponent
57
+
58
+ # ── Special elements ─────────────────────────────────────────────────────────
59
+
60
+ Fragment = React.Fragment
61
+ StrictMode = React.StrictMode
62
+ Suspense = React.Suspense
63
+ Profiler = React.Profiler
64
+
65
+ # ── Utilities ────────────────────────────────────────────────────────────────
66
+
67
+ createElement = React.createElement
68
+ cloneElement = React.cloneElement
69
+ createContext = React.createContext
70
+ createRef = React.createRef
71
+ forwardRef = React.forwardRef
72
+ isValidElement = React.isValidElement
73
+ memo = React.memo
74
+ lazy = React.lazy
@@ -1,63 +1,63 @@
1
- # vim:fileencoding=utf-8
2
- # License: BSD Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
3
- # globals: ρσ_str, ρσ_last_exception
4
-
5
-
6
- def _get_internal_traceback(err):
7
- if isinstance(err, Exception) and err.stack:
8
- lines = ρσ_str.splitlines(err.stack)
9
- final_lines = v'[]'
10
- found_sentinel = False
11
- for i, line in enumerate(lines):
12
- sline = ρσ_str.strip(line)
13
- if i is 0:
14
- final_lines.push(line)
15
- continue
16
- if found_sentinel:
17
- final_lines.push(line)
18
- continue
19
- # These two conditions work on desktop Chrome and Firefox to identify the correct
20
- # line in the traceback.
21
- if sline.startsWith('at new ' + err.name) or sline.startsWith(err.name + '@'):
22
- found_sentinel = True
23
- return final_lines.join('\n')
24
- return err and err.stack
25
-
26
- def format_exception(exc, limit):
27
- if jstype(exc) is 'undefined':
28
- exc = ρσ_last_exception
29
- if not isinstance(exc, Error):
30
- if exc and exc.toString:
31
- return [exc.toString()]
32
- return []
33
- tb = _get_internal_traceback(exc)
34
- if tb:
35
- lines = ρσ_str.splitlines(tb)
36
- e = lines[0]
37
- lines = lines[1:]
38
- if limit:
39
- lines = lines[:limit+1] if limit > 0 else lines[limit:]
40
- lines.reverse()
41
- lines.push(e)
42
- lines.insert(0, 'Traceback (most recent call last):')
43
- return [l+'\n' for l in lines]
44
- return [exc.toString()]
45
-
46
- def format_exc(limit):
47
- return format_exception(ρσ_last_exception, limit).join('')
48
-
49
- def print_exc(limit):
50
- print(format_exc(limit))
51
-
52
- def format_stack(limit):
53
- stack = Error().stack
54
- if not stack:
55
- return []
56
- lines = str.splitlines(stack)[2:]
57
- lines.reverse()
58
- if limit:
59
- lines = lines[:limit+1] if limit > 0 else lines[limit:]
60
- return [l + '\n' for l in lines]
61
-
62
- def print_stack(limit):
63
- print(format_stack(limit).join(''))
1
+ # vim:fileencoding=utf-8
2
+ # License: BSD Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
3
+ # globals: ρσ_str, ρσ_last_exception
4
+
5
+
6
+ def _get_internal_traceback(err):
7
+ if isinstance(err, Exception) and err.stack:
8
+ lines = ρσ_str.splitlines(err.stack)
9
+ final_lines = v'[]'
10
+ found_sentinel = False
11
+ for i, line in enumerate(lines):
12
+ sline = ρσ_str.strip(line)
13
+ if i is 0:
14
+ final_lines.push(line)
15
+ continue
16
+ if found_sentinel:
17
+ final_lines.push(line)
18
+ continue
19
+ # These two conditions work on desktop Chrome and Firefox to identify the correct
20
+ # line in the traceback.
21
+ if sline.startsWith('at new ' + err.name) or sline.startsWith(err.name + '@'):
22
+ found_sentinel = True
23
+ return final_lines.join('\n')
24
+ return err and err.stack
25
+
26
+ def format_exception(exc, limit):
27
+ if jstype(exc) is 'undefined':
28
+ exc = ρσ_last_exception
29
+ if not isinstance(exc, Error):
30
+ if exc and exc.toString:
31
+ return [exc.toString()]
32
+ return []
33
+ tb = _get_internal_traceback(exc)
34
+ if tb:
35
+ lines = ρσ_str.splitlines(tb)
36
+ e = lines[0]
37
+ lines = lines[1:]
38
+ if limit:
39
+ lines = lines[:limit+1] if limit > 0 else lines[limit:]
40
+ lines.reverse()
41
+ lines.push(e)
42
+ lines.insert(0, 'Traceback (most recent call last):')
43
+ return [l+'\n' for l in lines]
44
+ return [exc.toString()]
45
+
46
+ def format_exc(limit):
47
+ return format_exception(ρσ_last_exception, limit).join('')
48
+
49
+ def print_exc(limit):
50
+ print(format_exc(limit))
51
+
52
+ def format_stack(limit):
53
+ stack = Error().stack
54
+ if not stack:
55
+ return []
56
+ lines = str.splitlines(stack)[2:]
57
+ lines.reverse()
58
+ if limit:
59
+ lines = lines[:limit+1] if limit > 0 else lines[limit:]
60
+ return [l + '\n' for l in lines]
61
+
62
+ def print_stack(limit):
63
+ print(format_stack(limit).join(''))
package/src/lib/uuid.pyj CHANGED
@@ -1,77 +1,77 @@
1
- # vim:fileencoding=utf-8
2
- # License: BSD Copyright: 2017, Kovid Goyal <kovid at kovidgoyal.net>
3
- # globals: crypto
4
- from __python__ import hash_literals
5
-
6
- from encodings import hexlify, urlsafe_b64decode, urlsafe_b64encode
7
-
8
- RFC_4122 = 1
9
-
10
- if jstype(crypto) is 'object' and crypto.getRandomValues:
11
- random_bytes = def (num):
12
- ans = Uint8Array(num or 16)
13
- crypto.getRandomValues(ans)
14
- return ans
15
- else:
16
- random_bytes = def (num):
17
- ans = Uint8Array(num or 16)
18
- for i in range(ans.length):
19
- ans[i] = Math.floor(Math.random() * 256)
20
- return ans
21
-
22
-
23
- def uuid4_bytes():
24
- data = random_bytes()
25
- data[6] = 0b01000000 | (data[6] & 0b1111)
26
- data[8] = (((data[8] >> 4) & 0b11 | 0b1000) << 4) | (data[8] & 0b1111)
27
- return data
28
-
29
-
30
- def as_str():
31
- h = this.hex
32
- return h[:8] + '-' + h[8:12] + '-' + h[12:16] + '-' + h[16:20] + '-' + h[20:]
33
-
34
-
35
- def uuid4():
36
- b = uuid4_bytes()
37
- return {
38
- 'hex': hexlify(b),
39
- 'bytes': b,
40
- 'variant': RFC_4122,
41
- 'version': 4,
42
- '__str__': as_str,
43
- 'toString': as_str,
44
- }
45
-
46
-
47
- def num_to_string(numbers, alphabet, pad_to_length):
48
- ans = v'[]'
49
- alphabet_len = alphabet.length
50
- numbers = Array.prototype.slice.call(numbers)
51
- for v'var i = 0; i < numbers.length - 1; i++':
52
- x = divmod(numbers[i], alphabet_len)
53
- numbers[i] = x[0]
54
- numbers[i+1] += x[1]
55
- for v'var i = 0; i < numbers.length; i++':
56
- number = numbers[i]
57
- while number:
58
- x = divmod(number, alphabet_len)
59
- number = x[0]
60
- ans.push(alphabet[x[1]])
61
- if pad_to_length and pad_to_length > ans.length:
62
- ans.push(alphabet[0].repeat(pad_to_length - ans.length))
63
- return ans.join('')
64
-
65
-
66
- def short_uuid():
67
- # A totally random uuid encoded using only URL and filename safe characters
68
- return urlsafe_b64encode(random_bytes(), '')
69
-
70
-
71
- def short_uuid4():
72
- # A uuid4 encoded using only URL and filename safe characters
73
- return urlsafe_b64encode(uuid4_bytes(), '')
74
-
75
-
76
- def decode_short_uuid(val):
77
- return urlsafe_b64decode(val + '==')
1
+ # vim:fileencoding=utf-8
2
+ # License: BSD Copyright: 2017, Kovid Goyal <kovid at kovidgoyal.net>
3
+ # globals: crypto
4
+ from __python__ import hash_literals
5
+
6
+ from encodings import hexlify, urlsafe_b64decode, urlsafe_b64encode
7
+
8
+ RFC_4122 = 1
9
+
10
+ if jstype(crypto) is 'object' and crypto.getRandomValues:
11
+ random_bytes = def (num):
12
+ ans = Uint8Array(num or 16)
13
+ crypto.getRandomValues(ans)
14
+ return ans
15
+ else:
16
+ random_bytes = def (num):
17
+ ans = Uint8Array(num or 16)
18
+ for i in range(ans.length):
19
+ ans[i] = Math.floor(Math.random() * 256)
20
+ return ans
21
+
22
+
23
+ def uuid4_bytes():
24
+ data = random_bytes()
25
+ data[6] = 0b01000000 | (data[6] & 0b1111)
26
+ data[8] = (((data[8] >> 4) & 0b11 | 0b1000) << 4) | (data[8] & 0b1111)
27
+ return data
28
+
29
+
30
+ def as_str():
31
+ h = this.hex
32
+ return h[:8] + '-' + h[8:12] + '-' + h[12:16] + '-' + h[16:20] + '-' + h[20:]
33
+
34
+
35
+ def uuid4():
36
+ b = uuid4_bytes()
37
+ return {
38
+ 'hex': hexlify(b),
39
+ 'bytes': b,
40
+ 'variant': RFC_4122,
41
+ 'version': 4,
42
+ '__str__': as_str,
43
+ 'toString': as_str,
44
+ }
45
+
46
+
47
+ def num_to_string(numbers, alphabet, pad_to_length):
48
+ ans = v'[]'
49
+ alphabet_len = alphabet.length
50
+ numbers = Array.prototype.slice.call(numbers)
51
+ for v'var i = 0; i < numbers.length - 1; i++':
52
+ x = divmod(numbers[i], alphabet_len)
53
+ numbers[i] = x[0]
54
+ numbers[i+1] += x[1]
55
+ for v'var i = 0; i < numbers.length; i++':
56
+ number = numbers[i]
57
+ while number:
58
+ x = divmod(number, alphabet_len)
59
+ number = x[0]
60
+ ans.push(alphabet[x[1]])
61
+ if pad_to_length and pad_to_length > ans.length:
62
+ ans.push(alphabet[0].repeat(pad_to_length - ans.length))
63
+ return ans.join('')
64
+
65
+
66
+ def short_uuid():
67
+ # A totally random uuid encoded using only URL and filename safe characters
68
+ return urlsafe_b64encode(random_bytes(), '')
69
+
70
+
71
+ def short_uuid4():
72
+ # A uuid4 encoded using only URL and filename safe characters
73
+ return urlsafe_b64encode(uuid4_bytes(), '')
74
+
75
+
76
+ def decode_short_uuid(val):
77
+ return urlsafe_b64decode(val + '==')