write markdown filers parser
This commit is contained in:
parent
6963a34f97
commit
139ebc2c91
|
@ -1,2 +1,6 @@
|
|||
.vuepress
|
||||
node_modules/
|
||||
.vscode
|
||||
.pytest_cache
|
||||
.coverage
|
||||
*.pyc
|
||||
|
|
|
@ -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.
|
|
@ -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,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__))
|
|
@ -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())
|
|
@ -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
|
|
@ -0,0 +1,5 @@
|
|||
[flake8]
|
||||
max-line-length=100
|
||||
|
||||
[tool:pytest]
|
||||
addopts = -ra -q
|
|
@ -0,0 +1,9 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
{% block content %}{% endblock %}
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,6 @@
|
|||
{% extends "base.html" }
|
||||
|
||||
{% block content %}
|
||||
I'm a list.
|
||||
|
||||
{% endblock %}
|
|
@ -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,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
|
Loading…
Reference in New Issue