1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
import os
from pathlib import Path
from typing import Dict, List, Optional, Union
import requests
import yaml
from dateutil import parser
from django.conf import settings
from django.http import Http404
from markdown2 import markdown
COMMITS_URL = "https://api.github.com/repos/{owner}/{name}/commits?path={path}&sha={branch}"
BASE_ARTICLES_LOCATION = "pydis_site/apps/content/resources/content/"
def _get_base_path() -> Path:
"""Have extra function for base path getting for testability."""
return Path(settings.BASE_DIR, "pydis_site", "apps", "content", "resources", "content")
def get_category(category: str) -> Dict[str, str]:
"""Load category information by name from _info.yml."""
path = _get_base_path().joinpath(category)
if not path.exists() or not path.is_dir():
raise Http404("Category not found.")
return yaml.safe_load(path.joinpath("_info.yml").read_text())
def get_categories() -> Dict[str, Dict]:
"""Get all categories information."""
base_path = _get_base_path()
categories = {}
for name in base_path.iterdir():
if name.is_dir():
categories[name.name] = get_category(name.name)
return categories
def get_articles(category: Optional[str] = None) -> Dict[str, Dict]:
"""Get all root or category articles."""
if category is None:
base_dir = _get_base_path()
else:
base_dir = _get_base_path().joinpath(category)
articles = {}
for item in base_dir.iterdir():
if item.is_file() and item.name.endswith(".md"):
md = markdown(item.read_text(), extras=["metadata"])
articles[os.path.splitext(item.name)[0]] = md.metadata
return articles
def get_article(article: str, category: Optional[str]) -> Dict[str, Union[str, Dict]]:
"""Get one specific article. When category is specified, get it from there."""
if category is None:
base_path = _get_base_path()
else:
base_path = _get_base_path().joinpath(category)
if not base_path.exists() or not base_path.is_dir():
raise Http404("Category not found.")
article_path = base_path.joinpath(f"{article}.md")
if not article_path.exists() or not article_path.is_file():
raise Http404("Article not found.")
html = markdown(
article_path.read_text(),
extras=[
"metadata",
"fenced-code-blocks",
"header-ids",
"strike",
"target-blank-links",
"tables",
"task_list"
]
)
return {"article": str(html), "metadata": html.metadata}
def get_github_information(
article: str,
category: Optional[str] = None
) -> Dict[str, Union[List[str], str]]:
"""Get article last modified date and contributors from GitHub."""
result = requests.get(
COMMITS_URL.format(
owner=settings.SITE_REPOSITORY_OWNER,
name=settings.SITE_REPOSITORY_NAME,
branch=settings.SITE_REPOSITORY_BRANCH,
path=f"{BASE_ARTICLES_LOCATION}{f'{category}/' if category else ''}{article}.md"
)
)
if result.status_code == 200:
data = result.json()
return {
"last_modified": parser.isoparse(
data[0]["commit"]["committer"]["date"]
).strftime("%dth %B %Y"),
"contributors": {
c["commit"]["committer"]["name"]: c["committer"]["html_url"] for c in data
}
}
else:
return {
"last_modified": "N/A",
"contributors": {}
}
|