lispython 0.4.2__tar.gz → 0.4.5__tar.gz
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.
- {lispython-0.4.2 → lispython-0.4.5}/PKG-INFO +2 -1
- {lispython-0.4.2 → lispython-0.4.5}/pyproject.toml +5 -2
- {lispython-0.4.2 → lispython-0.4.5}/src/lispy/core/builtins.py +11 -1
- {lispython-0.4.2 → lispython-0.4.5}/src/lispy/core/macro.py +19 -1
- {lispython-0.4.2 → lispython-0.4.5}/src/lispy/core/nodes.py +5 -1
- {lispython-0.4.2 → lispython-0.4.5}/src/lispy/macros/sugar.lpy +4 -3
- {lispython-0.4.2 → lispython-0.4.5}/src/lispy/tools.lpy +67 -6
- lispython-0.4.5/tests/test_as_thread.py +49 -0
- lispython-0.4.5/tests/test_literal_unwrap.py +73 -0
- {lispython-0.4.2 → lispython-0.4.5}/uv.lock +24 -1
- lispython-0.4.2/tests/test_as_thread.py +0 -36
- {lispython-0.4.2 → lispython-0.4.5}/.claude/settings.local.json +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/.gitignore +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/.pre-commit-config.yaml +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/.vscode/settings.json +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/LICENSE.md +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/README.md +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/docs/index.md +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/docs/macros.md +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/docs/syntax/expressions.md +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/docs/syntax/overview.md +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/docs/syntax/statements.md +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/docs/usage/cli.md +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/docs/usage/getting-started.md +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/docs/version_macro.py +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/docs/why-lispy.md +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/mkdocs.yml +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/src/lispy/__init__.py +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/src/lispy/core/compiler/__init__.py +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/src/lispy/core/compiler/expr.py +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/src/lispy/core/compiler/literal.py +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/src/lispy/core/compiler/stmt.py +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/src/lispy/core/compiler/utils.py +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/src/lispy/core/importer.py +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/src/lispy/core/meta_functions.py +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/src/lispy/core/parser.py +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/src/lispy/core/utils.py +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/src/lispy/core_meta_functions.lpy +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/src/lispy/lsp/__init__.py +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/src/lispy/lsp/__main__.py +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/src/lispy/lsp/server.lpy +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/src/lispy/macros/__init__.py +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/src/lispy/macros/init.lpy +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/tests/__init__.py +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/tests/test_expr.py +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/tests/test_gensym.py +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/tests/test_include_meta.py +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/tests/test_literal.py +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/tests/test_meta_functions.py +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/tests/test_parser.py +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/tests/test_stmt.py +0 -0
- {lispython-0.4.2 → lispython-0.4.5}/tests/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lispython
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.5
|
|
4
4
|
Summary: Lisp-like Syntax for Python with Lisp-like Macros
|
|
5
5
|
Project-URL: Homepage, https://jetack.github.io/lispython
|
|
6
6
|
Project-URL: Repository, https://github.com/jetack/lispython
|
|
@@ -8,6 +8,7 @@ Author-email: Jetack <jetack23@gmail.com>
|
|
|
8
8
|
License: MIT
|
|
9
9
|
License-File: LICENSE.md
|
|
10
10
|
Requires-Python: >=3.11
|
|
11
|
+
Requires-Dist: prompt-toolkit>=3.0.52
|
|
11
12
|
Requires-Dist: pygls>=1.0.0
|
|
12
13
|
Provides-Extra: dev
|
|
13
14
|
Requires-Dist: pre-commit>=3.6.0; extra == 'dev'
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "lispython"
|
|
3
|
-
version = "0.4.
|
|
3
|
+
version = "0.4.5"
|
|
4
4
|
description = "Lisp-like Syntax for Python with Lisp-like Macros"
|
|
5
5
|
authors = [{ name = "Jetack", email = "jetack23@gmail.com" }]
|
|
6
6
|
license = { text = "MIT" }
|
|
7
7
|
readme = "README.md"
|
|
8
8
|
requires-python = ">=3.11"
|
|
9
|
-
dependencies = [
|
|
9
|
+
dependencies = [
|
|
10
|
+
"prompt-toolkit>=3.0.52",
|
|
11
|
+
"pygls>=1.0.0",
|
|
12
|
+
]
|
|
10
13
|
|
|
11
14
|
[project.urls]
|
|
12
15
|
Homepage = "https://jetack.github.io/lispython"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from lispy.core.nodes import Symbol
|
|
1
|
+
from lispy.core.nodes import Expression, Symbol, Wrapper
|
|
2
2
|
|
|
3
3
|
_gensym_counter = 0
|
|
4
4
|
|
|
@@ -17,3 +17,13 @@ def gensym(prefix="gensym"):
|
|
|
17
17
|
def reset_gensym_counter():
|
|
18
18
|
global _gensym_counter
|
|
19
19
|
_gensym_counter = 0
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def replace_symbol(node, old, new):
|
|
23
|
+
if isinstance(node, Symbol) and node.value == old.value:
|
|
24
|
+
return new
|
|
25
|
+
if isinstance(node, Expression):
|
|
26
|
+
node.list = [replace_symbol(child, old, new) for child in node.list]
|
|
27
|
+
elif isinstance(node, Wrapper):
|
|
28
|
+
node.value = replace_symbol(node.value, old, new)
|
|
29
|
+
return node
|
|
@@ -8,6 +8,22 @@ from lispy.core.nodes import *
|
|
|
8
8
|
|
|
9
9
|
__macro_namespace: Dict[str, Callable[[Node], ast.AST]] = {}
|
|
10
10
|
|
|
11
|
+
_ast_literal_eval = __import__("ast").literal_eval
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _unwrap_literal(node):
|
|
15
|
+
if isinstance(node, Constant):
|
|
16
|
+
try:
|
|
17
|
+
return _ast_literal_eval(node.value)
|
|
18
|
+
except (ValueError, SyntaxError):
|
|
19
|
+
return node
|
|
20
|
+
elif isinstance(node, String):
|
|
21
|
+
try:
|
|
22
|
+
return _ast_literal_eval(node.value)
|
|
23
|
+
except (ValueError, SyntaxError):
|
|
24
|
+
return node
|
|
25
|
+
return node
|
|
26
|
+
|
|
11
27
|
|
|
12
28
|
def define_macro(sexp, scope, include_meta=True):
|
|
13
29
|
transformed = defmacro_transform(sexp)
|
|
@@ -69,7 +85,9 @@ def macroexpand_1_and_check(sexp, scope=globals(), in_quasi=False, include_meta=
|
|
|
69
85
|
elif str(op) == "require" and not in_quasi:
|
|
70
86
|
sexp = require_macro(sexp, scope, include_meta=include_meta)
|
|
71
87
|
elif str(op) in scope.setdefault("__macro_namespace", {}) and not in_quasi and isinstance(sexp, Paren):
|
|
72
|
-
sexp = scope["__macro_namespace"][str(op)](*operands)
|
|
88
|
+
sexp = scope["__macro_namespace"][str(op)](*[_unwrap_literal(o) for o in operands])
|
|
89
|
+
if not isinstance(sexp, Node):
|
|
90
|
+
sexp = data_to_generator_expression(sexp)
|
|
73
91
|
expanded = True
|
|
74
92
|
else:
|
|
75
93
|
expanded_list, expanded_feedbacks = zip(
|
|
@@ -44,7 +44,11 @@ class Node:
|
|
|
44
44
|
|
|
45
45
|
|
|
46
46
|
def data_to_generator_expression(data):
|
|
47
|
-
if isinstance(data,
|
|
47
|
+
if isinstance(data, bool) or data is None:
|
|
48
|
+
return Constant(str(data))
|
|
49
|
+
elif isinstance(data, (int, float, complex)):
|
|
50
|
+
return Constant(str(data))
|
|
51
|
+
elif isinstance(data, str):
|
|
48
52
|
return String('"' + data + '"')
|
|
49
53
|
elif isinstance(data, list):
|
|
50
54
|
return Bracket(*data)
|
|
@@ -31,11 +31,12 @@
|
|
|
31
31
|
(defmacro as-> [expr name *forms]
|
|
32
32
|
(if (== 0 (len forms))
|
|
33
33
|
(return expr))
|
|
34
|
+
(= sym (gensym (str name)))
|
|
34
35
|
(= stmts [])
|
|
35
|
-
(stmts.append `(= ~
|
|
36
|
+
(stmts.append `(= ~sym ~expr))
|
|
36
37
|
(for f in forms
|
|
37
|
-
(stmts.append `(= ~
|
|
38
|
-
(stmts.append
|
|
38
|
+
(stmts.append `(= ~sym ~(replace-symbol f name sym))))
|
|
39
|
+
(stmts.append sym)
|
|
39
40
|
(return `(do ~@stmts)))
|
|
40
41
|
|
|
41
42
|
(defmacro fn [*body]
|
|
@@ -136,10 +136,69 @@
|
|
|
136
136
|
(= file (osp.join (os.getcwd) (sub more-args 0)))
|
|
137
137
|
(print (l2py-f file :include-meta args.include_meta :no-lispy args.no_lispy)))
|
|
138
138
|
|
|
139
|
-
(def
|
|
139
|
+
(def _make-open-handler [o c]
|
|
140
|
+
(def handler [event]
|
|
141
|
+
(= buf event.app.current-buffer)
|
|
142
|
+
(buf.insert-text (+ o c))
|
|
143
|
+
(buf.cursor-left))
|
|
144
|
+
(return handler))
|
|
145
|
+
|
|
146
|
+
(def _make-close-handler [c]
|
|
147
|
+
(def handler [event]
|
|
148
|
+
(= buf event.app.current-buffer)
|
|
149
|
+
(if (== buf.document.current-char c)
|
|
150
|
+
(buf.cursor-right)
|
|
151
|
+
(buf.insert-text c)))
|
|
152
|
+
(return handler))
|
|
153
|
+
|
|
154
|
+
(def _make-quote-handler [q]
|
|
155
|
+
(def handler [event]
|
|
156
|
+
(= buf event.app.current-buffer)
|
|
157
|
+
(if (== buf.document.current-char q)
|
|
158
|
+
(buf.cursor-right)
|
|
159
|
+
(do
|
|
160
|
+
(buf.insert-text (+ q q))
|
|
161
|
+
(buf.cursor-left))))
|
|
162
|
+
(return handler))
|
|
163
|
+
|
|
164
|
+
(def make-repl-session []
|
|
165
|
+
(from prompt-toolkit [PromptSession])
|
|
166
|
+
(from prompt-toolkit.history [FileHistory])
|
|
167
|
+
(from prompt-toolkit.key-binding [KeyBindings])
|
|
168
|
+
(from prompt-toolkit.keys [Keys])
|
|
169
|
+
|
|
170
|
+
(= kb (KeyBindings))
|
|
171
|
+
(= _pairs {"(" ")" "[" "]" "{" "}" "'" "'" "\"" "\""})
|
|
172
|
+
|
|
173
|
+
(for [o c] in (_pairs.items)
|
|
174
|
+
((kb.add o) (_make-open-handler o c)))
|
|
175
|
+
|
|
176
|
+
(for c in (_pairs.values)
|
|
177
|
+
((kb.add c) (_make-close-handler c)))
|
|
178
|
+
|
|
179
|
+
(for q in ["'" "\""]
|
|
180
|
+
((kb.add q) (_make-quote-handler q)))
|
|
181
|
+
|
|
182
|
+
;; Backspace deletes both chars of an empty pair
|
|
183
|
+
(= _bp _pairs)
|
|
184
|
+
(def handle-backspace [event]
|
|
185
|
+
(= buf event.app.current-buffer)
|
|
186
|
+
(= doc buf.document)
|
|
187
|
+
(= before doc.char-before-cursor)
|
|
188
|
+
(= after doc.current-char)
|
|
189
|
+
(if (and (in before _bp) (== (sub _bp before) after))
|
|
190
|
+
(do (buf.delete) (buf.delete-before-cursor))
|
|
191
|
+
(buf.delete-before-cursor)))
|
|
192
|
+
((kb.add Keys.Backspace) handle-backspace)
|
|
193
|
+
|
|
194
|
+
(= histfile (osp.join (osp.expanduser "~") ".lpy_history"))
|
|
195
|
+
(return (PromptSession :history (FileHistory histfile)
|
|
196
|
+
:key-bindings kb)))
|
|
197
|
+
|
|
198
|
+
(def read-multiline-input [session prompt_str]
|
|
140
199
|
(= paren-depth 0)
|
|
141
200
|
(= in-string False)
|
|
142
|
-
(= line (
|
|
201
|
+
(= line (session.prompt prompt_str))
|
|
143
202
|
(= src line)
|
|
144
203
|
(while True
|
|
145
204
|
(for c in line
|
|
@@ -150,15 +209,15 @@
|
|
|
150
209
|
|
|
151
210
|
(== c "\"")
|
|
152
211
|
(= in-string True)
|
|
153
|
-
|
|
212
|
+
|
|
154
213
|
(in c "([{")
|
|
155
214
|
(+= paren-depth 1)
|
|
156
|
-
|
|
215
|
+
|
|
157
216
|
(in c ")]}")
|
|
158
217
|
(-= paren-depth 1)))
|
|
159
218
|
(if (== paren-depth 0)
|
|
160
219
|
(break))
|
|
161
|
-
(= line (
|
|
220
|
+
(= line (session.prompt "... "))
|
|
162
221
|
(+= src (+ "\n" line)))
|
|
163
222
|
(return src))
|
|
164
223
|
|
|
@@ -184,13 +243,15 @@
|
|
|
184
243
|
(= cwd (os.getcwd))
|
|
185
244
|
(if (not (in cwd sys.path))
|
|
186
245
|
(sys.path.insert 0 cwd))
|
|
246
|
+
|
|
247
|
+
(= session (make-repl-session))
|
|
187
248
|
(= scope SCOPE)
|
|
188
249
|
(eval-and-print "(require lispy.macros *)
|
|
189
250
|
(from pprint [pprint])" scope)
|
|
190
251
|
(while True
|
|
191
252
|
(try
|
|
192
253
|
(do
|
|
193
|
-
(= src (read-multiline-input "repl> "))
|
|
254
|
+
(= src (read-multiline-input session "repl> "))
|
|
194
255
|
(eval-and-print src scope translate))
|
|
195
256
|
(except [SystemExit]
|
|
196
257
|
(print "SystemExit caught. Exiting REPL.")
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
from lispy.core.builtins import reset_gensym_counter
|
|
2
|
+
from lispy.tools import src_to_python_org
|
|
3
|
+
|
|
4
|
+
PREAMBLE = "(require lispy.macros *)\n"
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class TestAsThread:
|
|
8
|
+
def setup_method(self):
|
|
9
|
+
reset_gensym_counter()
|
|
10
|
+
|
|
11
|
+
def test_no_forms(self):
|
|
12
|
+
assert src_to_python_org(PREAMBLE + "(as-> 42 x)") == "42"
|
|
13
|
+
|
|
14
|
+
def test_single_form(self):
|
|
15
|
+
result = src_to_python_org(PREAMBLE + "(as-> 0 x (+ x 1))")
|
|
16
|
+
assert "__x_0 = 0" in result
|
|
17
|
+
assert "__x_0 = __x_0 + 1" in result
|
|
18
|
+
|
|
19
|
+
def test_multiple_forms(self):
|
|
20
|
+
result = src_to_python_org(
|
|
21
|
+
PREAMBLE + "(as-> 0 x (+ x 10) (* 2 x) (str x))"
|
|
22
|
+
)
|
|
23
|
+
assert "__x_0 = 0" in result
|
|
24
|
+
assert "__x_0 = __x_0 + 10" in result
|
|
25
|
+
assert "__x_0 = 2 * __x_0" in result
|
|
26
|
+
assert "__x_0 = str(__x_0)" in result
|
|
27
|
+
|
|
28
|
+
def test_method_call(self):
|
|
29
|
+
result = src_to_python_org(
|
|
30
|
+
PREAMBLE + '(as-> "hello" s (.upper s))'
|
|
31
|
+
)
|
|
32
|
+
assert "__s_0 = 'hello'" in result
|
|
33
|
+
assert "__s_0 = __s_0.upper()" in result
|
|
34
|
+
|
|
35
|
+
def test_flexible_placement(self):
|
|
36
|
+
result = src_to_python_org(
|
|
37
|
+
PREAMBLE + "(as-> 1 x (+ 10 x) (- x 5))"
|
|
38
|
+
)
|
|
39
|
+
assert "__x_0 = 10 + __x_0" in result
|
|
40
|
+
assert "__x_0 = __x_0 - 5" in result
|
|
41
|
+
|
|
42
|
+
def test_does_not_shadow_outer_variable(self):
|
|
43
|
+
result = src_to_python_org(
|
|
44
|
+
PREAMBLE + "(= x 100)\n(as-> 0 x (+ x 10))\n(print x)"
|
|
45
|
+
)
|
|
46
|
+
assert "x = 100" in result
|
|
47
|
+
assert "print(x)" in result
|
|
48
|
+
assert "__x_0 = 0" in result
|
|
49
|
+
assert "__x_0 = __x_0 + 10" in result
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
from lispy.tools import src_to_python_org
|
|
2
|
+
|
|
3
|
+
PREAMBLE = "(require lispy.macros *)\n"
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class TestLiteralUnwrapInMacro:
|
|
7
|
+
def test_number_is_int(self):
|
|
8
|
+
src = PREAMBLE + """
|
|
9
|
+
(defmacro repeat-n [n *body]
|
|
10
|
+
(= stmts [])
|
|
11
|
+
(for _ in (range n)
|
|
12
|
+
(stmts.extend body))
|
|
13
|
+
(return `(do ~@stmts)))
|
|
14
|
+
|
|
15
|
+
(repeat-n 3 (print "hello"))
|
|
16
|
+
"""
|
|
17
|
+
result = src_to_python_org(src)
|
|
18
|
+
assert result.count("print('hello')") == 3
|
|
19
|
+
|
|
20
|
+
def test_string_is_str(self):
|
|
21
|
+
src = PREAMBLE + """
|
|
22
|
+
(defmacro greet [name]
|
|
23
|
+
(= upper (.upper name))
|
|
24
|
+
(return `(print ~upper)))
|
|
25
|
+
|
|
26
|
+
(greet "world")
|
|
27
|
+
"""
|
|
28
|
+
result = src_to_python_org(src)
|
|
29
|
+
assert "WORLD" in result
|
|
30
|
+
|
|
31
|
+
def test_bool_is_bool(self):
|
|
32
|
+
src = PREAMBLE + """
|
|
33
|
+
(defmacro if-flag [flag *body]
|
|
34
|
+
(if flag
|
|
35
|
+
(return `(do ~@body))
|
|
36
|
+
(return `(pass))))
|
|
37
|
+
|
|
38
|
+
(if-flag True (print "yes"))
|
|
39
|
+
"""
|
|
40
|
+
result = src_to_python_org(src)
|
|
41
|
+
assert "print('yes')" in result
|
|
42
|
+
|
|
43
|
+
def test_none_is_none(self):
|
|
44
|
+
src = PREAMBLE + """
|
|
45
|
+
(defmacro maybe-wrap [val]
|
|
46
|
+
(if (is val None)
|
|
47
|
+
(return `(print "nothing"))
|
|
48
|
+
(return `(print ~val))))
|
|
49
|
+
|
|
50
|
+
(maybe-wrap None)
|
|
51
|
+
"""
|
|
52
|
+
result = src_to_python_org(src)
|
|
53
|
+
assert "nothing" in result
|
|
54
|
+
|
|
55
|
+
def test_symbol_stays_as_node(self):
|
|
56
|
+
src = PREAMBLE + """
|
|
57
|
+
(defmacro my-inc [x]
|
|
58
|
+
(return `(+ ~x 1)))
|
|
59
|
+
|
|
60
|
+
(my-inc y)
|
|
61
|
+
"""
|
|
62
|
+
result = src_to_python_org(src)
|
|
63
|
+
assert "y + 1" in result
|
|
64
|
+
|
|
65
|
+
def test_expression_stays_as_node(self):
|
|
66
|
+
src = PREAMBLE + """
|
|
67
|
+
(defmacro my-twice [expr]
|
|
68
|
+
(return `(+ ~expr ~expr)))
|
|
69
|
+
|
|
70
|
+
(my-twice (+ a b))
|
|
71
|
+
"""
|
|
72
|
+
result = src_to_python_org(src)
|
|
73
|
+
assert "a + b + (a + b)" in result
|
|
@@ -260,9 +260,10 @@ wheels = [
|
|
|
260
260
|
|
|
261
261
|
[[package]]
|
|
262
262
|
name = "lispython"
|
|
263
|
-
version = "0.4.
|
|
263
|
+
version = "0.4.5"
|
|
264
264
|
source = { editable = "." }
|
|
265
265
|
dependencies = [
|
|
266
|
+
{ name = "prompt-toolkit" },
|
|
266
267
|
{ name = "pygls" },
|
|
267
268
|
]
|
|
268
269
|
|
|
@@ -285,6 +286,7 @@ requires-dist = [
|
|
|
285
286
|
{ name = "mkdocs-macros-plugin", marker = "extra == 'docs'", specifier = ">=1.3.7" },
|
|
286
287
|
{ name = "mkdocs-material", marker = "extra == 'docs'", specifier = ">=9.6.14" },
|
|
287
288
|
{ name = "pre-commit", marker = "extra == 'dev'", specifier = ">=3.6.0" },
|
|
289
|
+
{ name = "prompt-toolkit", specifier = ">=3.0.52" },
|
|
288
290
|
{ name = "pygls", specifier = ">=1.0.0" },
|
|
289
291
|
{ name = "pytest", marker = "extra == 'dev'", specifier = ">=8.0.0" },
|
|
290
292
|
{ name = "ruff", marker = "extra == 'dev'", specifier = ">=0.8.0" },
|
|
@@ -576,6 +578,18 @@ wheels = [
|
|
|
576
578
|
{ url = "https://files.pythonhosted.org/packages/5d/19/fd3ef348460c80af7bb4669ea7926651d1f95c23ff2df18b9d24bab4f3fa/pre_commit-4.5.1-py2.py3-none-any.whl", hash = "sha256:3b3afd891e97337708c1674210f8eba659b52a38ea5f822ff142d10786221f77", size = 226437, upload-time = "2025-12-16T21:14:32.409Z" },
|
|
577
579
|
]
|
|
578
580
|
|
|
581
|
+
[[package]]
|
|
582
|
+
name = "prompt-toolkit"
|
|
583
|
+
version = "3.0.52"
|
|
584
|
+
source = { registry = "https://pypi.org/simple" }
|
|
585
|
+
dependencies = [
|
|
586
|
+
{ name = "wcwidth" },
|
|
587
|
+
]
|
|
588
|
+
sdist = { url = "https://files.pythonhosted.org/packages/a1/96/06e01a7b38dce6fe1db213e061a4602dd6032a8a97ef6c1a862537732421/prompt_toolkit-3.0.52.tar.gz", hash = "sha256:28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855", size = 434198, upload-time = "2025-08-27T15:24:02.057Z" }
|
|
589
|
+
wheels = [
|
|
590
|
+
{ url = "https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955", size = 391431, upload-time = "2025-08-27T15:23:59.498Z" },
|
|
591
|
+
]
|
|
592
|
+
|
|
579
593
|
[[package]]
|
|
580
594
|
name = "pygls"
|
|
581
595
|
version = "2.1.1"
|
|
@@ -864,6 +878,15 @@ wheels = [
|
|
|
864
878
|
{ url = "https://files.pythonhosted.org/packages/33/e8/e40370e6d74ddba47f002a32919d91310d6074130fe4e17dabcafc15cbf1/watchdog-6.0.0-py3-none-win_ia64.whl", hash = "sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f", size = 79067, upload-time = "2024-11-01T14:07:11.845Z" },
|
|
865
879
|
]
|
|
866
880
|
|
|
881
|
+
[[package]]
|
|
882
|
+
name = "wcwidth"
|
|
883
|
+
version = "0.6.0"
|
|
884
|
+
source = { registry = "https://pypi.org/simple" }
|
|
885
|
+
sdist = { url = "https://files.pythonhosted.org/packages/35/a2/8e3becb46433538a38726c948d3399905a4c7cabd0df578ede5dc51f0ec2/wcwidth-0.6.0.tar.gz", hash = "sha256:cdc4e4262d6ef9a1a57e018384cbeb1208d8abbc64176027e2c2455c81313159", size = 159684, upload-time = "2026-02-06T19:19:40.919Z" }
|
|
886
|
+
wheels = [
|
|
887
|
+
{ url = "https://files.pythonhosted.org/packages/68/5a/199c59e0a824a3db2b89c5d2dade7ab5f9624dbf6448dc291b46d5ec94d3/wcwidth-0.6.0-py3-none-any.whl", hash = "sha256:1a3a1e510b553315f8e146c54764f4fb6264ffad731b3d78088cdb1478ffbdad", size = 94189, upload-time = "2026-02-06T19:19:39.646Z" },
|
|
888
|
+
]
|
|
889
|
+
|
|
867
890
|
[[package]]
|
|
868
891
|
name = "zipp"
|
|
869
892
|
version = "3.23.0"
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
from lispy.tools import src_to_python_org
|
|
2
|
-
|
|
3
|
-
PREAMBLE = "(require lispy.macros *)\n"
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class TestAsThread:
|
|
7
|
-
def test_no_forms(self):
|
|
8
|
-
assert src_to_python_org(PREAMBLE + "(as-> 42 x)") == "42"
|
|
9
|
-
|
|
10
|
-
def test_single_form(self):
|
|
11
|
-
result = src_to_python_org(PREAMBLE + "(as-> 0 x (+ x 1))")
|
|
12
|
-
assert "x = 0" in result
|
|
13
|
-
assert "x = x + 1" in result
|
|
14
|
-
|
|
15
|
-
def test_multiple_forms(self):
|
|
16
|
-
result = src_to_python_org(
|
|
17
|
-
PREAMBLE + "(as-> 0 x (+ x 10) (* 2 x) (str x))"
|
|
18
|
-
)
|
|
19
|
-
assert "x = 0" in result
|
|
20
|
-
assert "x = x + 10" in result
|
|
21
|
-
assert "x = 2 * x" in result
|
|
22
|
-
assert "x = str(x)" in result
|
|
23
|
-
|
|
24
|
-
def test_method_call(self):
|
|
25
|
-
result = src_to_python_org(
|
|
26
|
-
PREAMBLE + '(as-> "hello" s (.upper s))'
|
|
27
|
-
)
|
|
28
|
-
assert "s = 'hello'" in result
|
|
29
|
-
assert "s = s.upper()" in result
|
|
30
|
-
|
|
31
|
-
def test_flexible_placement(self):
|
|
32
|
-
result = src_to_python_org(
|
|
33
|
-
PREAMBLE + "(as-> 1 x (+ 10 x) (- x 5))"
|
|
34
|
-
)
|
|
35
|
-
assert "x = 10 + x" in result
|
|
36
|
-
assert "x = x - 5" in result
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|