Verbose version: http://worlddomination.be/about/about.html
Not lossless !
ast_to_code(code_to_ast(code_source)) != source_code
(Comments, formatting)
(And ast_to_code doesn't exist officially).
API Sax like
1 class KeyAttributesFinder(ast.NodeVisitor):
2 def visit_Assign(self, assign_node):
3 # ...
4
5 def visit_FunctionDef(self, function_node):
6 # ...
7
8 # visit_...
Terribly boring and unfunny to use (and unusable in a shell like IPython.)
Source code auto formater
Django (opendata projects like memopol):
donnees.json -> models.py + import.py
1 from baron.helpers import show
2
3 print show("1 + 2")
4
5 [
6 {
7 "first_formatting": [
8 {
9 "type": "space",
10 "value": " "
11 }
12 ],
13 "value": "+",
14 "second_formatting": [
15 {
16 "type": "space",
17 "value": " "
18 }
19 ],
20 "second": {
21 "section": "number",
22 "type": "int",
23 "value": "2"
24 },
25 "type": "binary_operator",
26 "first": {
27 "section": "number",
28 "type": "int",
29 "value": "1"
30 }
31 }
32 ]
~1 year of work (needed to learn)
Very simple API:
1 from redbaron import RedBaron
2
3 red = RedBaron("some source code as a string")
4 # ...
5 red.dumps() # source code
Overloading of __repr__:
BeautifulSoup:
Overloading of __repr__:
BeautifulSoup:
RedBaron:
RedBaron:
RedBaron:
".help()"
Like BeautifulSoup:
1 red = RedBaron("a = 42\ndef test_chocolate(): pass")
2 red.find("name")
3 red.find("int", value=42)
4 red.find("def", name="g:test_*")
5 red.find("def", name="re:test_*")
6 red.find("assignment", lambda x: x.target.dumps() == "INSTALLED_APPS")
7
8 red.find_all("name")
9 red.find_all(("name", "int"))
10 red.find_all("def", arguments=lambda x: len(x) == 3)
11 red.find_all("def", recursive=False)
Like BeautifulSoup:
1 red = RedBaron("a = 42\ndef test_chocolate(): pass")
2 red.find("name")
3 red.find("int", value=42)
4 red.find("def", name="g:test_*")
5 red.find("def", name="re:test_*")
6 red.find("assignment", lambda x: x.target.dumps() == "INSTALLED_APPS")
7
8 red.find_all("name")
9 red.find_all(("name", "int"))
10 red.find_all("def", arguments=lambda x: len(x) == 3)
11 red.find_all("def", recursive=False)
Shortcuts (like BeautifulSoup):
1 red = RedBaron("a = 42\ndef test_chocolate(): pass")
2 red.name
3 red.int
4 red.else_
5
6 red("name")
7 red(("name", "int"))
8 red("def", arguments=lambda x: len(x) == 3)
How to modify a node?
1 from redbaron import RedBaron, BinaryOperatorNode
2
3 red = RedBaron("a = 'plop'")
4 red[O].value # 'plop'
5 red[0].value = BinaryOperatorNode({'first_formatting':[{'type': 'space',
6 'value': ' '}], 'value': '+', 'second_formatting': [{'type': 'space',
7 'value': ' '}], 'second': {'section': 'number', 'type': 'int', 'value':
8 '1'}, 'type': 'binary_operator', 'first': {'section': 'number', 'type':
9 'int', 'value': '1'}})
Pretty much horrible.
1 from redbaron import RedBaron, BinaryOperatorNode
2
3 red = RedBaron("a = 'plop'")
4 red[0].value = "1 + 1"
5
6 # works also with: redbaron nodes and json ast
Works for every nodes.
Another problem: what is the body of the bar function?
1 class Foo():
2 def bar(self):
3 pass
4
5 def baz(self):
6 pass
Another problem: what is the body of the bar function?
1 class Foo():
2 def bar(self):
3 pass
4
5 def baz(self):
6 pass
Expected:
Another problem: what is the body of the bar function?
1 class Foo():
2 def bar(self):
3 pass
4
5 def baz(self):
6 pass
Expected:
Reality:
1 red.find("def", name="bar").value = "pass"
2 red.find("def", name="bar").value = "pass\n"
3 red.find("def", name="bar").value = " pass\n"
4 red.find("def", name="bar").value = " pass\n "
5 red.find("def", name="bar").value = " pass\n "
6 red.find("def", name="bar").value = "\n pass\n "
7 # etc ..
Works for every node with a body: else, exceptions, finally, elif etc...
Problem: how many elements are in this list? ['a', 'b', 'c']
Problem: how many elements are in this list?
Expected:
Problem: how many elements are in this list?
Expected:
Reality:
Solution: "proxy lists", gives you the same API than python list and handle formatting for you.
Reality again:
Works for:
a.b.c().pouet[stuff]
.map
.apply
.filter
.next
, .previous
, .parent
.replace
.insert_before
.insert_after
1 # rename a 'name' (warning: won't rename everything)
2 for i in red('name', value='pouet'): i.value = 'plop'
1 # install a django app
2 red.find("assign", target=lambda x: x.dumps() == 'INSTALLED_APPS').\
3 value.append("'debug_toolbar.apps.DebugToolbarConfig'")
1 # lines_profiler
2 red('def', recursive=False).\
3 map(lambda x: x.decorators.insert(0, '@profile'))
1 # lines_profiler
2 red('def', recursive=False).\
3 map(lambda x: x.decorators.insert(0, '@profile'))
4
5 # remove them
6 red("decorator", lambda x: x.dumps() == "@decorator").\
7 map(lambda x: x.parent.parent.decorators.remove(x))
1 # print a -> logger.debug(a)
2 red('print', value=lambda x: len(x) == 1).\
3 map(lambda x: x.replace('logger.debug(%s)' % x.value.dumps())
4
5 # print a, b, c -> logger.debug("%s %s %s" % (a, b, c))
6 red('print', value=lambda x: len(x) == 1).\
7 map(lambda x: x.replace('logger.debug("%s" % (%s))' %
8 (" ".join('%s' * len(x.value)))
Every example are run at documentation compile time:
RedBaron:
pip install redbaron
Baron:
pip install baron
Contacts:
Usage:
1 from pyfmt import format_code
2
3 format_code(source_code)
1 red *.py # in a shell bash/zsh/autre
It launchs a Ipython shell with:
1 red
2 red[0]
3 red["./test_redflyingbaron.py"]
4 red["test_redflyingbaron.py"]
5 red["test_redflyingbaron"]
6 red[1:]
7
8 red.display()
9
10 red[0].save()
11 red.save()
12 red[0].reload()
13 red.reload()
14
15 red["f:redflyingbaron"]
16 red[re.compile(r'[^_]+')]
17 red["re:[^_]+"]
18 red[lambda key, value: "red" in key]
19
20 red.find("stuff")
21 red.find_all("stuff")
22
23 red.add("/path/to/file", "/path/to/another/file", "again.py")
Table of Contents | t |
---|---|
Exposé | ESC |
Full screen slides | e |
Presenter View | p |
Source Files | s |
Slide Numbers | n |
Toggle screen blanking | b |
Show/hide slide context | c |
Notes | 2 |
Help | h |