diff --git a/blag/__init__.py b/blag/__init__.py
index 6527216..318e4f3 100644
--- a/blag/__init__.py
+++ b/blag/__init__.py
@@ -1 +1 @@
-from blag.version import __VERSION__ # noqa
+from blag.version import __VERSION__ as __VERSION__ # noqa
diff --git a/blag/blag.py b/blag/blag.py
index f1c1b1a..8a9ce81 100644
--- a/blag/blag.py
+++ b/blag/blag.py
@@ -6,6 +6,7 @@
# remove when we don't support py38 anymore
from __future__ import annotations
+from typing import Any
import argparse
import os
import shutil
@@ -34,7 +35,7 @@ logging.basicConfig(
)
-def main(arguments: list[str] = None) -> None:
+def main(arguments: list[str] | None = None) -> None:
"""Main entrypoint for the CLI.
This method parses the CLI arguments and executes the respective
@@ -54,7 +55,7 @@ def main(arguments: list[str] = None) -> None:
args.func(args)
-def parse_args(args: list[str] = None) -> argparse.Namespace:
+def parse_args(args: list[str] | None = None) -> argparse.Namespace:
"""Parse command line arguments.
Parameters
@@ -175,8 +176,8 @@ def get_config(configfile: str) -> configparser.SectionProxy:
def environment_factory(
- template_dir: str = None,
- globals_: dict = None,
+ template_dir: str | None = None,
+ globals_: dict[str, object] | None = None,
) -> Environment:
"""Environment factory.
@@ -188,7 +189,7 @@ def environment_factory(
Parameters
----------
template_dir : str
- globals_ : dict
+ globals_ : dict[str, object]
Returns
-------
@@ -278,7 +279,7 @@ def process_markdown(
output_dir: str,
page_template: Template,
article_template: Template,
-) -> tuple[list[tuple[str, dict]], list[tuple[str, dict]]]:
+) -> tuple[list[tuple[str, dict[str, Any]]], list[tuple[str, dict[str, Any]]]]:
"""Process markdown files.
This method processes the convertibles, converts them to html and
@@ -298,7 +299,7 @@ def process_markdown(
Returns
-------
- articles, pages : list[tuple[str, dict]]
+ articles, pages : list[tuple[str, dict[str, Any]]]
"""
logger.info("Converting Markdown files...")
@@ -334,7 +335,7 @@ def process_markdown(
def generate_feed(
- articles: list[tuple[str, dict]],
+ articles: list[tuple[str, dict[str, Any]]],
output_dir: str,
base_url: str,
blog_title: str,
@@ -345,7 +346,7 @@ def generate_feed(
Parameters
----------
- articles : list[tuple[str, dict]]
+ articles : list[tuple[str, dict[str, Any]]]
list of relative output path and article dictionary
output_dir : str
where the feed is stored
@@ -386,7 +387,7 @@ def generate_feed(
def generate_archive(
- articles: list[tuple[str, dict]],
+ articles: list[tuple[str, dict[str, Any]]],
template: Template,
output_dir: str,
) -> None:
@@ -394,7 +395,7 @@ def generate_archive(
Parameters
----------
- articles : list[tuple[str, dict]]
+ articles : list[tuple[str, dict[str, Any]]]
List of articles. Each article has the destination path and a
dictionary with the content.
template : jinja2.Template instance
@@ -413,7 +414,7 @@ def generate_archive(
def generate_tags(
- articles: list[tuple[str, dict]],
+ articles: list[tuple[str, dict[str, Any]]],
tags_template: Template,
tag_template: Template,
output_dir: str,
@@ -422,7 +423,7 @@ def generate_tags(
Parameters
----------
- articles : list[tuple[str, dict]]
+ articles : list[tuple[str, dict[str, Any]]]
List of articles. Each article has the destination path and a
dictionary with the content.
tags_template, tag_template : jinja2.Template instance
@@ -431,11 +432,10 @@ def generate_tags(
"""
logger.info("Generating Tag-pages.")
os.makedirs(f'{output_dir}/tags', exist_ok=True)
-
# get tags number of occurrences
- all_tags: dict = {}
+ all_tags: dict[str, int] = {}
for _, context in articles:
- tags = context.get('tags', [])
+ tags: list[str] = context.get('tags', [])
for tag in tags:
all_tags[tag] = all_tags.get(tag, 0) + 1
# sort by occurrence
@@ -448,17 +448,17 @@ def generate_tags(
fh.write(result)
# get tags and archive per tag
- all_tags = {}
+ all_tags2: dict[str, list[dict[str, Any]]] = {}
for dst, context in articles:
tags = context.get('tags', [])
for tag in tags:
- archive = all_tags.get(tag, [])
+ archive: list[dict[str, Any]] = all_tags2.get(tag, [])
entry = context.copy()
entry['dst'] = dst
archive.append(entry)
- all_tags[tag] = archive
+ all_tags2[tag] = archive
- for tag, archive in all_tags.items():
+ for tag, archive in all_tags2.items():
result = tag_template.render(dict(archive=archive, tag=tag))
with open(f'{output_dir}/tags/{tag}.html', 'w') as fh:
fh.write(result)
diff --git a/blag/markdown.py b/blag/markdown.py
index b71df4b..efe0926 100644
--- a/blag/markdown.py
+++ b/blag/markdown.py
@@ -41,7 +41,10 @@ def markdown_factory() -> Markdown:
return md
-def convert_markdown(md: Markdown, markdown: str) -> tuple[str, dict]:
+def convert_markdown(
+ md: Markdown,
+ markdown: str,
+) -> tuple[str, dict[str, str]]:
"""Convert markdown into html and extract meta data.
Some meta data is treated special:
@@ -56,13 +59,13 @@ def convert_markdown(md: Markdown, markdown: str) -> tuple[str, dict]:
Returns
-------
- str, dict :
+ str, dict[str, str] :
html and metadata
"""
md.reset()
content = md.convert(markdown)
- meta = md.Meta
+ meta = md.Meta # type: ignore
# markdowns metadata consists as list of strings -- one item per
# line. let's convert into single strings.
@@ -90,7 +93,7 @@ class MarkdownLinkTreeprocessor(Treeprocessor):
"""
- def run(self, root: Element):
+ def run(self, root: Element) -> Element:
for element in root.iter():
if element.tag == 'a':
url = element.get('href')
@@ -102,7 +105,7 @@ class MarkdownLinkTreeprocessor(Treeprocessor):
element.set('href', converted)
return root
- def convert(self, url: str):
+ def convert(self, url: str) -> str:
scheme, netloc, path, query, fragment = urlsplit(url)
logger.debug(
f'{url}: {scheme=} {netloc=} {path=} {query=} {fragment=}'
@@ -120,7 +123,7 @@ class MarkdownLinkExtension(Extension):
"""markdown.extension that converts relative .md- to .html-links.
"""
- def extendMarkdown(self, md: Markdown):
+ def extendMarkdown(self, md: Markdown) -> None:
md.treeprocessors.register(
MarkdownLinkTreeprocessor(md), 'mdlink', 0,
)
diff --git a/blag/quickstart.py b/blag/quickstart.py
index dc82380..cbdcaac 100644
--- a/blag/quickstart.py
+++ b/blag/quickstart.py
@@ -32,7 +32,7 @@ def get_input(question: str, default: str) -> str:
return reply
-def quickstart(args: argparse.Namespace) -> None:
+def quickstart(args: argparse.Namespace | None) -> None:
"""Quickstart.
This method asks the user some questions and generates a
diff --git a/setup.cfg b/setup.cfg
index 71030af..94d778c 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -10,6 +10,7 @@ exclude = venv,build,docs
[mypy]
files = blag,tests
+strict = True
[mypy-feedgenerator.*]
ignore_missing_imports = True
diff --git a/tests/conftest.py b/tests/conftest.py
index 221078c..f774841 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -1,13 +1,16 @@
+from argparse import Namespace
+from typing import Iterator, Callable
from tempfile import TemporaryDirectory
import os
import pytest
+from jinja2 import Environment, Template
from blag import blag
@pytest.fixture
-def environment():
+def environment() -> Iterator[Environment]:
site = {
'base_url': 'site base_url',
'title': 'site title',
@@ -19,32 +22,32 @@ def environment():
@pytest.fixture
-def page_template(environment):
+def page_template(environment: Environment) -> Iterator[Template]:
yield environment.get_template('page.html')
@pytest.fixture
-def article_template(environment):
+def article_template(environment: Environment) -> Iterator[Template]:
yield environment.get_template('article.html')
@pytest.fixture
-def archive_template(environment):
+def archive_template(environment: Environment) -> Iterator[Template]:
yield environment.get_template('archive.html')
@pytest.fixture
-def tags_template(environment):
+def tags_template(environment: Environment) -> Iterator[Template]:
yield environment.get_template('tags.html')
@pytest.fixture
-def tag_template(environment):
+def tag_template(environment: Environment) -> Iterator[Template]:
yield environment.get_template('tag.html')
@pytest.fixture
-def cleandir():
+def cleandir() -> Iterator[str]:
"""Create a temporary workind directory and cwd.
"""
@@ -70,14 +73,9 @@ author = a. u. thor
@pytest.fixture
-def args(cleandir):
+def args(cleandir: Callable[[], Iterator[str]]) -> Iterator[Namespace]:
- class NameSpace:
- def __init__(self, **kwargs):
- for name in kwargs:
- setattr(self, name, kwargs[name])
-
- args = NameSpace(
+ args = Namespace(
input_dir='content',
output_dir='build',
static_dir='static',
diff --git a/tests/test_blag.py b/tests/test_blag.py
index eeafbae..d4f40ae 100644
--- a/tests/test_blag.py
+++ b/tests/test_blag.py
@@ -1,37 +1,41 @@
from tempfile import TemporaryDirectory
import os
from datetime import datetime
+from typing import Any
+from argparse import Namespace
import pytest
+from pytest import CaptureFixture, LogCaptureFixture
+from jinja2 import Template
+from blag import __VERSION__
from blag import blag
-def test_generate_feed(cleandir):
- articles = []
+def test_generate_feed(cleandir: str) -> None:
+ articles: list[tuple[str, dict[str, Any]]] = []
blag.generate_feed(articles, 'build', ' ', ' ', ' ', ' ')
assert os.path.exists('build/atom.xml')
-def test_feed(cleandir):
- articles = [
- [
+def test_feed(cleandir: str) -> None:
+ articles: list[tuple[str, dict[str, Any]]] = [
+ (
'dest1.html',
{
'title': 'title1',
'date': datetime(2019, 6, 6),
'content': 'content1',
}
- ],
- [
+ ),
+ (
'dest2.html',
{
'title': 'title2',
'date': datetime(1980, 5, 9),
'content': 'content2',
}
- ],
-
+ ),
]
blag.generate_feed(articles, 'build', 'https://example.com/',
@@ -60,10 +64,10 @@ def test_feed(cleandir):
assert ' None:
# if a description is provided, it will be used as the summary in
# the feed, otherwise we simply use the title of the article
- articles = [[
+ articles: list[tuple[str, dict[str, Any]]] = [(
'dest.html',
{
'title': 'title',
@@ -71,7 +75,7 @@ def test_generate_feed_with_description(cleandir):
'date': datetime(2019, 6, 6),
'content': 'content',
}
- ]]
+ )]
blag.generate_feed(articles, 'build', ' ', ' ', ' ', ' ')
with open('build/atom.xml') as fh:
@@ -83,7 +87,7 @@ def test_generate_feed_with_description(cleandir):
assert 'content' in feed
-def test_parse_args_build():
+def test_parse_args_build() -> None:
# test default args
args = blag.parse_args(['build'])
assert args.input_dir == 'content'
@@ -116,7 +120,7 @@ def test_parse_args_build():
assert args.static_dir == 'foo'
-def test_get_config():
+def test_get_config() -> None:
config = """
[main]
base_url = https://example.com/
@@ -166,8 +170,8 @@ author = a. u. thor
assert config_parsed['base_url'] == 'https://example.com/'
-def test_environment_factory():
- globals_ = {
+def test_environment_factory() -> None:
+ globals_: dict[str, object] = {
'foo': 'bar',
'test': 'me'
}
@@ -176,7 +180,11 @@ def test_environment_factory():
assert env.globals['test'] == 'me'
-def test_process_markdown(cleandir, page_template, article_template):
+def test_process_markdown(
+ cleandir: str,
+ page_template: Template,
+ article_template: Template,
+) -> None:
page1 = """\
title: some page
@@ -202,10 +210,9 @@ foo bar
convertibles = []
for i, txt in enumerate((page1, article1, article2)):
- i = str(i)
- with open(f'content/{i}', 'w') as fh:
+ with open(f'content/{str(i)}', 'w') as fh:
fh.write(txt)
- convertibles.append([i, i])
+ convertibles.append((str(i), str(i)))
articles, pages = blag.process_markdown(
convertibles,
@@ -230,7 +237,7 @@ foo bar
assert 'content' in context
-def test_build(args):
+def test_build(args: Namespace) -> None:
page1 = """\
title: some page
@@ -259,10 +266,9 @@ foo bar
# write some convertibles
convertibles = []
for i, txt in enumerate((page1, article1, article2)):
- i = str(i)
- with open(f'{args.input_dir}/{i}.md', 'w') as fh:
+ with open(f'{args.input_dir}/{str(i)}.md', 'w') as fh:
fh.write(txt)
- convertibles.append([i, i])
+ convertibles.append((str(i), str(i)))
# some static files
with open(f'{args.static_dir}/test', 'w') as fh:
@@ -291,21 +297,21 @@ foo bar
assert os.path.exists(f'{args.output_dir}/tags/bar.html')
-def test_main(cleandir):
+def test_main(cleandir: str) -> None:
blag.main(['build'])
-def test_cli_version(capsys):
+def test_cli_version(capsys: CaptureFixture[str]) -> None:
with pytest.raises(SystemExit) as ex:
blag.main(['--version'])
# normal system exit
assert ex.value.code == 0
# proper version reported
out, _ = capsys.readouterr()
- assert blag.__VERSION__ in out
+ assert __VERSION__ in out
-def test_cli_verbose(cleandir, caplog):
+def test_cli_verbose(cleandir: str, caplog: LogCaptureFixture) -> None:
blag.main(['build'])
assert 'DEBUG' not in caplog.text
diff --git a/tests/test_devserver.py b/tests/test_devserver.py
index 7f56a40..cdbb842 100644
--- a/tests/test_devserver.py
+++ b/tests/test_devserver.py
@@ -1,12 +1,13 @@
import time
import threading
+from argparse import Namespace
import pytest
from blag import devserver
-def test_get_last_modified(cleandir):
+def test_get_last_modified(cleandir: str) -> None:
# take initial time
t1 = devserver.get_last_modified(['content'])
@@ -24,7 +25,7 @@ def test_get_last_modified(cleandir):
assert t2 == t3
-def test_autoreload_builds_immediately(args):
+def test_autoreload_builds_immediately(args: Namespace) -> None:
# create a dummy file that can be build
with open('content/test.md', 'w') as fh:
fh.write('boo')
@@ -45,7 +46,7 @@ def test_autoreload_builds_immediately(args):
@pytest.mark.filterwarnings("ignore::pytest.PytestUnhandledThreadExceptionWarning") # noqa
-def test_autoreload(args):
+def test_autoreload(args: Namespace) -> None:
t = threading.Thread(target=devserver.autoreload,
args=(args, ),
daemon=True,)
diff --git a/tests/test_markdown.py b/tests/test_markdown.py
index 9103ec1..4cee8c2 100644
--- a/tests/test_markdown.py
+++ b/tests/test_markdown.py
@@ -1,4 +1,5 @@
from datetime import datetime
+from typing import Any
import pytest
import markdown
@@ -26,7 +27,7 @@ from blag.markdown import convert_markdown, markdown_factory
('[test][]\n[test]: /a/test.md', '/a/test.html'),
('[test][]\n[test]: /a/test.md "test"', '/a/test.html'),
])
-def test_convert_markdown_links(input_, expected):
+def test_convert_markdown_links(input_: str, expected: str) -> None:
md = markdown_factory()
html, _ = convert_markdown(md, input_)
assert expected in html
@@ -40,7 +41,7 @@ def test_convert_markdown_links(input_, expected):
# no path
('[test]()', ''),
])
-def test_dont_convert_normal_links(input_, expected):
+def test_dont_convert_normal_links(input_: str, expected: str) -> None:
md = markdown_factory()
html, _ = convert_markdown(md, input_)
assert expected in html
@@ -54,18 +55,18 @@ def test_dont_convert_normal_links(input_, expected):
('date: 2020-01-01 12:10', {'date':
datetime(2020, 1, 1, 12, 10).astimezone()}),
])
-def test_convert_metadata(input_, expected):
+def test_convert_metadata(input_: str, expected: dict[str, Any]) -> None:
md = markdown_factory()
_, meta = convert_markdown(md, input_)
assert expected == meta
-def test_markdown_factory():
+def test_markdown_factory() -> None:
md = markdown_factory()
assert isinstance(md, markdown.Markdown)
-def test_smarty():
+def test_smarty() -> None:
md = markdown_factory()
md1 = """
@@ -79,7 +80,7 @@ this --- is -- a test ...
assert 'hellip' in html
-def test_smarty_code():
+def test_smarty_code() -> None:
md = markdown_factory()
md1 = """
diff --git a/tests/test_quickstart.py b/tests/test_quickstart.py
index 4594497..ada2844 100644
--- a/tests/test_quickstart.py
+++ b/tests/test_quickstart.py
@@ -1,19 +1,21 @@
+from pytest import MonkeyPatch
+
from blag.quickstart import get_input, quickstart
-def test_get_input_default_answer(monkeypatch):
+def test_get_input_default_answer(monkeypatch: MonkeyPatch) -> None:
monkeypatch.setattr('builtins.input', lambda x: '')
answer = get_input("foo", "bar")
assert answer == 'bar'
-def test_get_input(monkeypatch):
+def test_get_input(monkeypatch: MonkeyPatch) -> None:
monkeypatch.setattr('builtins.input', lambda x: 'baz')
answer = get_input("foo", "bar")
assert answer == 'baz'
-def test_quickstart(cleandir, monkeypatch):
+def test_quickstart(cleandir: str, monkeypatch: MonkeyPatch) -> None:
monkeypatch.setattr('builtins.input', lambda x: 'foo')
quickstart(None)
with open('config.ini', 'r') as fh:
diff --git a/tests/test_templates.py b/tests/test_templates.py
index e420891..dc3395a 100644
--- a/tests/test_templates.py
+++ b/tests/test_templates.py
@@ -1,7 +1,9 @@
import datetime
+from jinja2 import Template
-def test_page(page_template):
+
+def test_page(page_template: Template) -> None:
ctx = {
'content': 'this is the content',
'title': 'this is the title',
@@ -11,7 +13,7 @@ def test_page(page_template):
assert 'this is the title' in result
-def test_article(article_template):
+def test_article(article_template: Template) -> None:
ctx = {
'content': 'this is the content',
'title': 'this is the title',
@@ -23,7 +25,7 @@ def test_article(article_template):
assert '1980-05-09' in result
-def test_archive(archive_template):
+def test_archive(archive_template: Template) -> None:
entry = {
'title': 'this is a title',
'dst': 'https://example.com/link',
@@ -41,7 +43,7 @@ def test_archive(archive_template):
assert 'https://example.com/link' in result
-def test_tags(tags_template):
+def test_tags(tags_template: Template) -> None:
tags = [('foo', 42)]
ctx = {
'tags': tags,
@@ -54,7 +56,7 @@ def test_tags(tags_template):
assert '42' in result
-def test_tag(tag_template):
+def test_tag(tag_template: Template) -> None:
entry = {
'title': 'this is a title',
'dst': 'https://example.com/link',
diff --git a/tests/test_version.py b/tests/test_version.py
index 04f8d9a..d978f67 100644
--- a/tests/test_version.py
+++ b/tests/test_version.py
@@ -1,5 +1,5 @@
import blag
-def test_version():
+def test_version() -> None:
assert isinstance(blag.__VERSION__, str)