from sqlalchemy import create_engine from sqlalchemy.sql import select, update, insert from sqlalchemy.sql.expression import literal from .schema import metadata, articles from markdown import markdown from string import whitespace, punctuation import re import os import sys db_file = os.path.join(sys.argv[1], 'lazy_wiki.sqlite3') regex = re.compile(r'^\W+|^\W*\w+\W*') # instantiate an engine for connecting to a database engine = create_engine('sqlite:///{}'.format(db_file)) # create tables if they don't exist metadata.create_all(engine) # connect to the database dbc = engine.connect() def select_longest_keyword_string_starts_with(string): ''' Fetch the longest keyword that the given string starts with. ''' query = select([articles]) \ .where(literal(string).ilike(articles.c.title + '%')) # may be bottleneck results = [dict(u) for u in dbc.execute(query).fetchall()] if not results: return None return max(results, key = lambda keyword : len(keyword['title'])) def select_article(keyword): ''' Fetch an article associated with the given keyword. ''' query = select([articles]) \ .where(articles.c.title == literal(keyword)) try: return dict(dbc.execute(query).fetchone()) except: return None def select_formatted_article(keyword): ''' Fetch an article associated with the given keyword, add hyperlinks to it, and format it to HTML. ''' # get article content article = select_article(keyword) raw = article['content'] # add hyperlinks to the content formatted = '' # until the raw content is empty while raw: # if the remaining raw content starts with a keyword word = select_longest_keyword_string_starts_with(raw) if word and raw[len(word['title'])] in punctuation + whitespace: # use original capitalization for hyperlink text original = raw[:len(word['title'])] # create a Markdown hyperlink word = '[{}](/view/{})'.format(original, word['title']) # cut off the start of the raw content raw = raw[len(original):] else: # cut a word off the start of the raw content word = regex.search(raw).group() raw = raw[len(word):] # add the hyperlink or word to the formatted content formatted += word article['content'] = markdown(formatted) return article def insert_article(**kwargs): query = insert(articles).values(**kwargs) dbc.execute(query) def update_article(title, **kwargs): query = update(articles) \ .where(articles.c.title == literal(title)) \ .values(**kwargs) dbc.execute(query)