From 628b681940fdee4258dc3fb47e2ad2d8be5d6e98 Mon Sep 17 00:00:00 2001 From: Gijs Date: Fri, 4 Jun 2021 10:02:30 +0200 Subject: [PATCH] First version of Grafting a Tree book generator. --- Readme.md | 4 +- __pycache__/trees.cpython-38.pyc | Bin 8515 -> 0 bytes app.py | 48 +++++++++ growing_a_tree_sketch.py => graft_a_tree.py | 112 +++++++++----------- test.py => pagedjs.py | 2 +- requirements.txt | 3 + run.sh | 3 + templates/book.html | 53 +++++++++ templates/index.html | 97 +++++++++++++++++ 9 files changed, 259 insertions(+), 63 deletions(-) delete mode 100644 __pycache__/trees.cpython-38.pyc create mode 100644 app.py rename growing_a_tree_sketch.py => graft_a_tree.py (54%) rename test.py => pagedjs.py (97%) create mode 100644 run.sh create mode 100644 templates/book.html create mode 100644 templates/index.html diff --git a/Readme.md b/Readme.md index 977382d..ddda4ce 100644 --- a/Readme.md +++ b/Readme.md @@ -3,4 +3,6 @@ # Installation The prototype uses pagedjs-cli to convert the HTML into PDF. In a terminal `cd` into the cloned folder and run: -`npm install pagedjs-cli` \ No newline at end of file +`npm install pagedjs-cli` + +*to do* Add instructions on installation of NLTK data \ No newline at end of file diff --git a/__pycache__/trees.cpython-38.pyc b/__pycache__/trees.cpython-38.pyc deleted file mode 100644 index fa384c55b30b5e53ab26530e743e4851e0eb2cf2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8515 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 diff --git a/app.py b/app.py new file mode 100644 index 0000000..dcbe4e5 --- /dev/null +++ b/app.py @@ -0,0 +1,48 @@ +#!/usr/bin/env/ python +from sys import stdout +from flask import Flask, Response, render_template, request +from pagedjs import make_pdf +from graft_a_tree import graft_a_tree +from io import StringIO +import sys +import textwrap + +BASEURL = '' +MIN_GROW_YEARS = 0 +MAX_GROW_YEARS = 25 + +app = Flask(__name__) + +def wrap (text, width): + return'\n'.join([(' \\\n').join(textwrap.wrap(line, width=width - 2)) for line in text.splitlines()]) + +with open('graft_a_tree.py', 'r') as script: + source_code = script.read() + +@app.route('{}/'.format(BASEURL)) +def index(): + return render_template('index.html', BASEURL=BASEURL) + +@app.route('{}/graft'.format(BASEURL), methods=['POST']) +def graft(): + years = max(MIN_GROW_YEARS, min(MAX_GROW_YEARS, int(request.form['years']))) + + with StringIO() as script_stdout: + default_stdout = sys.stdout + sys.stdout = script_stdout + graft_a_tree(years) + content = script_stdout.getvalue() + sys.stdout = default_stdout + + html = render_template('book.html', content=content, source_code=wrap(source_code, 100).replace(' ', ' ').replace('\n', '
')) + # print(html) + print('html rendered') + pdf = make_pdf(html) + print('made pdf') + r = Response(pdf, mimetype='application/pdf') + + r.headers.extend({ + 'Content-Disposition': 'attachment; filename="grafted-tree.pdf"' + }) + + return r \ No newline at end of file diff --git a/growing_a_tree_sketch.py b/graft_a_tree.py similarity index 54% rename from growing_a_tree_sketch.py rename to graft_a_tree.py index 2d598cb..15ab48f 100644 --- a/growing_a_tree_sketch.py +++ b/graft_a_tree.py @@ -37,20 +37,8 @@ from trees import trees import os import os.path -from colored import fg, attr - -## Text attributes -bold = attr(1) -underlined = (4) -reset = attr(0) - -## Text colors -black = fg(0) -spring_green = fg(48) -light_gray = fg(7) -sky_blue = fg(109) -yellow = fg(3) - +import sys +from io import StringIO def choose_a_tree(dict): collection = random.choice(list(trees.items())) @@ -77,7 +65,7 @@ def bio(gardener): bio = wikipedia.page(gardener) short_bio = bio.summary except: - short_bio = "{}There is no English Wikipedia page about this person.{}".format(sky_blue, reset) + short_bio = "There is no English Wikipedia page about this person." return short_bio def bio_offline(gardener): @@ -87,7 +75,7 @@ def bio_offline(gardener): with open(filename, 'r') as h: return h.read() - return "{}There is no English Wikipedia page about this person.{}".format(sky_blue, reset) + return "There is no English Wikipedia page about this person." """ @@ -106,52 +94,54 @@ def grow_new_branch (bud): # Turn nltk tree back into a sentence def trim_tree (branches): tree = " ".join([branch[0] for branch in branches]) + # Remove spaces in html tags + tree = re.sub(r'\<\s*(\/?\w+)\s*\>', '<\\1>', tree) return re.sub(r'\s[\.,:;\(\)]', '', tree) -def show (state, length=1): - os.system('clear') - # Optionally vertically align here - print(state) - time.sleep(length) - -def grow (tree, generation = 1): - branches = nltk.pos_tag(word_tokenize(tree)) - # Filter out nouns, pick one - position, bud = random.choice([(position, bud[0]) for position, bud in enumerate(branches) if bud[1] == 'NN']) - - # Make new tree placeholder for the bud show we can show it in two states and then grow out - next_tree = '{} {{}} {}'.format(trim_tree(branches[:max(0, position)]), trim_tree(branches[position+1:])) - new_branch = grow_new_branch(bud) - - show(tree, 3 if generation == 1 else 1) - # Mark the bud, underlined and orange - show(next_tree.format("{}{}{}{}{}".format(bold, yellow, bud, reset, black)), 2) - # Mark the new branch green - show(next_tree.format("{}{}{}".format(spring_green, new_branch, black)), 2) - show(next_tree.format("{}{}{}".format(fg(82), new_branch, black)), 1) - show(next_tree.format("{}{}{}".format(fg(120), new_branch, black)), 1) - show(next_tree.format("{}{}{}".format(fg(157), new_branch, black)), 1) - show(next_tree.format("{}{}{}".format(fg(195), new_branch, black)), 1) - # Let it grow again - - return next_tree.format(new_branch) +def graft_a_tree (years = 3): + gardener, source, tree = choose_a_tree(trees) + short_bio = bio_offline(gardener) + + print( + '
' + + 'Using a quote by {}

