patternpythonMinor
Static blog generator
Viewed 0 times
blogstaticgenerator
Problem
I want yet another review on my static blog generator script for improvements.
```
#
#Static blogs generator.
#See https://github.com/st-kurilin/blogator for details.
#
#Main script. Used to build final script using build.py script.
#
###Files operations
#separated to make testing easier
"""Default values for some files.
Used to distribute script as a single file.
Actual values filled by build.py script."""
PREDEFINED = {}
def read(path):
"""Reads file content from FS"""
if path in PREDEFINED:
return PREDEFINED[path]
with open(path.as_posix()) as file:
return file.read()
def write(path, content):
"""Writes file content to FS"""
with open(path.as_posix(), 'w') as file:
file.write(content)
def copy(from_p, to_p):
"""Copies file content"""
import shutil
shutil.copyfile(from_p.as_posix(), to_p.as_posix())
def file_exist(path):
"""Check if file exist for specified path"""
return path.is_file()
###Markdown template engine operations
def md_read(inp):
"""Reads markdown formatted message."""
import markdown
md_converter = markdown.Markdown(extensions=['meta'])
content = md_converter.convert(inp)
meta = getattr(md_converter, 'Meta', [])
return {
'meta' : meta,
'content' : content
}
def md_meta_get(meta, key, alt=None, single_value=True):
"""Reads value from markdown read message meta."""
if key in meta:
if single_value and meta[key]:
return meta[key][0]
else:
return meta[key]
return alt
###Pystache template engine operations
def pystached(template, data):
"""Applies data to pystache template"""
import pystache
pys_template = pystache.parse(template)
pys_renderer = pystache.Renderer()
return pys_renderer.render(pys_template, data)
###Meta files readers operations
def parse_blog_meta(blog_meta_content):
"""Reads general blog info from file."""
from functools import partial
```
#
#Static blogs generator.
#See https://github.com/st-kurilin/blogator for details.
#
#Main script. Used to build final script using build.py script.
#
###Files operations
#separated to make testing easier
"""Default values for some files.
Used to distribute script as a single file.
Actual values filled by build.py script."""
PREDEFINED = {}
def read(path):
"""Reads file content from FS"""
if path in PREDEFINED:
return PREDEFINED[path]
with open(path.as_posix()) as file:
return file.read()
def write(path, content):
"""Writes file content to FS"""
with open(path.as_posix(), 'w') as file:
file.write(content)
def copy(from_p, to_p):
"""Copies file content"""
import shutil
shutil.copyfile(from_p.as_posix(), to_p.as_posix())
def file_exist(path):
"""Check if file exist for specified path"""
return path.is_file()
###Markdown template engine operations
def md_read(inp):
"""Reads markdown formatted message."""
import markdown
md_converter = markdown.Markdown(extensions=['meta'])
content = md_converter.convert(inp)
meta = getattr(md_converter, 'Meta', [])
return {
'meta' : meta,
'content' : content
}
def md_meta_get(meta, key, alt=None, single_value=True):
"""Reads value from markdown read message meta."""
if key in meta:
if single_value and meta[key]:
return meta[key][0]
else:
return meta[key]
return alt
###Pystache template engine operations
def pystached(template, data):
"""Applies data to pystache template"""
import pystache
pys_template = pystache.parse(template)
pys_renderer = pystache.Renderer()
return pys_renderer.render(pys_template, data)
###Meta files readers operations
def parse_blog_meta(blog_meta_content):
"""Reads general blog info from file."""
from functools import partial
Solution
(The code looks great, I still tried to provide helpful suggestions.)
I use single source file to make it easier to distribute
Why would a single .py file be easier to distribute? We have lots of ways to distribute Python files, such as
and imports
in functions to make it more clear to myself.
Except you're violating PEP 8, which means other developers will have trouble understanding (and sticking to) your convention. Speaking about PEP8,
Those functions only complicate your code since the abstraction offered is not enough to compensate the added complexity.
This one wouldn't be needed with a standard way to distribute your file. Also, the pathlib documentation advises
Since you're in the context of your application, is it possible to give a more meaningful name to the
Think what you want about the clarity of
Isn't
This is interesting. You could think of it as the canonical data structure that you want to pass around, using a standard name, instead of sending specifically
Consider using
Good abstraction!
What's the point? Isn't it equivalent without
```
post['published'] = reformat_date('%Y-%m-%d', '%d %b %
I use single source file to make it easier to distribute
Why would a single .py file be easier to distribute? We have lots of ways to distribute Python files, such as
git clone ... && python setup.py install, pip, wheels...and imports
in functions to make it more clear to myself.
Except you're violating PEP 8, which means other developers will have trouble understanding (and sticking to) your convention. Speaking about PEP8,
pip install flake8 and flake8 myfile.py will help. I won't comment about lexical syntax anymore.###Files operations
#separated to make testing easierThose functions only complicate your code since the abstraction offered is not enough to compensate the added complexity.
"""Default values for some files.
Used to distribute script as a single file.
Actual values filled by build.py script."""
PREDEFINED = {}
def read(path):
"""Reads file content from FS"""
if path in PREDEFINED:
return PREDEFINED[path]
with open(path.as_posix()) as file:
return file.read()This one wouldn't be needed with a standard way to distribute your file. Also, the pathlib documentation advises
str(path) instead of path.as_posix().def write(path, content):
"""Writes file content to FS"""
with open(path.as_posix(), 'w') as file:
file.write(content)Since you're in the context of your application, is it possible to give a more meaningful name to the
write function?def copy(from_p, to_p):
"""Copies file content"""
import shutil
shutil.copyfile(from_p.as_posix(), to_p.as_posix())
def file_exist(path):
"""Check if file exist for specified path"""
return path.is_file()Think what you want about the clarity of
path.is_file(), but those two functions complicate the code (I need to lookup what they do), while shutil.copyfile and is_file() are standard and more likely to be known by other developers.###Markdown template engine operations
def md_read(inp):
"""Reads markdown formatted message."""
import markdown
md_converter = markdown.Markdown(extensions=['meta'])
content = md_converter.convert(inp)
meta = getattr(md_converter, 'Meta', [])Isn't
md_converter.meta enough?return {
'meta' : meta,
'content' : content
}This is interesting. You could think of it as the canonical data structure that you want to pass around, using a standard name, instead of sending specifically
meta and content.def md_meta_get(meta, key, alt=None, single_value=True):
"""Reads value from markdown read message meta."""
if key in meta:
if single_value and meta[key]:
return meta[key][0]
else:
return meta[key]
return altConsider using
meta_key = meta.get(key, alt).###Pystache template engine operations
def pystached(template, data):
"""Applies data to pystache template"""
import pystache
pys_template = pystache.parse(template)
pys_renderer = pystache.Renderer()
return pys_renderer.render(pys_template, data)Good abstraction!
###Meta files readers operations
def parse_blog_meta(blog_meta_content):
"""Reads general blog info from file."""
from functools import partial
meta = md_read(blog_meta_content)['meta']
get = partial(md_meta_get, meta)get is a bit generic and confusing. Is saving a few keystrokes that important anyway?favicon_file = get('favicon-file')
favicon_url = get('favicon-url', 'favicon.cc/favicon/169/1/favicon.png')
return {
'meta' : meta,
'title' : get('title', 'Blog'),
'annotation' : get('annotation', 'Blogging for living'),
'favicon-file' : favicon_file,
'favicon' : 'favicon.ico' if favicon_file else favicon_url,
'posts' : get('posts', [], False),
'disqus' : get('disqus'),
'ganalitics' : get('ganalitics'),
}
def parse_post(post_blob, post_blob_orig_name):
"""Reads post info from file."""
import datetime
from functools import partial
def reformat_date(inpf, outf, date):
"""Reformats dates from one specified format to other one."""
if date is None:
return None
return datetime.datetime.strptime(date, inpf).strftime(outf)
row_post = md_read(post_blob)
post = {}
post['meta'] = meta = row_post['meta']
get = partial(md_meta_get, meta)
post['content'] = row_post['content']
post['title'] = get('title', post_blob_orig_name)
post['brief'] = get('brief')
post['short_title'] = get('short_title', post['title'])
post['link_base'] = get('link', post_blob_orig_name + ".html")
post['link'] = './' + post['link_base']What's the point? Isn't it equivalent without
post['link_base']?```
post['published'] = reformat_date('%Y-%m-%d', '%d %b %
Code Snippets
###Files operations
#separated to make testing easier"""Default values for some files.
Used to distribute script as a single file.
Actual values filled by build.py script."""
PREDEFINED = {}
def read(path):
"""Reads file content from FS"""
if path in PREDEFINED:
return PREDEFINED[path]
with open(path.as_posix()) as file:
return file.read()def write(path, content):
"""Writes file content to FS"""
with open(path.as_posix(), 'w') as file:
file.write(content)def copy(from_p, to_p):
"""Copies file content"""
import shutil
shutil.copyfile(from_p.as_posix(), to_p.as_posix())
def file_exist(path):
"""Check if file exist for specified path"""
return path.is_file()###Markdown template engine operations
def md_read(inp):
"""Reads markdown formatted message."""
import markdown
md_converter = markdown.Markdown(extensions=['meta'])
content = md_converter.convert(inp)
meta = getattr(md_converter, 'Meta', [])Context
StackExchange Code Review Q#63174, answer score: 5
Revisions (0)
No revisions yet.