write markdown filers parser

This commit is contained in:
Frederick Pauchet 2018-08-22 15:56:39 +02:00
parent 6963a34f97
commit 139ebc2c91
13 changed files with 225 additions and 2 deletions

4
.gitignore vendored
View File

@ -1,2 +1,6 @@
.vuepress
node_modules/
.vscode
.pytest_cache
.coverage
*.pyc

35
articles/dev/pytest.md Normal file
View File

@ -0,0 +1,35 @@
# PyTest
[Pytest](https://docs.pytest.org/en/latest/) se pose comme une alternative au module [unittest](https://docs.python.org/3/library/unittest.html), dont la syntaxe est un peu plus light que le modèle basé sur JUnit.
Par exemple, on passe de
```python
import unittest
class MyTestClass(unittest.TestCase):
def setUp(self):
pass
def test_bidule_brol(self):
self.assertEquals(1, 1)
self.assertContains(1, [1, 2])
...
def tearDown(self):
pass
```
à
```python
def test_equality():
assert 1 == 1
assert 1 in [1, 2]
```
On gagne donc pas mal en lisibilité et en rapidité d'écriture: il n'est pas utile de retenir toutes les fonctions d'assertion (et quand on voit [la liste disponible](../../old/testing.md), ce n'est pas un mal).
Pour gagner en rapidité sur certains projets, n'hésitez pas à passer directement le répertoire dans lequel les tests sont disponibles. Sans cela, on passe par un processus de découverte, qui va parcourir chaque répertoire afin de trouver quelque chose à faire.
En plus de cela, il y a pas mal de plugins, notamment [pytest-cov](https://pytest-cov.readthedocs.io/en/latest/readme.html#usage) qui permet de simuler la couverture de code pour un package en particulier. Une fois l'installation terminée, il suffit de passer `--cov=package` à l'exécution des tests.

View File

@ -1,7 +1,16 @@
import os
from os.path import join
from bottle import Bottle, run
app = Bottle()
run(app, host='localhost', port=5000)
if __name__ == "__main__":
for root, dirs, files in os.walk('articles'):
for file in files:
print(os.path.join(root))

0
grnx/__init__.py Normal file
View File

17
grnx/grnx.py Normal file
View File

@ -0,0 +1,17 @@
# coding: utf-8
from grnx.models import Site
from jinja2 import Environment, PackageLoader, select_autoescape
env = Environment(
loader=PackageLoader('grnx', 'templates'),
autoescape=select_autoescape(['html'])
)
if __name__ == "__main__":
root = Site('content')
root.serialize()
template = env.get_template('single.html')
for article in root.articles:
print(template.render(article.__dict__))

116
grnx/models.py Normal file
View File

@ -0,0 +1,116 @@
# coding: utf-8
import datetime
import json
import re
import os
import logging
logger = logging.getLogger(__name__)
RE_HEADER = re.compile('---((.)?(\n)?)*---')
date_handler = lambda obj: (
obj.isoformat()
if isinstance(obj, datetime.datetime)
or isinstance(obj, datetime.date)
else None
)
def json_handler(obj):
"""Handles the JSON object serializer.
Returns:
The iso format if the object is a date.
The __dict__ attribute for any other JSON serializable object.
Excepts:
TypeError when object is not JSON serialisable.
"""
if hasattr(obj, 'isoformat'):
return obj.isoformat()
elif obj.__dict__:
return obj.__dict__
else:
raise TypeError('Object of type %s with value of %s is not JSON serializable' % (type(obj), repr(obj)))
class Article(object):
def __init__(self, path, content, publication_date):
self.path = path
self.content = content
self.publication_date = publication_date
def get_date_from_article_filename(article_filename):
"""Get the date from a file name.
Args:
article_filename (str): the file name of the article.
Example:
2018-02-01-firewatch.md -> 1st of February 2018
2017-02-03-divinity-origin-sin.md -> None
lynis.md -> None
"""
values = article_filename.split('-')
date = None
try:
date = datetime.date(int(values[0]), int(values[1]), int(values[2]))
except (ValueError, TypeError):
logger.warn('Ignoring file %s', article_filename)
return date
class Site(object):
"""Represents a Site object.
Args:
root_path (path): The path where articles are stored.
articles (array): contain all articles.
"""
def __init__(self, root_path='articles'):
self.articles = []
self.categories = {}
self.keywords = {}
for root, *_, files in os.walk(root_path):
for file in [file for file in files if file.endswith(".md")]:
self.build_article(root, file)
def build_article(self, filepath, filename):
"""Build a new article from an existing file.
Args:
root_path (str): the path where the file is stored.
filename (str): the filename of the file.
"""
publication_date = get_date_from_article_filename(filename)
if not publication_date:
return
with open(filepath, 'r') as f:
content = f.read()
article = Article(filepath, content, publication_date)
return article
def to_json(self):
"""Serialize the content of the current structure to JSON format."""
json_dumps = json.dumps(self, default=json_handler, sort_keys=True, indent=4)
print('json result: ' + json_dumps)
return json_dumps
def serialize(self):
"""Serialize the current files structure to index.json"""
with open('index.json', 'w') as json_serialized_file:
json_serialized_file.write(self.to_json())

View File

@ -1,3 +1,6 @@
bottle
flake8
pylint
pylint==2.1.1
clize==4.0.3
pytest==3.7.2
pytest-cov==2.5.1
jinja==2.10

5
setup.cfg Normal file
View File

@ -0,0 +1,5 @@
[flake8]
max-line-length=100
[tool:pytest]
addopts = -ra -q

9
templates/base.html Normal file
View File

@ -0,0 +1,9 @@
<!doctype html>
<html>
<head>
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>

6
templates/list.html Normal file
View File

@ -0,0 +1,6 @@
{% extends "base.html" }
{% block content %}
I'm a list.
{% endblock %}

6
templates/single.html Normal file
View File

@ -0,0 +1,6 @@
{% extends "base.html" %}
{% block content %}
I'm an article. I'm called {{ title }}. I was published at {{ published_date }}
{% endblock %}

0
tests/__init__.py Normal file
View File

13
tests/test_models.py Normal file
View File

@ -0,0 +1,13 @@
"""Checks structure associated with articles."""
from datetime import date
from grnx.models import get_date_from_article_filename
def test_article_match_date():
"""Checks that a date can be extracted from a filename."""
assert get_date_from_article_filename('2018-09-01-test.md') == date(2018, 9, 1)
assert get_date_from_article_filename('2017-02-30-divinity-origin-sin.md') == None
assert get_date_from_article_filename('lynis.md') == None