Evaluation of Python code in content files

This commit is contained in:
faildev_mode 2023-05-29 22:23:19 +02:00
parent 5be18c393c
commit 4363871abc
No known key found for this signature in database
GPG Key ID: 70845C70C0F5E205
2 changed files with 50 additions and 5 deletions

View File

@ -12,6 +12,7 @@ import frontmatter # from package python-frontmatter
import datetime
import re
from functools import partial
import evaluations # from itself
def link_this(src: str, dest: str):
"""Creates symlink to source at destination
@ -87,8 +88,28 @@ def save_this(path: str, content: str):
with open(path, 'w') as fp:
fp.write(content)
def evaluate_content(match: re.Match, frontmatter_data: dict) -> str:
return '{evaluation goes here!}'
def evaluate_content(match: re.Match, frontmatter_data: dict, path: str) -> str:
global config
match = match.group(1)
print(' '+match)
# prepare globals (environment) for the evaluation
environment = {}
extension = vars(evaluations.Content)
for i in extension.keys():
if i.startswith('_'): continue
environment[i] = extension[i]
environment.update(config['variables'])
environment['path'] = path
environment.update(frontmatter_data)
# this trick let the evaluation functions access our environment
evaluations.environment = environment
# now execute the command!
try:
return str(eval(match, environment))
except Exception as error:
print('\033[31m ', error, '\033[m', file=sys.stderr)
if __name__ == '__main__':
@ -101,6 +122,7 @@ if __name__ == '__main__':
# load config
config = configparser.ConfigParser(interpolation=configparser.ExtendedInterpolation())
config.read('config.ini')
evaluations.config = config # pass the config to evaluations module, so functions can read it
# scan source files
content_files = scan_dir('content')
@ -135,12 +157,11 @@ if __name__ == '__main__':
# evaluate {python code} in braces in content files, pass frontmatter_data to the function
content = re.sub(r'\{([^\s}]+([^}]*[^\s}])?)\}',
partial(evaluate_content, frontmatter_data=frontmatter_data),
content, flags=re.DOTALL)
partial(evaluate_content, frontmatter_data=frontmatter_data, path=path),
content)
# load template
if template := template_for(path):
print(' template:', template)
if template not in template_cache:
with open('templates/'+template) as fp:
template_cache[template] = fp.read()

24
_src/evaluations.py Normal file
View File

@ -0,0 +1,24 @@
#!/usr/bin/env python3
import os
import urllib.parse
class Content:
def log(dest: str) -> str:
return 'gemlog/'+dest+'.gmi'
def article(dest):
return 'articles/'+dest+'.gmi'
def res(dest, label=None):
path = os.path.splitext(environment['path'])[0]
path += '/'+dest
if not os.path.exists('static/'+path):
raise Exception(f'Resource {dest} for {path} not found')
path = os.path.relpath(path, start=os.path.dirname(os.path.dirname(path)))
path = urllib.parse.quote(path)
if label:
return path+' '+label
else:
return path