'.format(gardener) \ + + short_bio + + '
' + ) + + year = 1 + + print('

{}

'.format(tree)) + + while year <= years: + branches = nltk.pos_tag(word_tokenize(tree)) + # Filter out nouns, pick one + position, bud = random.choice([(position, bud[0]) for position, bud in enumerate(branches) if bud[1] == 'NN']) + + tree_with_bud = '{} {} {}'.format( + trim_tree(branches[:max(0, position)]), + bud.strip(), + trim_tree(branches[position+1:])) + + print('

{}

'.format(year, tree_with_bud)) + + # Make new tree placeholder for the bud show we can show it in two states and then grow out + grown_tree = '{} {} {}'.format( + trim_tree(branches[:max(0, position)]), + grow_new_branch(bud).strip(), + trim_tree(branches[position+1:])) + # Let it grow again + + print('

{}

'.format(year, grown_tree)) + + grown_tree = re.sub(r'\<\/?\w+\>', '', grown_tree) + + if grown_tree == tree: + break + else: + tree = grown_tree + + year += 1 if __name__ == '__main__': - while True: - gardener, source, tree = choose_a_tree(trees) - short_bio = bio_offline(gardener) - - show( - 'Using a quote by {}{}{}\n\n'.format(bold, gardener, reset) \ - + short_bio, 3 - ) - - generation = 1 - - while len(tree) < 1500: - next_tree = grow(tree, generation) - if next_tree == tree: - break - else: - tree = next_tree - generation += 1 \ No newline at end of file + graft_a_tree(3) \ No newline at end of file diff --git a/test.py b/pagedjs.py similarity index 97% rename from test.py rename to pagedjs.py index adadee5..6fb6774 100644 --- a/test.py +++ b/pagedjs.py @@ -65,7 +65,7 @@ def make_pdf (html, path_out=None, extra_scripts=[]): shutil.copy(name_out, path_out) return path_out else: - with open(name_out) as generated_pdf: + with open(name_out, 'rb') as generated_pdf: return generated_pdf.read() if __name__ == '__main__': diff --git a/requirements.txt b/requirements.txt index e69de29..5ac81d0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -0,0 +1,3 @@ +nltk +wikipedia +flask \ No newline at end of file diff --git a/run.sh b/run.sh new file mode 100644 index 0000000..a1709d8 --- /dev/null +++ b/run.sh @@ -0,0 +1,3 @@ +export FLASK_APP=app.py +export FLASK_ENV=development +flask run \ No newline at end of file diff --git a/templates/book.html b/templates/book.html new file mode 100644 index 0000000..1d41a42 --- /dev/null +++ b/templates/book.html @@ -0,0 +1,53 @@ + + + + + + + Document + + + +

Grafted tree

+ + {% autoescape false %} + {{ content }} + + {{ source_code }} + {% endautoescape %} + + \ No newline at end of file diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..dd0f0de --- /dev/null +++ b/templates/index.html @@ -0,0 +1,97 @@ + + + + + + + Document + + + +

Grafting a tree

+

+

+ Graft a tree for years. + +
+

+

+ Grafting your tree. This might take a while. +

+

+ Something went wrong. +

+ + + \ No newline at end of file