Date: Tue, 23 Mar 2021 16:00:07 +0800
Subject: Style tag backgrounds same as .
This makes it consistent with the django-wiki version of the code
blocks, which looks neater.
---
pydis_site/static/css/content/articles.css | 9 +++++++++
1 file changed, 9 insertions(+)
(limited to 'pydis_site')
diff --git a/pydis_site/static/css/content/articles.css b/pydis_site/static/css/content/articles.css
index fa7a0ba5..f46d6b15 100644
--- a/pydis_site/static/css/content/articles.css
+++ b/pydis_site/static/css/content/articles.css
@@ -5,3 +5,12 @@
i.has-icon-padding {
padding: 0 10px 25px 0;
}
+
+pre {
+ /*
+ * Style it the same as the tag, since highlight.js does not style
+ * backgrounds of tags but bulma does, resulting in a weird off-white
+ * border.
+ */
+ background-color: #282c34;
+}
--
cgit v1.2.3
From 7de2959402a048652bf6d4ec8e3bec1172bb11e8 Mon Sep 17 00:00:00 2001
From: kosayoda
Date: Tue, 23 Mar 2021 17:17:22 +0800
Subject: Remove Github metadata feature.
This feature is still under implementation debate, so it will be further
discussed in another issue and implemeneted in a future PR.
---
Pipfile | 1 -
Pipfile.lock | 503 ++++++++++++----------
pydis_site/apps/content/tests/test_utils.py | 40 --
pydis_site/apps/content/tests/test_views.py | 10 +-
pydis_site/apps/content/utils.py | 38 --
pydis_site/apps/content/views/article_category.py | 1 -
pydis_site/templates/content/article.html | 18 -
7 files changed, 283 insertions(+), 328 deletions(-)
(limited to 'pydis_site')
diff --git a/Pipfile b/Pipfile
index dae75ea0..8af6e3ce 100644
--- a/Pipfile
+++ b/Pipfile
@@ -19,7 +19,6 @@ pyuwsgi = {version = "~=2.0", sys_platform = "!='win32'"}
sentry-sdk = "~=0.14"
gitpython = "~=3.1.7"
markdown2 = "~=2.3.9"
-python-dateutil = "~=2.8.1"
[dev-packages]
coverage = "~=5.0"
diff --git a/Pipfile.lock b/Pipfile.lock
index 18b0d582..3dfb7ec6 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
- "sha256": "c0e53fd7b7c3d2fc62331078d4ba9301a7e848cd39ec8b41f0f7bc6d911a4d88"
+ "sha256": "893ab5cc0b64f7bb87c0304c9fb6eb24b1856c40286fbbdb1a2bf4a0d7a6d39f"
},
"pipfile-spec": 6,
"requires": {
@@ -18,33 +18,34 @@
"default": {
"asgiref": {
"hashes": [
- "sha256:a5098bc870b80e7b872bff60bb363c7f2c2c89078759f6c47b53ff8c525a152e",
- "sha256:cd88907ecaec59d78e4ac00ea665b03e571cb37e3a0e37b3702af1a9e86c365a"
+ "sha256:5ee950735509d04eb673bd7f7120f8fa1c9e2df495394992c73234d526907e17",
+ "sha256:7162a3cb30ab0609f1a4c95938fd73e8604f63bdba516a7f7d64b83ff09478f0"
],
"markers": "python_version >= '3.5'",
- "version": "==3.3.0"
+ "version": "==3.3.1"
},
"certifi": {
"hashes": [
- "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3",
- "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41"
+ "sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c",
+ "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830"
],
- "version": "==2020.6.20"
+ "version": "==2020.12.5"
},
"chardet": {
"hashes": [
- "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
- "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
+ "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa",
+ "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5"
],
- "version": "==3.0.4"
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
+ "version": "==4.0.0"
},
"django": {
"hashes": [
- "sha256:2d14be521c3ae24960e5e83d4575e156a8c479a75c935224b671b1c6e66eddaf",
- "sha256:313d0b8f96685e99327785cc600a5178ca855f8e6f4ed162e671e8c3cf749739"
+ "sha256:2afe4900667bcceac792fa34b4fb25448c4fd950d8b32c5508b3442c4b10442a",
+ "sha256:6f13c3e8109236129c49d65a42fbf30c928e66b05ca6862246061b9343ecbaf2"
],
"index": "pypi",
- "version": "==3.0.10"
+ "version": "==3.0.13"
},
"django-environ": {
"hashes": [
@@ -103,11 +104,11 @@
},
"gitpython": {
"hashes": [
- "sha256:6eea89b655917b500437e9668e4a12eabdcf00229a0df1762aabd692ef9b746b",
- "sha256:befa4d101f91bad1b632df4308ec64555db684c360bd7d2130b4807d49ce86b8"
+ "sha256:3283ae2fba31c913d857e12e5ba5f9a7772bbc064ae2bb09efafa71b0dd4939b",
+ "sha256:be27633e7509e58391f10207cd32b2a6cf5b908f92d9cd30da2e514e1137af61"
],
"index": "pypi",
- "version": "==3.1.11"
+ "version": "==3.1.14"
},
"idna": {
"hashes": [
@@ -145,61 +146,56 @@
},
"psycopg2-binary": {
"hashes": [
- "sha256:42ec1035841b389e8cc3692277a0bd81cdfe0b65d575a2c8862cec7a80e62e52",
+ "sha256:0deac2af1a587ae12836aa07970f5cb91964f05a7c6cdb69d8425ff4c15d4e2c",
+ "sha256:0e4dc3d5996760104746e6cfcdb519d9d2cd27c738296525d5867ea695774e67",
"sha256:11b9c0ebce097180129e422379b824ae21c8f2a6596b159c7659e2e5a00e1aa0",
- "sha256:bd1be66dde2b82f80afb9459fc618216753f67109b859a361cf7def5c7968729",
- "sha256:d5227b229005a696cc67676e24c214740efd90b148de5733419ac9aaba3773da",
+ "sha256:15978a1fbd225583dd8cdaf37e67ccc278b5abecb4caf6b2d6b8e2b948e953f6",
+ "sha256:1fabed9ea2acc4efe4671b92c669a213db744d2af8a9fc5d69a8e9bc14b7a9db",
"sha256:2dac98e85565d5688e8ab7bdea5446674a83a3945a8f416ad0110018d1501b94",
- "sha256:e74a55f6bad0e7d3968399deb50f61f4db1926acf4a6d83beaaa7df986f48b1c",
- "sha256:b4afc542c0ac0db720cf516dd20c0846f71c248d2b3d21013aa0d4ef9c71ca25",
- "sha256:ad20d2eb875aaa1ea6d0f2916949f5c08a19c74d05b16ce6ebf6d24f2c9f75d1",
- "sha256:a0eb43a07386c3f1f1ebb4dc7aafb13f67188eab896e7397aa1ee95a9c884eb2",
+ "sha256:42ec1035841b389e8cc3692277a0bd81cdfe0b65d575a2c8862cec7a80e62e52",
+ "sha256:6422f2ff0919fd720195f64ffd8f924c1395d30f9a495f31e2392c2efafb5056",
+ "sha256:6a32f3a4cb2f6e1a0b15215f448e8ce2da192fd4ff35084d80d5e39da683e79b",
+ "sha256:7312e931b90fe14f925729cde58022f5d034241918a5c4f9797cac62f6b3a9dd",
+ "sha256:7d92a09b788cbb1aec325af5fcba9fed7203897bbd9269d5691bb1e3bce29550",
+ "sha256:833709a5c66ca52f1d21d41865a637223b368c0ee76ea54ca5bad6f2526c7679",
"sha256:89705f45ce07b2dfa806ee84439ec67c5d9a0ef20154e0e475e2b2ed392a5b83",
- "sha256:c2507d796fca339c8fb03216364cca68d87e037c1f774977c8fc377627d01c71",
+ "sha256:8cd0fb36c7412996859cb4606a35969dd01f4ea34d9812a141cd920c3b18be77",
+ "sha256:950bc22bb56ee6ff142a2cb9ee980b571dd0912b0334aa3fe0fe3788d860bea2",
+ "sha256:a0c50db33c32594305b0ef9abc0cb7db13de7621d2cadf8392a1d9b3c437ef77",
+ "sha256:a0eb43a07386c3f1f1ebb4dc7aafb13f67188eab896e7397aa1ee95a9c884eb2",
"sha256:aaa4213c862f0ef00022751161df35804127b78adf4a2755b9f991a507e425fd",
- "sha256:7312e931b90fe14f925729cde58022f5d034241918a5c4f9797cac62f6b3a9dd",
"sha256:ac0c682111fbf404525dfc0f18a8b5f11be52657d4f96e9fcb75daf4f3984859",
+ "sha256:ad20d2eb875aaa1ea6d0f2916949f5c08a19c74d05b16ce6ebf6d24f2c9f75d1",
+ "sha256:b4afc542c0ac0db720cf516dd20c0846f71c248d2b3d21013aa0d4ef9c71ca25",
+ "sha256:b8a3715b3c4e604bcc94c90a825cd7f5635417453b253499664f784fc4da0152",
+ "sha256:ba28584e6bca48c59eecbf7efb1576ca214b47f05194646b081717fa628dfddf",
+ "sha256:ba381aec3a5dc29634f20692349d73f2d21f17653bda1decf0b52b11d694541f",
+ "sha256:bd1be66dde2b82f80afb9459fc618216753f67109b859a361cf7def5c7968729",
+ "sha256:c2507d796fca339c8fb03216364cca68d87e037c1f774977c8fc377627d01c71",
"sha256:cec7e622ebc545dbb4564e483dd20e4e404da17ae07e06f3e780b2dacd5cee66",
- "sha256:8cd0fb36c7412996859cb4606a35969dd01f4ea34d9812a141cd920c3b18be77",
- "sha256:f5ab93a2cb2d8338b1674be43b442a7f544a0971da062a5da774ed40587f18f5",
"sha256:d14b140a4439d816e3b1229a4a525df917d6ea22a0771a2a78332273fd9528a4",
- "sha256:0deac2af1a587ae12836aa07970f5cb91964f05a7c6cdb69d8425ff4c15d4e2c",
- "sha256:6a32f3a4cb2f6e1a0b15215f448e8ce2da192fd4ff35084d80d5e39da683e79b",
"sha256:d1b4ab59e02d9008efe10ceabd0b31e79519da6fb67f7d8e8977118832d0f449",
- "sha256:ee69dad2c7155756ad114c02db06002f4cded41132cc51378e57aad79cc8e4f4",
- "sha256:b8a3715b3c4e604bcc94c90a825cd7f5635417453b253499664f784fc4da0152",
- "sha256:ba381aec3a5dc29634f20692349d73f2d21f17653bda1decf0b52b11d694541f",
- "sha256:a0c50db33c32594305b0ef9abc0cb7db13de7621d2cadf8392a1d9b3c437ef77",
- "sha256:7d92a09b788cbb1aec325af5fcba9fed7203897bbd9269d5691bb1e3bce29550",
- "sha256:950bc22bb56ee6ff142a2cb9ee980b571dd0912b0334aa3fe0fe3788d860bea2",
- "sha256:ba28584e6bca48c59eecbf7efb1576ca214b47f05194646b081717fa628dfddf",
- "sha256:e82aba2188b9ba309fd8e271702bd0d0fc9148ae3150532bbb474f4590039ffb",
- "sha256:0e4dc3d5996760104746e6cfcdb519d9d2cd27c738296525d5867ea695774e67",
- "sha256:1fabed9ea2acc4efe4671b92c669a213db744d2af8a9fc5d69a8e9bc14b7a9db",
+ "sha256:d5227b229005a696cc67676e24c214740efd90b148de5733419ac9aaba3773da",
"sha256:e1f57aa70d3f7cc6947fd88636a481638263ba04a742b4a37dd25c373e41491a",
- "sha256:833709a5c66ca52f1d21d41865a637223b368c0ee76ea54ca5bad6f2526c7679"
+ "sha256:e74a55f6bad0e7d3968399deb50f61f4db1926acf4a6d83beaaa7df986f48b1c",
+ "sha256:e82aba2188b9ba309fd8e271702bd0d0fc9148ae3150532bbb474f4590039ffb",
+ "sha256:ee69dad2c7155756ad114c02db06002f4cded41132cc51378e57aad79cc8e4f4",
+ "sha256:f5ab93a2cb2d8338b1674be43b442a7f544a0971da062a5da774ed40587f18f5"
],
"index": "pypi",
"version": "==2.8.6"
},
- "python-dateutil": {
- "hashes": [
- "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c",
- "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"
- ],
- "index": "pypi",
- "version": "==2.8.1"
- },
"pytz": {
"hashes": [
- "sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed",
- "sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048"
+ "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da",
+ "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"
],
- "version": "==2020.1"
+ "version": "==2021.1"
},
"pyuwsgi": {
"hashes": [
"sha256:0bd14517398f494d828d77a9bf72b5a6cbef0112e1cc05e9a0080fa8828ccfa0",
+ "sha256:149675b2e020b0e833e8b871a545751ca346cbfed85c8fd2b320a01d40dc3d8f",
"sha256:285e263a9094389f13cfdefd033a4e99fbed3ad120dba9ac5093846cc03ac5ab",
"sha256:297d1d0b8c472374b12eda7f17a9f5de67cf516612e42b71a7636afb9d1e3974",
"sha256:5439f0f3ef5d6bf1622f341662d04c1d92b88889db40b295419e5fe75a7c7d45",
@@ -209,6 +205,7 @@
"sha256:90e4235020048456ad867aefc383cdf5528b7f6e327555ceec579c428a828759",
"sha256:94d4287b155aa789ce4b6f671c981f7d6c58fc3113330e2f29ac7926cb854645",
"sha256:a425f562f382a097ca49df26b70d47d12f0cf0abf233610f3f58b1f7f780355e",
+ "sha256:ac79dead0685beab5ecfe0926426849a44c5572528f89bb17f6ecf5eb561024e",
"sha256:bddeb8df77010d0f842068765a0b3155fdcfd847f14bc1ba89fc7e37914a13d2",
"sha256:dac4a04dc0f69d641dba984e83214d2c2cc098496c5d5585e7d3f4e7a9190f84"
],
@@ -218,36 +215,54 @@
},
"pyyaml": {
"hashes": [
- "sha256:06a0d7ba600ce0b2d2fe2e78453a470b5a6e000a985dd4a4e54e436cc36b0e97",
- "sha256:240097ff019d7c70a4922b6869d8a86407758333f02203e0fc6ff79c5dcede76",
- "sha256:4f4b913ca1a7319b33cfb1369e91e50354d6f07a135f3b901aca02aa95940bd2",
- "sha256:69f00dca373f240f842b2931fb2c7e14ddbacd1397d57157a9b005a6a9942648",
- "sha256:73f099454b799e05e5ab51423c7bcf361c58d3206fa7b0d555426b1f4d9a3eaf",
- "sha256:74809a57b329d6cc0fdccee6318f44b9b8649961fa73144a98735b0aaf029f1f",
- "sha256:7739fc0fa8205b3ee8808aea45e968bc90082c10aef6ea95e855e10abf4a37b2",
- "sha256:95f71d2af0ff4227885f7a6605c37fd53d3a106fcab511b8860ecca9fcf400ee",
- "sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d",
- "sha256:cc8955cfbfc7a115fa81d85284ee61147059a753344bc51098f3ccd69b0d7e0c",
- "sha256:d13155f591e6fcc1ec3b30685d50bf0711574e2c0dfffd7644babf8b5102ca1a"
- ],
- "index": "pypi",
- "version": "==5.3.1"
+ "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf",
+ "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696",
+ "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393",
+ "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77",
+ "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922",
+ "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5",
+ "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8",
+ "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10",
+ "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc",
+ "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018",
+ "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e",
+ "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253",
+ "sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347",
+ "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183",
+ "sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541",
+ "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb",
+ "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185",
+ "sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc",
+ "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db",
+ "sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa",
+ "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46",
+ "sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122",
+ "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b",
+ "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63",
+ "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df",
+ "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc",
+ "sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247",
+ "sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6",
+ "sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0"
+ ],
+ "index": "pypi",
+ "version": "==5.4.1"
},
"requests": {
"hashes": [
- "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b",
- "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898"
+ "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804",
+ "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e"
],
"index": "pypi",
- "version": "==2.24.0"
+ "version": "==2.25.1"
},
"sentry-sdk": {
"hashes": [
- "sha256:0eea248408d36e8e7037c7b73827bea20b13a4375bf1719c406cae6fcbc094e3",
- "sha256:5cf36eb6b1dc62d55f3c64289792cbaebc8ffa5a9da14474f49b46d20caa7fc8"
+ "sha256:4ae8d1ced6c67f1c8ea51d82a16721c166c489b76876c9f2c202b8a50334b237",
+ "sha256:e75c8c58932bda8cd293ea8e4b242527129e1caaec91433d21b8b2f20fee030b"
],
"index": "pypi",
- "version": "==0.19.1"
+ "version": "==0.20.3"
},
"six": {
"hashes": [
@@ -259,11 +274,11 @@
},
"smmap": {
"hashes": [
- "sha256:54c44c197c819d5ef1991799a7e30b662d1e520f2ac75c9efbeb54a742214cf4",
- "sha256:9c98bbd1f9786d22f14b3d4126894d56befb835ec90cef151af566c7e19b5d24"
+ "sha256:7bfcf367828031dc893530a29cb35eb8c8f2d7c8f2d0989354d75d24c8573714",
+ "sha256:84c2751ef3072d4f6b2785ec7ee40244c6f45eb934d9e543e2c51f1bd3d54c50"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
- "version": "==3.0.4"
+ "version": "==3.0.5"
},
"sqlparse": {
"hashes": [
@@ -275,11 +290,11 @@
},
"urllib3": {
"hashes": [
- "sha256:8d7eaa5a82a1cac232164990f04874c594c9453ec55eef02eab885aa02fc17a2",
- "sha256:f5321fbe4bf3fefa0efd0bfe7fb14e90909eb62a48ccda331726b4319897dd5e"
+ "sha256:2f4da4594db7e1e110a944bb1b551fdf4e6c136ad42e4234131391e21eb5b0df",
+ "sha256:e7b021f7241115872f92f43c6508082facffbd1c048e3c6e2bb9c2a157e28937"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'",
- "version": "==1.25.11"
+ "version": "==1.26.4"
},
"whitenoise": {
"hashes": [
@@ -300,18 +315,18 @@
},
"attrs": {
"hashes": [
- "sha256:26b54ddbbb9ee1d34d5d3668dd37d6cf74990ab23c828c2888dccdceee395594",
- "sha256:fce7fc47dfc976152e82d53ff92fa0407700c21acd20886a13777a0d20e655dc"
+ "sha256:31b2eced602aa8423c2aea9c76a724617ed67cf9513173fd3a4f03e3a929c7e6",
+ "sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
- "version": "==20.2.0"
+ "version": "==20.3.0"
},
"bandit": {
"hashes": [
- "sha256:336620e220cf2d3115877685e264477ff9d9abaeb0afe3dc7264f55fa17a3952",
- "sha256:41e75315853507aa145d62a78a2a6c5e3240fe14ee7c601459d0df9418196065"
+ "sha256:216be4d044209fa06cf2a3e51b319769a51be8318140659719aa7a115c35ed07",
+ "sha256:8a4c7415254d75df8ff3c3b15cfe9042ecee628a1e40b44c15a98890fbfc2608"
],
- "version": "==1.6.2"
+ "version": "==1.7.0"
},
"cfgv": {
"hashes": [
@@ -323,43 +338,61 @@
},
"coverage": {
"hashes": [
- "sha256:0203acd33d2298e19b57451ebb0bed0ab0c602e5cf5a818591b4918b1f97d516",
- "sha256:0f313707cdecd5cd3e217fc68c78a960b616604b559e9ea60cc16795c4304259",
- "sha256:1c6703094c81fa55b816f5ae542c6ffc625fec769f22b053adb42ad712d086c9",
- "sha256:1d44bb3a652fed01f1f2c10d5477956116e9b391320c94d36c6bf13b088a1097",
- "sha256:280baa8ec489c4f542f8940f9c4c2181f0306a8ee1a54eceba071a449fb870a0",
- "sha256:29a6272fec10623fcbe158fdf9abc7a5fa032048ac1d8631f14b50fbfc10d17f",
- "sha256:2b31f46bf7b31e6aa690d4c7a3d51bb262438c6dcb0d528adde446531d0d3bb7",
- "sha256:2d43af2be93ffbad25dd959899b5b809618a496926146ce98ee0b23683f8c51c",
- "sha256:381ead10b9b9af5f64646cd27107fb27b614ee7040bb1226f9c07ba96625cbb5",
- "sha256:47a11bdbd8ada9b7ee628596f9d97fbd3851bd9999d398e9436bd67376dbece7",
- "sha256:4d6a42744139a7fa5b46a264874a781e8694bb32f1d76d8137b68138686f1729",
- "sha256:50691e744714856f03a86df3e2bff847c2acede4c191f9a1da38f088df342978",
- "sha256:530cc8aaf11cc2ac7430f3614b04645662ef20c348dce4167c22d99bec3480e9",
- "sha256:582ddfbe712025448206a5bc45855d16c2e491c2dd102ee9a2841418ac1c629f",
- "sha256:63808c30b41f3bbf65e29f7280bf793c79f54fb807057de7e5238ffc7cc4d7b9",
- "sha256:71b69bd716698fa62cd97137d6f2fdf49f534decb23a2c6fc80813e8b7be6822",
- "sha256:7858847f2d84bf6e64c7f66498e851c54de8ea06a6f96a32a1d192d846734418",
- "sha256:78e93cc3571fd928a39c0b26767c986188a4118edc67bc0695bc7a284da22e82",
- "sha256:7f43286f13d91a34fadf61ae252a51a130223c52bfefb50310d5b2deb062cf0f",
- "sha256:86e9f8cd4b0cdd57b4ae71a9c186717daa4c5a99f3238a8723f416256e0b064d",
- "sha256:8f264ba2701b8c9f815b272ad568d555ef98dfe1576802ab3149c3629a9f2221",
- "sha256:9342dd70a1e151684727c9c91ea003b2fb33523bf19385d4554f7897ca0141d4",
- "sha256:9361de40701666b034c59ad9e317bae95c973b9ff92513dd0eced11c6adf2e21",
- "sha256:9669179786254a2e7e57f0ecf224e978471491d660aaca833f845b72a2df3709",
- "sha256:aac1ba0a253e17889550ddb1b60a2063f7474155465577caa2a3b131224cfd54",
- "sha256:aef72eae10b5e3116bac6957de1df4d75909fc76d1499a53fb6387434b6bcd8d",
- "sha256:bd3166bb3b111e76a4f8e2980fa1addf2920a4ca9b2b8ca36a3bc3dedc618270",
- "sha256:c1b78fb9700fc961f53386ad2fd86d87091e06ede5d118b8a50dea285a071c24",
- "sha256:c3888a051226e676e383de03bf49eb633cd39fc829516e5334e69b8d81aae751",
- "sha256:c5f17ad25d2c1286436761b462e22b5020d83316f8e8fcb5deb2b3151f8f1d3a",
- "sha256:c851b35fc078389bc16b915a0a7c1d5923e12e2c5aeec58c52f4aa8085ac8237",
- "sha256:cb7df71de0af56000115eafd000b867d1261f786b5eebd88a0ca6360cccfaca7",
- "sha256:cedb2f9e1f990918ea061f28a0f0077a07702e3819602d3507e2ff98c8d20636",
- "sha256:e8caf961e1b1a945db76f1b5fa9c91498d15f545ac0ababbe575cfab185d3bd8"
- ],
- "index": "pypi",
- "version": "==5.3"
+ "sha256:004d1880bed2d97151facef49f08e255a20ceb6f9432df75f4eef018fdd5a78c",
+ "sha256:01d84219b5cdbfc8122223b39a954820929497a1cb1422824bb86b07b74594b6",
+ "sha256:040af6c32813fa3eae5305d53f18875bedd079960822ef8ec067a66dd8afcd45",
+ "sha256:06191eb60f8d8a5bc046f3799f8a07a2d7aefb9504b0209aff0b47298333302a",
+ "sha256:13034c4409db851670bc9acd836243aeee299949bd5673e11844befcb0149f03",
+ "sha256:13c4ee887eca0f4c5a247b75398d4114c37882658300e153113dafb1d76de529",
+ "sha256:184a47bbe0aa6400ed2d41d8e9ed868b8205046518c52464fde713ea06e3a74a",
+ "sha256:18ba8bbede96a2c3dde7b868de9dcbd55670690af0988713f0603f037848418a",
+ "sha256:1aa846f56c3d49205c952d8318e76ccc2ae23303351d9270ab220004c580cfe2",
+ "sha256:217658ec7187497e3f3ebd901afdca1af062b42cfe3e0dafea4cced3983739f6",
+ "sha256:24d4a7de75446be83244eabbff746d66b9240ae020ced65d060815fac3423759",
+ "sha256:2910f4d36a6a9b4214bb7038d537f015346f413a975d57ca6b43bf23d6563b53",
+ "sha256:2949cad1c5208b8298d5686d5a85b66aae46d73eec2c3e08c817dd3513e5848a",
+ "sha256:2a3859cb82dcbda1cfd3e6f71c27081d18aa251d20a17d87d26d4cd216fb0af4",
+ "sha256:2cafbbb3af0733db200c9b5f798d18953b1a304d3f86a938367de1567f4b5bff",
+ "sha256:2e0d881ad471768bf6e6c2bf905d183543f10098e3b3640fc029509530091502",
+ "sha256:30c77c1dc9f253283e34c27935fded5015f7d1abe83bc7821680ac444eaf7793",
+ "sha256:3487286bc29a5aa4b93a072e9592f22254291ce96a9fbc5251f566b6b7343cdb",
+ "sha256:372da284cfd642d8e08ef606917846fa2ee350f64994bebfbd3afb0040436905",
+ "sha256:41179b8a845742d1eb60449bdb2992196e211341818565abded11cfa90efb821",
+ "sha256:44d654437b8ddd9eee7d1eaee28b7219bec228520ff809af170488fd2fed3e2b",
+ "sha256:4a7697d8cb0f27399b0e393c0b90f0f1e40c82023ea4d45d22bce7032a5d7b81",
+ "sha256:51cb9476a3987c8967ebab3f0fe144819781fca264f57f89760037a2ea191cb0",
+ "sha256:52596d3d0e8bdf3af43db3e9ba8dcdaac724ba7b5ca3f6358529d56f7a166f8b",
+ "sha256:53194af30d5bad77fcba80e23a1441c71abfb3e01192034f8246e0d8f99528f3",
+ "sha256:5fec2d43a2cc6965edc0bb9e83e1e4b557f76f843a77a2496cbe719583ce8184",
+ "sha256:6c90e11318f0d3c436a42409f2749ee1a115cd8b067d7f14c148f1ce5574d701",
+ "sha256:74d881fc777ebb11c63736622b60cb9e4aee5cace591ce274fb69e582a12a61a",
+ "sha256:7501140f755b725495941b43347ba8a2777407fc7f250d4f5a7d2a1050ba8e82",
+ "sha256:796c9c3c79747146ebd278dbe1e5c5c05dd6b10cc3bcb8389dfdf844f3ead638",
+ "sha256:869a64f53488f40fa5b5b9dcb9e9b2962a66a87dab37790f3fcfb5144b996ef5",
+ "sha256:8963a499849a1fc54b35b1c9f162f4108017b2e6db2c46c1bed93a72262ed083",
+ "sha256:8d0a0725ad7c1a0bcd8d1b437e191107d457e2ec1084b9f190630a4fb1af78e6",
+ "sha256:900fbf7759501bc7807fd6638c947d7a831fc9fdf742dc10f02956ff7220fa90",
+ "sha256:92b017ce34b68a7d67bd6d117e6d443a9bf63a2ecf8567bb3d8c6c7bc5014465",
+ "sha256:970284a88b99673ccb2e4e334cfb38a10aab7cd44f7457564d11898a74b62d0a",
+ "sha256:972c85d205b51e30e59525694670de6a8a89691186012535f9d7dbaa230e42c3",
+ "sha256:9a1ef3b66e38ef8618ce5fdc7bea3d9f45f3624e2a66295eea5e57966c85909e",
+ "sha256:af0e781009aaf59e25c5a678122391cb0f345ac0ec272c7961dc5455e1c40066",
+ "sha256:b6d534e4b2ab35c9f93f46229363e17f63c53ad01330df9f2d6bd1187e5eaacf",
+ "sha256:b7895207b4c843c76a25ab8c1e866261bcfe27bfaa20c192de5190121770672b",
+ "sha256:c0891a6a97b09c1f3e073a890514d5012eb256845c451bd48f7968ef939bf4ae",
+ "sha256:c2723d347ab06e7ddad1a58b2a821218239249a9e4365eaff6649d31180c1669",
+ "sha256:d1f8bf7b90ba55699b3a5e44930e93ff0189aa27186e96071fac7dd0d06a1873",
+ "sha256:d1f9ce122f83b2305592c11d64f181b87153fc2c2bbd3bb4a3dde8303cfb1a6b",
+ "sha256:d314ed732c25d29775e84a960c3c60808b682c08d86602ec2c3008e1202e3bb6",
+ "sha256:d636598c8305e1f90b439dbf4f66437de4a5e3c31fdf47ad29542478c8508bbb",
+ "sha256:deee1077aae10d8fa88cb02c845cfba9b62c55e1183f52f6ae6a2df6a2187160",
+ "sha256:ebe78fe9a0e874362175b02371bdfbee64d8edc42a044253ddf4ee7d3c15212c",
+ "sha256:f030f8873312a16414c0d8e1a1ddff2d3235655a2174e3648b4fa66b3f2f1079",
+ "sha256:f0b278ce10936db1a37e6954e15a3730bea96a0997c26d7fee88e6c396c2086d",
+ "sha256:f11642dddbb0253cc8853254301b51390ba0081750a8ac03f20ea8103f0c56b6"
+ ],
+ "index": "pypi",
+ "version": "==5.5"
},
"distlib": {
"hashes": [
@@ -377,19 +410,19 @@
},
"flake8": {
"hashes": [
- "sha256:749dbbd6bfd0cf1318af27bf97a14e28e5ff548ef8e5b1566ccfb25a11e7c839",
- "sha256:aadae8761ec651813c24be05c6f7b4680857ef6afaae4651a4eccaef97ce6c3b"
+ "sha256:12d05ab02614b6aee8df7c36b97d1a3b2372761222b19b58621355e82acddcff",
+ "sha256:78873e372b12b093da7b5e5ed302e8ad9e988b38b063b61ad937f26ca58fc5f0"
],
"index": "pypi",
- "version": "==3.8.4"
+ "version": "==3.9.0"
},
"flake8-annotations": {
"hashes": [
- "sha256:0bcebb0792f1f96d617ded674dca7bf64181870bfe5dace353a1483551f8e5f1",
- "sha256:bebd11a850f6987a943ce8cdff4159767e0f5f89b3c88aca64680c2175ee02df"
+ "sha256:40a4d504cdf64126ea0bdca39edab1608bc6d515e96569b7e7c3c59c84f66c36",
+ "sha256:eabbfb2dd59ae0e9835f509f930e79cd99fa4ff1026fe6ca073503a57407037c"
],
"index": "pypi",
- "version": "==2.4.1"
+ "version": "==2.6.1"
},
"flake8-bandit": {
"hashes": [
@@ -400,19 +433,19 @@
},
"flake8-bugbear": {
"hashes": [
- "sha256:a3ddc03ec28ba2296fc6f89444d1c946a6b76460f859795b35b77d4920a51b63",
- "sha256:bd02e4b009fb153fe6072c31c52aeab5b133d508095befb2ffcf3b41c4823162"
+ "sha256:528020129fea2dea33a466b9d64ab650aa3e5f9ffc788b70ea4bc6cf18283538",
+ "sha256:f35b8135ece7a014bc0aee5b5d485334ac30a6da48494998cc1fabf7ec70d703"
],
"index": "pypi",
- "version": "==20.1.4"
+ "version": "==20.11.1"
},
"flake8-docstrings": {
"hashes": [
- "sha256:3d5a31c7ec6b7367ea6506a87ec293b94a0a46c0bce2bb4975b7f1d09b6f3717",
- "sha256:a256ba91bc52307bef1de59e2a009c3cf61c3d0952dbe035d6ff7208940c2edc"
+ "sha256:99cac583d6c7e32dd28bbfbef120a7c0d1b6dde4adb5a9fd441c4227a6534bde",
+ "sha256:9fe7c6a306064af8e62a055c2f61e9eb1da55f84bb39caef2b84ce53708ac34b"
],
"index": "pypi",
- "version": "==1.5.0"
+ "version": "==1.6.0"
},
"flake8-import-order": {
"hashes": [
@@ -439,11 +472,11 @@
},
"flake8-tidy-imports": {
"hashes": [
- "sha256:62059ca07d8a4926b561d392cbab7f09ee042350214a25cf12823384a45d27dd",
- "sha256:c30b40337a2e6802ba3bb611c26611154a27e94c53fc45639e3e282169574fd3"
+ "sha256:52e5f2f987d3d5597538d5941153409ebcab571635835b78f522c7bf03ca23bc",
+ "sha256:76e36fbbfdc8e3c5017f9a216c2855a298be85bc0631e66777f4e6a07a859dc4"
],
"index": "pypi",
- "version": "==4.1.0"
+ "version": "==4.2.1"
},
"flake8-todo": {
"hashes": [
@@ -462,27 +495,27 @@
},
"gitpython": {
"hashes": [
- "sha256:6eea89b655917b500437e9668e4a12eabdcf00229a0df1762aabd692ef9b746b",
- "sha256:befa4d101f91bad1b632df4308ec64555db684c360bd7d2130b4807d49ce86b8"
+ "sha256:3283ae2fba31c913d857e12e5ba5f9a7772bbc064ae2bb09efafa71b0dd4939b",
+ "sha256:be27633e7509e58391f10207cd32b2a6cf5b908f92d9cd30da2e514e1137af61"
],
"index": "pypi",
- "version": "==3.1.11"
+ "version": "==3.1.14"
},
"identify": {
"hashes": [
- "sha256:3139bf72d81dfd785b0a464e2776bd59bdc725b4cc10e6cf46b56a0db931c82e",
- "sha256:969d844b7a85d32a5f9ac4e163df6e846d73c87c8b75847494ee8f4bd2186421"
+ "sha256:39c0b110c9d0cd2391b6c38cd0ff679ee4b4e98f8db8b06c5d9d9e502711a1e1",
+ "sha256:efbf090a619255bc31c4fbba709e2805f7d30913fd4854ad84ace52bd276e2f6"
],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
- "version": "==1.5.6"
+ "markers": "python_full_version >= '3.6.1'",
+ "version": "==2.2.0"
},
"importlib-metadata": {
"hashes": [
- "sha256:77a540690e24b0305878c37ffd421785a6f7e53c8b5720d211b211de8d0e95da",
- "sha256:cefa1a2f919b866c5beb7c9f7b0ebb4061f30a8a9bf16d609b000e2dfaceb9c3"
+ "sha256:742add720a20d0467df2f444ae41704000f50e1234f46174b51f9c6031a1bd71",
+ "sha256:b74159469b464a99cb8cc3e21973e4d96e05d3024d337313fedb618a6e86e6f4"
],
"markers": "python_version < '3.8'",
- "version": "==2.0.0"
+ "version": "==3.7.3"
},
"mccabe": {
"hashes": [
@@ -517,52 +550,70 @@
},
"pre-commit": {
"hashes": [
- "sha256:7eadaa7f4547a8a19b83230ce430ba81bbe4797bd41c8d7fb54b246164628d1f",
- "sha256:8fb2037c404ef8c87125e72564f316cf2bc94fc9c1cb184b8352117de747e164"
+ "sha256:94c82f1bf5899d56edb1d926732f4e75a7df29a0c8c092559c77420c9d62428b",
+ "sha256:de55c5c72ce80d79106e48beb1b54104d16495ce7f95b0c7b13d4784193a00af"
],
"index": "pypi",
- "version": "==2.8.1"
+ "version": "==2.11.1"
},
"pycodestyle": {
"hashes": [
- "sha256:2295e7b2f6b5bd100585ebcb1f616591b652db8a741695b3d8f5d28bdc934367",
- "sha256:c58a7d2815e0e8d7972bf1803331fb0152f867bd89adf8a01dfd55085434192e"
+ "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068",
+ "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
- "version": "==2.6.0"
+ "version": "==2.7.0"
},
"pydocstyle": {
"hashes": [
- "sha256:19b86fa8617ed916776a11cd8bc0197e5b9856d5433b777f51a3defe13075325",
- "sha256:aca749e190a01726a4fb472dd4ef23b5c9da7b9205c0a7857c06533de13fd678"
+ "sha256:164befb520d851dbcf0e029681b91f4f599c62c5cd8933fd54b1bfbd50e89e1f",
+ "sha256:d4449cf16d7e6709f63192146706933c7a334af7c0f083904799ccb851c50f6d"
],
- "markers": "python_version >= '3.5'",
- "version": "==5.1.1"
+ "markers": "python_version >= '3.6'",
+ "version": "==6.0.0"
},
"pyflakes": {
"hashes": [
- "sha256:0d94e0e05a19e57a99444b6ddcf9a6eb2e5c68d3ca1e98e90707af8152c90a92",
- "sha256:35b2d75ee967ea93b55750aa9edbbf72813e06a66ba54438df2cfac9e3c27fc8"
+ "sha256:910208209dcea632721cb58363d0f72913d9e8cf64dc6f8ae2e02a3609aba40d",
+ "sha256:e59fd8e750e588358f1b8885e5a4751203a0516e0ee6d34811089ac294c8806f"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
- "version": "==2.2.0"
+ "version": "==2.3.0"
},
"pyyaml": {
"hashes": [
- "sha256:06a0d7ba600ce0b2d2fe2e78453a470b5a6e000a985dd4a4e54e436cc36b0e97",
- "sha256:240097ff019d7c70a4922b6869d8a86407758333f02203e0fc6ff79c5dcede76",
- "sha256:4f4b913ca1a7319b33cfb1369e91e50354d6f07a135f3b901aca02aa95940bd2",
- "sha256:69f00dca373f240f842b2931fb2c7e14ddbacd1397d57157a9b005a6a9942648",
- "sha256:73f099454b799e05e5ab51423c7bcf361c58d3206fa7b0d555426b1f4d9a3eaf",
- "sha256:74809a57b329d6cc0fdccee6318f44b9b8649961fa73144a98735b0aaf029f1f",
- "sha256:7739fc0fa8205b3ee8808aea45e968bc90082c10aef6ea95e855e10abf4a37b2",
- "sha256:95f71d2af0ff4227885f7a6605c37fd53d3a106fcab511b8860ecca9fcf400ee",
- "sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d",
- "sha256:cc8955cfbfc7a115fa81d85284ee61147059a753344bc51098f3ccd69b0d7e0c",
- "sha256:d13155f591e6fcc1ec3b30685d50bf0711574e2c0dfffd7644babf8b5102ca1a"
- ],
- "index": "pypi",
- "version": "==5.3.1"
+ "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf",
+ "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696",
+ "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393",
+ "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77",
+ "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922",
+ "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5",
+ "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8",
+ "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10",
+ "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc",
+ "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018",
+ "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e",
+ "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253",
+ "sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347",
+ "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183",
+ "sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541",
+ "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb",
+ "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185",
+ "sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc",
+ "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db",
+ "sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa",
+ "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46",
+ "sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122",
+ "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b",
+ "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63",
+ "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df",
+ "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc",
+ "sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247",
+ "sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6",
+ "sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0"
+ ],
+ "index": "pypi",
+ "version": "==5.4.1"
},
"six": {
"hashes": [
@@ -574,69 +625,79 @@
},
"smmap": {
"hashes": [
- "sha256:54c44c197c819d5ef1991799a7e30b662d1e520f2ac75c9efbeb54a742214cf4",
- "sha256:9c98bbd1f9786d22f14b3d4126894d56befb835ec90cef151af566c7e19b5d24"
+ "sha256:7bfcf367828031dc893530a29cb35eb8c8f2d7c8f2d0989354d75d24c8573714",
+ "sha256:84c2751ef3072d4f6b2785ec7ee40244c6f45eb934d9e543e2c51f1bd3d54c50"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
- "version": "==3.0.4"
+ "version": "==3.0.5"
},
"snowballstemmer": {
"hashes": [
- "sha256:209f257d7533fdb3cb73bdbd24f436239ca3b2fa67d56f6ff88e86be08cc5ef0",
- "sha256:df3bac3df4c2c01363f3dd2cfa78cce2840a79b9f1c2d2de9ce8d31683992f52"
+ "sha256:b51b447bea85f9968c13b650126a888aabd4cb4463fca868ec596826325dedc2",
+ "sha256:e997baa4f2e9139951b6f4c631bad912dfd3c792467e2f03d7239464af90e914"
],
- "version": "==2.0.0"
+ "version": "==2.1.0"
},
"stevedore": {
"hashes": [
- "sha256:5e1ab03eaae06ef6ce23859402de785f08d97780ed774948ef16c4652c41bc62",
- "sha256:f845868b3a3a77a2489d226568abe7328b5c2d4f6a011cc759dfa99144a521f0"
+ "sha256:3a5bbd0652bf552748871eaa73a4a8dc2899786bc497a2aa1fcb4dcdb0debeee",
+ "sha256:50d7b78fbaf0d04cd62411188fa7eedcb03eb7f4c4b37005615ceebe582aa82a"
],
"markers": "python_version >= '3.6'",
- "version": "==3.2.2"
+ "version": "==3.3.0"
},
"toml": {
"hashes": [
- "sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f",
- "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88"
+ "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b",
+ "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"
],
- "version": "==0.10.1"
+ "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==0.10.2"
},
"typed-ast": {
"hashes": [
- "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355",
- "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919",
- "sha256:0d8110d78a5736e16e26213114a38ca35cb15b6515d535413b090bd50951556d",
- "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa",
- "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652",
- "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75",
- "sha256:3742b32cf1c6ef124d57f95be609c473d7ec4c14d0090e5a5e05a15269fb4d0c",
- "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01",
- "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d",
- "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1",
- "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907",
- "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c",
- "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3",
- "sha256:7e4c9d7658aaa1fc80018593abdf8598bf91325af6af5cce4ce7c73bc45ea53d",
- "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b",
- "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614",
- "sha256:92c325624e304ebf0e025d1224b77dd4e6393f18aab8d829b5b7e04afe9b7a2c",
- "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb",
- "sha256:b52ccf7cfe4ce2a1064b18594381bccf4179c2ecf7f513134ec2f993dd4ab395",
- "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b",
- "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41",
- "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6",
- "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34",
- "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe",
- "sha256:d648b8e3bf2fe648745c8ffcee3db3ff903d0817a01a12dd6a6ea7a8f4889072",
- "sha256:f208eb7aff048f6bea9586e61af041ddf7f9ade7caed625742af423f6bae3298",
- "sha256:fac11badff8313e23717f3dada86a15389d0708275bddf766cca67a84ead3e91",
- "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4",
- "sha256:fcf135e17cc74dbfbc05894ebca928ffeb23d9790b3167a674921db19082401f",
- "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"
+ "sha256:07d49388d5bf7e863f7fa2f124b1b1d89d8aa0e2f7812faff0a5658c01c59aa1",
+ "sha256:14bf1522cdee369e8f5581238edac09150c765ec1cb33615855889cf33dcb92d",
+ "sha256:240296b27397e4e37874abb1df2a608a92df85cf3e2a04d0d4d61055c8305ba6",
+ "sha256:36d829b31ab67d6fcb30e185ec996e1f72b892255a745d3a82138c97d21ed1cd",
+ "sha256:37f48d46d733d57cc70fd5f30572d11ab8ed92da6e6b28e024e4a3edfb456e37",
+ "sha256:4c790331247081ea7c632a76d5b2a265e6d325ecd3179d06e9cf8d46d90dd151",
+ "sha256:5dcfc2e264bd8a1db8b11a892bd1647154ce03eeba94b461effe68790d8b8e07",
+ "sha256:7147e2a76c75f0f64c4319886e7639e490fee87c9d25cb1d4faef1d8cf83a440",
+ "sha256:7703620125e4fb79b64aa52427ec192822e9f45d37d4b6625ab37ef403e1df70",
+ "sha256:8368f83e93c7156ccd40e49a783a6a6850ca25b556c0fa0240ed0f659d2fe496",
+ "sha256:84aa6223d71012c68d577c83f4e7db50d11d6b1399a9c779046d75e24bed74ea",
+ "sha256:85f95aa97a35bdb2f2f7d10ec5bbdac0aeb9dafdaf88e17492da0504de2e6400",
+ "sha256:8db0e856712f79c45956da0c9a40ca4246abc3485ae0d7ecc86a20f5e4c09abc",
+ "sha256:9044ef2df88d7f33692ae3f18d3be63dec69c4fb1b5a4a9ac950f9b4ba571606",
+ "sha256:963c80b583b0661918718b095e02303d8078950b26cc00b5e5ea9ababe0de1fc",
+ "sha256:987f15737aba2ab5f3928c617ccf1ce412e2e321c77ab16ca5a293e7bbffd581",
+ "sha256:9ec45db0c766f196ae629e509f059ff05fc3148f9ffd28f3cfe75d4afb485412",
+ "sha256:9fc0b3cb5d1720e7141d103cf4819aea239f7d136acf9ee4a69b047b7986175a",
+ "sha256:a2c927c49f2029291fbabd673d51a2180038f8cd5a5b2f290f78c4516be48be2",
+ "sha256:a38878a223bdd37c9709d07cd357bb79f4c760b29210e14ad0fb395294583787",
+ "sha256:b4fcdcfa302538f70929eb7b392f536a237cbe2ed9cba88e3bf5027b39f5f77f",
+ "sha256:c0c74e5579af4b977c8b932f40a5464764b2f86681327410aa028a22d2f54937",
+ "sha256:c1c876fd795b36126f773db9cbb393f19808edd2637e00fd6caba0e25f2c7b64",
+ "sha256:c9aadc4924d4b5799112837b226160428524a9a45f830e0d0f184b19e4090487",
+ "sha256:cc7b98bf58167b7f2db91a4327da24fb93368838eb84a44c472283778fc2446b",
+ "sha256:cf54cfa843f297991b7388c281cb3855d911137223c6b6d2dd82a47ae5125a41",
+ "sha256:d003156bb6a59cda9050e983441b7fa2487f7800d76bdc065566b7d728b4581a",
+ "sha256:d175297e9533d8d37437abc14e8a83cbc68af93cc9c1c59c2c292ec59a0697a3",
+ "sha256:d746a437cdbca200622385305aedd9aef68e8a645e385cc483bdc5e488f07166",
+ "sha256:e683e409e5c45d5c9082dc1daf13f6374300806240719f95dc783d1fc942af10"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==1.4.2"
+ },
+ "typing-extensions": {
+ "hashes": [
+ "sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918",
+ "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c",
+ "sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f"
],
"markers": "python_version < '3.8'",
- "version": "==1.4.1"
+ "version": "==3.7.4.3"
},
"unittest-xml-reporting": {
"hashes": [
@@ -648,19 +709,19 @@
},
"virtualenv": {
"hashes": [
- "sha256:b0011228208944ce71052987437d3843e05690b2f23d1c7da4263fde104c97a2",
- "sha256:b8d6110f493af256a40d65e29846c69340a947669eec8ce784fcf3dd3af28380"
+ "sha256:49ec4eb4c224c6f7dd81bb6d0a28a09ecae5894f4e593c89b0db0885f565a107",
+ "sha256:83f95875d382c7abafe06bd2a4cdd1b363e1bb77e02f155ebe8ac082a916b37c"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
- "version": "==20.1.0"
+ "version": "==20.4.3"
},
"zipp": {
"hashes": [
- "sha256:102c24ef8f171fd729d46599845e95c7ab894a4cf45f5de11a44cc7444fb1108",
- "sha256:ed5eee1974372595f9e416cc7bbeeb12335201d8081ca8a0743c954d4446e5cb"
+ "sha256:3607921face881ba3e026887d8150cca609d517579abe052ac81fc5aeffdbd76",
+ "sha256:51cb66cc54621609dd593d1787f286ee42a5c0adbb4b29abea5a63edc3e03098"
],
"markers": "python_version >= '3.6'",
- "version": "==3.4.0"
+ "version": "==3.4.1"
}
}
}
diff --git a/pydis_site/apps/content/tests/test_utils.py b/pydis_site/apps/content/tests/test_utils.py
index 85f1139a..26b2bba9 100644
--- a/pydis_site/apps/content/tests/test_utils.py
+++ b/pydis_site/apps/content/tests/test_utils.py
@@ -146,43 +146,3 @@ class TestGetArticle(TestCase):
"""Check does this raise Http404 when category don't exist."""
with self.assertRaises(Http404):
utils.get_article(["invalid", "some-guide"])
-
-
-class GetGitHubInformationTests(TestCase):
- @patch("pydis_site.apps.content.utils.requests.get")
- @patch("pydis_site.apps.content.utils.COMMITS_URL", "foobar")
- def test_call_get_github_information_requests_get(self, requests_get_mock):
- """Check does this call requests.get function with proper URL."""
- utils.get_github_information(["foo"])
- requests_get_mock.assert_called_once_with("foobar")
-
- @patch("pydis_site.apps.content.utils.requests.get")
- def test_github_status_code_200_response(self, requests_get_mock):
- """Check does this return provided modified date and contributors."""
- requests_get_mock.return_value = MagicMock(status_code=200)
- requests_get_mock.return_value.json.return_value = [{
- "commit": {
- "committer": {
- "date": datetime(2020, 10, 1).isoformat(),
- "name": "foobar",
- }
- },
- "committer": {
- "html_url": "abc1234"
- }
- }]
- result = utils.get_github_information(["foo"])
- self.assertEqual(result, {
- "last_modified": datetime(2020, 10, 1).strftime("%dth %B %Y"),
- "contributors": {"foobar": "abc1234"}
- })
-
- @patch("pydis_site.apps.content.utils.requests.get")
- def test_github_other_status_code_response(self, requests_get_mock):
- """Check does this return provided modified date and contributors."""
- requests_get_mock.return_value = MagicMock(status_code=404)
- result = utils.get_github_information(["foo"])
- self.assertEqual(result, {
- "last_modified": "N/A",
- "contributors": {}
- })
diff --git a/pydis_site/apps/content/tests/test_views.py b/pydis_site/apps/content/tests/test_views.py
index 98b99b83..55bfb8ea 100644
--- a/pydis_site/apps/content/tests/test_views.py
+++ b/pydis_site/apps/content/tests/test_views.py
@@ -30,8 +30,7 @@ class TestArticleOrCategoryView(TestCase):
@override_settings(ARTICLES_PATH=BASE_PATH)
@patch("pydis_site.apps.content.views.article_category.utils.get_article")
@patch("pydis_site.apps.content.views.article_category.utils.get_category")
- @patch("pydis_site.apps.content.views.article_category.utils.get_github_information")
- def test_article_return_code_200(self, gh_info_mock, get_category_mock, get_article_mock):
+ def test_article_return_code_200(self, get_category_mock, get_article_mock):
get_article_mock.return_value = {"guide": "test", "metadata": {}}
url = reverse("content:article_category", args=["test2"])
@@ -39,7 +38,6 @@ class TestArticleOrCategoryView(TestCase):
self.assertEqual(response.status_code, 200)
get_category_mock.assert_not_called()
get_article_mock.assert_called_once()
- gh_info_mock.assert_called_once()
@patch("pydis_site.apps.content.views.article_category.utils.get_article")
@patch("pydis_site.apps.content.views.article_category.utils.get_category")
@@ -99,11 +97,9 @@ class TestArticleOrCategoryView(TestCase):
@patch("pydis_site.apps.content.views.article_category.utils.get_article")
@patch("pydis_site.apps.content.views.article_category.utils.get_category")
- @patch("pydis_site.apps.content.views.article_category.utils.get_github_information")
@override_settings(ARTICLES_PATH=BASE_PATH)
def test_valid_category_article_code_200(
self,
- gh_info_mock,
get_category_mock,
get_article_mock
):
@@ -115,15 +111,12 @@ class TestArticleOrCategoryView(TestCase):
self.assertEqual(response.status_code, 200)
get_article_mock.assert_called_once()
self.assertEqual(get_category_mock.call_count, 2)
- gh_info_mock.assert_called_once()
@patch("pydis_site.apps.content.views.article_category.utils.get_article")
@patch("pydis_site.apps.content.views.article_category.utils.get_category")
- @patch("pydis_site.apps.content.views.article_category.utils.get_github_information")
@override_settings(ARTICLES_PATH=BASE_PATH)
def test_invalid_category_article_code_404(
self,
- gh_info_mock,
get_category_mock,
get_article_mock
):
@@ -135,7 +128,6 @@ class TestArticleOrCategoryView(TestCase):
self.assertEqual(response.status_code, 404)
get_article_mock.assert_not_called()
get_category_mock.assert_not_called()
- gh_info_mock.assert_not_called()
@override_settings(ARTICLES_PATH=BASE_PATH)
def test_article_category_template_names(self):
diff --git a/pydis_site/apps/content/utils.py b/pydis_site/apps/content/utils.py
index a89db83c..305d26b5 100644
--- a/pydis_site/apps/content/utils.py
+++ b/pydis_site/apps/content/utils.py
@@ -1,16 +1,11 @@
import os
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_category(path: List[str]) -> Dict[str, str]:
"""Load category information by name from _info.yml."""
@@ -77,36 +72,3 @@ def get_article(path: List[str]) -> Dict[str, Union[str, Dict]]:
)
return {"article": str(html), "metadata": html.metadata}
-
-
-def get_github_information(
- path: List[str]
-) -> 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}{'/'.join(path[:-1])}"
- f"{'/' if len(path) > 1 else ''}{path[-1]}.md"
- )
- )
- )
-
- if result.status_code == 200 and len(result.json()):
- 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": {}
- }
diff --git a/pydis_site/apps/content/views/article_category.py b/pydis_site/apps/content/views/article_category.py
index 0c22b5e8..51b1def2 100644
--- a/pydis_site/apps/content/views/article_category.py
+++ b/pydis_site/apps/content/views/article_category.py
@@ -54,7 +54,6 @@ class ArticleOrCategoryView(TemplateView):
article_result["metadata"].get("relevant_link_values", "").split(",")
) if link != "" and value != ""
}
- context["github_data"] = utils.get_github_information(location)
else:
raise Http404
diff --git a/pydis_site/templates/content/article.html b/pydis_site/templates/content/article.html
index fcb29f32..bcdee95a 100644
--- a/pydis_site/templates/content/article.html
+++ b/pydis_site/templates/content/article.html
@@ -34,29 +34,11 @@
{{ article.metadata.title }}
-
Last modified: {{ github_data.last_modified }}
{{ article.article|safe }}
-
-
-
- {% if github_data.contributors|length %}
-
- {% else %}
-
N/A
- {% endif %}
-
-
-
{% if relevant_links|length > 0 %}
--
cgit v1.2.3
From 102ac2be5523bb4a26157168e426fae8f15cf28c Mon Sep 17 00:00:00 2001
From: kosayoda
Date: Tue, 23 Mar 2021 17:34:34 +0800
Subject: Simplify relevant_links configuration in markdown.
---
pydis_site/apps/content/views/article_category.py | 7 +------
pydis_site/templates/content/article.html | 2 +-
2 files changed, 2 insertions(+), 7 deletions(-)
(limited to 'pydis_site')
diff --git a/pydis_site/apps/content/views/article_category.py b/pydis_site/apps/content/views/article_category.py
index 51b1def2..2a407b99 100644
--- a/pydis_site/apps/content/views/article_category.py
+++ b/pydis_site/apps/content/views/article_category.py
@@ -48,12 +48,7 @@ class ArticleOrCategoryView(TemplateView):
context["category_data"] = {"name": None, "raw_name": None}
context["article"] = article_result
- context["relevant_links"] = {
- link: value for link, value in zip(
- article_result["metadata"].get("relevant_links", "").split(","),
- article_result["metadata"].get("relevant_link_values", "").split(",")
- ) if link != "" and value != ""
- }
+ context["relevant_links"] = article_result["metadata"].get("relevant_links", {})
else:
raise Http404
diff --git a/pydis_site/templates/content/article.html b/pydis_site/templates/content/article.html
index bcdee95a..69d01a8d 100644
--- a/pydis_site/templates/content/article.html
+++ b/pydis_site/templates/content/article.html
@@ -43,7 +43,7 @@
--
cgit v1.2.3
From 367ba267c4dbc6d406922f80bc4337ee9a0139a0 Mon Sep 17 00:00:00 2001
From: kosayoda
Date: Tue, 23 Mar 2021 18:24:56 +0800
Subject: Rename `articles` to `pages`.
Articles was a good name, but we want an `articles` category in
the future. `/pages/guides/` and `/pages/articles/` are clearer in name
than `/articles/guides/` and `/articles/articles/`.
---
pydis_site/apps/content/tests/test_utils.py | 70 ++++++------
pydis_site/apps/content/tests/test_views.py | 127 +++++++++++-----------
pydis_site/apps/content/urls.py | 4 +-
pydis_site/apps/content/utils.py | 36 +++---
pydis_site/apps/content/views/__init__.py | 6 +-
pydis_site/apps/content/views/article_category.py | 69 ------------
pydis_site/apps/content/views/articles.py | 16 ---
pydis_site/apps/content/views/page_category.py | 69 ++++++++++++
pydis_site/apps/content/views/pages.py | 16 +++
pydis_site/apps/events/urls.py | 4 +-
pydis_site/apps/events/views/__init__.py | 4 +-
pydis_site/apps/events/views/page.py | 2 +-
pydis_site/apps/home/urls.py | 2 +-
pydis_site/settings.py | 2 +-
pydis_site/static/css/content/articles.css | 16 ---
pydis_site/static/css/content/page.css | 16 +++
pydis_site/templates/content/article.html | 58 ----------
pydis_site/templates/content/listing.html | 20 ++--
pydis_site/templates/content/page.html | 58 ++++++++++
pydis_site/templates/resources/resources.html | 2 +-
20 files changed, 299 insertions(+), 298 deletions(-)
delete mode 100644 pydis_site/apps/content/views/article_category.py
delete mode 100644 pydis_site/apps/content/views/articles.py
create mode 100644 pydis_site/apps/content/views/page_category.py
create mode 100644 pydis_site/apps/content/views/pages.py
delete mode 100644 pydis_site/static/css/content/articles.css
create mode 100644 pydis_site/static/css/content/page.css
delete mode 100644 pydis_site/templates/content/article.html
create mode 100644 pydis_site/templates/content/page.html
(limited to 'pydis_site')
diff --git a/pydis_site/apps/content/tests/test_utils.py b/pydis_site/apps/content/tests/test_utils.py
index 26b2bba9..e1f1b92a 100644
--- a/pydis_site/apps/content/tests/test_utils.py
+++ b/pydis_site/apps/content/tests/test_utils.py
@@ -13,20 +13,20 @@ BASE_PATH = Path(settings.BASE_DIR, "pydis_site", "apps", "content", "tests", "t
class TestGetCategory(TestCase):
- @override_settings(ARTICLES_PATH=BASE_PATH)
+ @override_settings(PAGES_PATH=BASE_PATH)
def test_get_category_successfully(self):
"""Check does this get right data from category data file."""
result = utils.get_category(["category"])
self.assertEqual(result, {"name": "My Category", "description": "My Description"})
- @override_settings(ARTICLES_PATH=BASE_PATH)
+ @override_settings(PAGES_PATH=BASE_PATH)
def test_get_category_not_exists(self):
"""Check does this raise 404 error when category don't exists."""
with self.assertRaises(Http404):
utils.get_category(["invalid"])
- @override_settings(ARTICLES_PATH=BASE_PATH)
+ @override_settings(PAGES_PATH=BASE_PATH)
def test_get_category_not_directory(self):
"""Check does this raise 404 error when category isn't directory."""
with self.assertRaises(Http404):
@@ -34,7 +34,7 @@ class TestGetCategory(TestCase):
class TestGetCategories(TestCase):
- @override_settings(ARTICLES_PATH=BASE_PATH)
+ @override_settings(PAGES_PATH=BASE_PATH)
@patch("pydis_site.apps.content.utils.get_category")
def test_get_categories(self, get_category_mock):
"""Check does this return test content categories."""
@@ -47,7 +47,7 @@ class TestGetCategories(TestCase):
result, {"category": {"name": "My Category", "description": "My Description"}}
)
- @override_settings(ARTICLES_PATH=BASE_PATH)
+ @override_settings(PAGES_PATH=BASE_PATH)
def test_get_categories_root_path(self):
"""Check does this doesn't call joinpath when getting root categories."""
result = utils.get_categories()
@@ -55,7 +55,7 @@ class TestGetCategories(TestCase):
result, {"category": {"name": "My Category", "description": "My Description"}}
)
- @override_settings(ARTICLES_PATH=BASE_PATH)
+ @override_settings(PAGES_PATH=BASE_PATH)
def test_get_categories_in_category(self):
"""Check does this call joinpath when getting subcategories."""
result = utils.get_categories(["category"])
@@ -64,11 +64,11 @@ class TestGetCategories(TestCase):
)
-class TestGetArticles(TestCase):
- @override_settings(ARTICLES_PATH=BASE_PATH)
- def test_get_all_root_articles(self):
+class TestGetPages(TestCase):
+ @override_settings(PAGES_PATH=BASE_PATH)
+ def test_get_all_root_pages(self):
"""Check does this return all root level testing content."""
- result = utils.get_articles()
+ result = utils.get_pages()
for case in ["test", "test2"]:
with self.subTest(guide=case):
@@ -77,10 +77,10 @@ class TestGetArticles(TestCase):
self.assertIn(case, result)
self.assertEqual(md.metadata, result[case])
- @override_settings(ARTICLES_PATH=BASE_PATH)
- def test_get_all_category_articles(self):
+ @override_settings(PAGES_PATH=BASE_PATH)
+ def test_get_all_category_pages(self):
"""Check does this return all category testing content."""
- result = utils.get_articles(["category"])
+ result = utils.get_pages(["category"])
md = markdown(BASE_PATH.joinpath("category", "test3.md").read_text(), extras=["metadata"])
@@ -88,11 +88,11 @@ class TestGetArticles(TestCase):
self.assertEqual(md.metadata, result["test3"])
-class TestGetArticle(TestCase):
- @override_settings(ARTICLES_PATH=BASE_PATH)
- def test_get_root_article_success(self):
- """Check does this return article HTML and metadata when root article exist."""
- result = utils.get_article(["test"])
+class TestGetPage(TestCase):
+ @override_settings(PAGES_PATH=BASE_PATH)
+ def test_get_root_page_success(self):
+ """Check does this return page HTML and metadata when root page exist."""
+ result = utils.get_page(["test"])
md = markdown(
BASE_PATH.joinpath("test.md").read_text(),
@@ -107,18 +107,18 @@ class TestGetArticle(TestCase):
]
)
- self.assertEqual(result, {"article": str(md), "metadata": md.metadata})
+ self.assertEqual(result, {"page": str(md), "metadata": md.metadata})
- @override_settings(ARTICLES_PATH=BASE_PATH)
- def test_get_root_article_dont_exist(self):
- """Check does this raise Http404 when root article don't exist."""
+ @override_settings(PAGES_PATH=BASE_PATH)
+ def test_get_root_page_dont_exist(self):
+ """Check does this raise Http404 when root page don't exist."""
with self.assertRaises(Http404):
- utils.get_article(["invalid"])
+ utils.get_page(["invalid"])
- @override_settings(ARTICLES_PATH=BASE_PATH)
- def test_get_category_article_success(self):
- """Check does this return article HTML and metadata when category guide exist."""
- result = utils.get_article(["category", "test3"])
+ @override_settings(PAGES_PATH=BASE_PATH)
+ def test_get_category_page_success(self):
+ """Check does this return page HTML and metadata when category guide exist."""
+ result = utils.get_page(["category", "test3"])
md = markdown(
BASE_PATH.joinpath("category", "test3.md").read_text(),
@@ -133,16 +133,16 @@ class TestGetArticle(TestCase):
]
)
- self.assertEqual(result, {"article": str(md), "metadata": md.metadata})
+ self.assertEqual(result, {"page": str(md), "metadata": md.metadata})
- @override_settings(ARTICLES_PATH=BASE_PATH)
- def test_get_category_article_dont_exist(self):
- """Check does this raise Http404 when category article don't exist."""
+ @override_settings(PAGES_PATH=BASE_PATH)
+ def test_get_category_page_dont_exist(self):
+ """Check does this raise Http404 when category page don't exist."""
with self.assertRaises(Http404):
- utils.get_article(["category", "invalid"])
+ utils.get_page(["category", "invalid"])
- @patch("pydis_site.settings.ARTICLES_PATH", new=BASE_PATH)
- def test_get_category_article_category_dont_exist(self):
+ @patch("pydis_site.settings.PAGES_PATH", new=BASE_PATH)
+ def test_get_category_page_category_dont_exist(self):
"""Check does this raise Http404 when category don't exist."""
with self.assertRaises(Http404):
- utils.get_article(["invalid", "some-guide"])
+ utils.get_page(["invalid", "some-guide"])
diff --git a/pydis_site/apps/content/tests/test_views.py b/pydis_site/apps/content/tests/test_views.py
index 55bfb8ea..5ce18afb 100644
--- a/pydis_site/apps/content/tests/test_views.py
+++ b/pydis_site/apps/content/tests/test_views.py
@@ -6,143 +6,144 @@ from django.http import Http404
from django.test import RequestFactory, TestCase, override_settings
from django_hosts.resolvers import reverse
-from pydis_site.apps.content.views import ArticleOrCategoryView
+from pydis_site.apps.content.views import PageOrCategoryView
BASE_PATH = Path(settings.BASE_DIR, "pydis_site", "apps", "content", "tests", "test_content")
-class TestArticlesIndexView(TestCase):
- @patch("pydis_site.apps.content.views.articles.get_articles")
- @patch("pydis_site.apps.content.views.articles.get_categories")
- def test_articles_index_return_200(self, get_categories_mock, get_articles_mock):
+class TestPagesIndexView(TestCase):
+ @patch("pydis_site.apps.content.views.pages.get_pages")
+ @patch("pydis_site.apps.content.views.pages.get_categories")
+ def test_pages_index_return_200(self, get_categories_mock, get_page_mock):
"""Check that content index return HTTP code 200."""
get_categories_mock.return_value = {}
- get_articles_mock.return_value = {}
+ get_page_mock.return_value = {}
- url = reverse('content:articles')
+ url = reverse('content:pages')
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
- get_articles_mock.assert_called_once()
+ get_page_mock.assert_called_once()
get_categories_mock.assert_called_once()
-class TestArticleOrCategoryView(TestCase):
- @override_settings(ARTICLES_PATH=BASE_PATH)
- @patch("pydis_site.apps.content.views.article_category.utils.get_article")
- @patch("pydis_site.apps.content.views.article_category.utils.get_category")
- def test_article_return_code_200(self, get_category_mock, get_article_mock):
- get_article_mock.return_value = {"guide": "test", "metadata": {}}
+class TestPageOrCategoryView(TestCase):
+ @override_settings(PAGES_PATH=BASE_PATH)
+ @patch("pydis_site.apps.content.views.page_category.utils.get_page")
+ @patch("pydis_site.apps.content.views.page_category.utils.get_category")
+ @patch("pydis_site.apps.content.views.page_category.utils.get_github_information")
+ def test_page_return_code_200(self, get_category_mock, get_page_mock):
+ get_page_mock.return_value = {"guide": "test", "metadata": {}}
- url = reverse("content:article_category", args=["test2"])
+ url = reverse("content:page_category", args=["test2"])
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
get_category_mock.assert_not_called()
- get_article_mock.assert_called_once()
+ get_page_mock.assert_called_once()
- @patch("pydis_site.apps.content.views.article_category.utils.get_article")
- @patch("pydis_site.apps.content.views.article_category.utils.get_category")
- @override_settings(ARTICLES_PATH=BASE_PATH)
- def test_article_return_404(self, get_category_mock, get_article_mock):
- """Check that return code is 404 when invalid article provided."""
- get_article_mock.side_effect = Http404("Article not found.")
+ @patch("pydis_site.apps.content.views.page_category.utils.get_page")
+ @patch("pydis_site.apps.content.views.page_category.utils.get_category")
+ @override_settings(PAGES_PATH=BASE_PATH)
+ def test_page_return_404(self, get_category_mock, get_page_mock):
+ """Check that return code is 404 when invalid page provided."""
+ get_page_mock.side_effect = Http404("Page not found.")
- url = reverse("content:article_category", args=["invalid-guide"])
+ url = reverse("content:page_category", args=["invalid-guide"])
response = self.client.get(url)
self.assertEqual(response.status_code, 404)
- get_article_mock.assert_not_called()
+ get_page_mock.assert_not_called()
get_category_mock.assert_not_called()
- @patch("pydis_site.apps.content.views.article_category.utils.get_category")
- @patch("pydis_site.apps.content.views.article_category.utils.get_articles")
- @patch("pydis_site.apps.content.views.article_category.utils.get_categories")
- @override_settings(ARTICLES_PATH=BASE_PATH)
+ @patch("pydis_site.apps.content.views.page_category.utils.get_category")
+ @patch("pydis_site.apps.content.views.page_category.utils.get_pages")
+ @patch("pydis_site.apps.content.views.page_category.utils.get_categories")
+ @override_settings(PAGES_PATH=BASE_PATH)
def test_valid_category_code_200(
self,
get_categories_mock,
- get_articles_mock,
+ get_pages_mock,
get_category_mock
):
"""Check that return code is 200 when visiting valid category."""
get_category_mock.return_value = {"name": "test", "description": "test"}
- get_articles_mock.return_value = {}
+ get_pages_mock.return_value = {}
- url = reverse("content:article_category", args=["category"])
+ url = reverse("content:page_category", args=["category"])
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
- get_articles_mock.assert_called_once()
+ get_pages_mock.assert_called_once()
get_category_mock.assert_called_once()
get_categories_mock.assert_called_once()
- @patch("pydis_site.apps.content.views.article_category.utils.get_category")
- @patch("pydis_site.apps.content.views.article_category.utils.get_articles")
- @patch("pydis_site.apps.content.views.article_category.utils.get_categories")
- @override_settings(ARTICLES_PATH=BASE_PATH)
+ @patch("pydis_site.apps.content.views.page_category.utils.get_category")
+ @patch("pydis_site.apps.content.views.page_category.utils.get_pages")
+ @patch("pydis_site.apps.content.views.page_category.utils.get_categories")
+ @override_settings(PAGES_PATH=BASE_PATH)
def test_invalid_category_code_404(
self,
get_categories_mock,
- get_articles_mock,
+ get_pages_mock,
get_category_mock
):
"""Check that return code is 404 when trying to visit invalid category."""
get_category_mock.side_effect = Http404("Category not found.")
- url = reverse("content:article_category", args=["invalid-category"])
+ url = reverse("content:page_category", args=["invalid-category"])
response = self.client.get(url)
self.assertEqual(response.status_code, 404)
get_category_mock.assert_not_called()
- get_articles_mock.assert_not_called()
+ get_pages_mock.assert_not_called()
get_categories_mock.assert_not_called()
- @patch("pydis_site.apps.content.views.article_category.utils.get_article")
- @patch("pydis_site.apps.content.views.article_category.utils.get_category")
- @override_settings(ARTICLES_PATH=BASE_PATH)
- def test_valid_category_article_code_200(
+ @patch("pydis_site.apps.content.views.page_category.utils.get_page")
+ @patch("pydis_site.apps.content.views.page_category.utils.get_category")
+ @override_settings(PAGES_PATH=BASE_PATH)
+ def test_valid_category_page_code_200(
self,
get_category_mock,
- get_article_mock
+ get_page_mock
):
- """Check that return code is 200 when visiting valid category article."""
- get_article_mock.return_value = {"guide": "test", "metadata": {}}
+ """Check that return code is 200 when visiting valid category page."""
+ get_page_mock.return_value = {"guide": "test", "metadata": {}}
- url = reverse("content:article_category", args=["category/test3"])
+ url = reverse("content:page_category", args=["category/test3"])
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
- get_article_mock.assert_called_once()
+ get_page_mock.assert_called_once()
self.assertEqual(get_category_mock.call_count, 2)
- @patch("pydis_site.apps.content.views.article_category.utils.get_article")
- @patch("pydis_site.apps.content.views.article_category.utils.get_category")
- @override_settings(ARTICLES_PATH=BASE_PATH)
- def test_invalid_category_article_code_404(
+ @patch("pydis_site.apps.content.views.page_category.utils.get_page")
+ @patch("pydis_site.apps.content.views.page_category.utils.get_category")
+ @override_settings(PAGES_PATH=BASE_PATH)
+ def test_invalid_category_page_code_404(
self,
get_category_mock,
- get_article_mock
+ get_page_mock
):
- """Check that return code is 200 when trying to visit invalid category article."""
- get_article_mock.side_effect = Http404("Article not found.")
+ """Check that return code is 200 when trying to visit invalid category page."""
+ get_page_mock.side_effect = Http404("Page not found.")
- url = reverse("content:article_category", args=["category/invalid"])
+ url = reverse("content:page_category", args=["category/invalid"])
response = self.client.get(url)
self.assertEqual(response.status_code, 404)
- get_article_mock.assert_not_called()
+ get_page_mock.assert_not_called()
get_category_mock.assert_not_called()
- @override_settings(ARTICLES_PATH=BASE_PATH)
- def test_article_category_template_names(self):
- """Check that this return category, article template or raise Http404."""
+ @override_settings(PAGES_PATH=BASE_PATH)
+ def test_page_category_template_names(self):
+ """Check that this return category, page template or raise Http404."""
factory = RequestFactory()
cases = [
{"location": "category", "output": ["content/listing.html"]},
- {"location": "test", "output": ["content/article.html"]},
+ {"location": "test", "output": ["content/page.html"]},
{"location": "invalid", "output": None, "raises": Http404}
]
for case in cases:
with self.subTest(location=case["location"], output=case["output"]):
- request = factory.get(f"/articles/{case['location']}")
- instance = ArticleOrCategoryView()
+ request = factory.get(f"/pages/{case['location']}")
+ instance = PageOrCategoryView()
instance.request = request
instance.kwargs = {"location": case["location"]}
diff --git a/pydis_site/apps/content/urls.py b/pydis_site/apps/content/urls.py
index 49a5a2ef..1406f672 100644
--- a/pydis_site/apps/content/urls.py
+++ b/pydis_site/apps/content/urls.py
@@ -4,6 +4,6 @@ from . import views
app_name = "content"
urlpatterns = [
- path("", views.ArticlesView.as_view(), name='articles'),
- path("/", views.ArticleOrCategoryView.as_view(), name='article_category'),
+ path("", views.PagesView.as_view(), name='pages'),
+ path("/", views.PageOrCategoryView.as_view(), name='page_category'),
]
diff --git a/pydis_site/apps/content/utils.py b/pydis_site/apps/content/utils.py
index 305d26b5..db502a71 100644
--- a/pydis_site/apps/content/utils.py
+++ b/pydis_site/apps/content/utils.py
@@ -9,7 +9,7 @@ from markdown2 import markdown
def get_category(path: List[str]) -> Dict[str, str]:
"""Load category information by name from _info.yml."""
- path = settings.ARTICLES_PATH.joinpath(*path)
+ path = settings.PAGES_PATH.joinpath(*path)
if not path.exists() or not path.is_dir():
raise Http404("Category not found.")
@@ -20,10 +20,10 @@ def get_categories(path: Optional[List[str]] = None) -> Dict[str, Dict]:
"""Get all categories information."""
categories = {}
if path is None:
- categories_path = settings.ARTICLES_PATH
+ categories_path = settings.PAGES_PATH
path = []
else:
- categories_path = settings.ARTICLES_PATH.joinpath(*path)
+ categories_path = settings.PAGES_PATH.joinpath(*path)
for name in categories_path.iterdir():
if name.is_dir():
@@ -32,34 +32,34 @@ def get_categories(path: Optional[List[str]] = None) -> Dict[str, Dict]:
return categories
-def get_articles(path: Optional[List[str]] = None) -> Dict[str, Dict]:
- """Get all root or category articles."""
+def get_pages(path: Optional[List[str]] = None) -> Dict[str, Dict]:
+ """Get all root or category pages."""
if path is None:
- base_dir = settings.ARTICLES_PATH
+ base_dir = settings.PAGES_PATH
else:
- base_dir = settings.ARTICLES_PATH.joinpath(*path)
+ base_dir = settings.PAGES_PATH.joinpath(*path)
- articles = {}
+ pages = {}
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
+ pages[os.path.splitext(item.name)[0]] = md.metadata
- return articles
+ return pages
-def get_article(path: List[str]) -> Dict[str, Union[str, Dict]]:
- """Get one specific article. When category is specified, get it from there."""
- article_path = settings.ARTICLES_PATH.joinpath(*path[:-1])
+def get_page(path: List[str]) -> Dict[str, Union[str, Dict]]:
+ """Get one specific page. When category is specified, get it from there."""
+ page_path = settings.PAGES_PATH.joinpath(*path[:-1])
# We need to include extension MD
- article_path = article_path.joinpath(f"{path[-1]}.md")
- if not article_path.exists() or not article_path.is_file():
- raise Http404("Article not found.")
+ page_path = page_path.joinpath(f"{path[-1]}.md")
+ if not page_path.exists() or not page_path.is_file():
+ raise Http404("Page not found.")
html = markdown(
- article_path.read_text(),
+ page_path.read_text(),
extras=[
"metadata",
"fenced-code-blocks",
@@ -71,4 +71,4 @@ def get_article(path: List[str]) -> Dict[str, Union[str, Dict]]:
]
)
- return {"article": str(html), "metadata": html.metadata}
+ return {"page": str(html), "metadata": html.metadata}
diff --git a/pydis_site/apps/content/views/__init__.py b/pydis_site/apps/content/views/__init__.py
index f92660d6..740d98e9 100644
--- a/pydis_site/apps/content/views/__init__.py
+++ b/pydis_site/apps/content/views/__init__.py
@@ -1,4 +1,4 @@
-from .article_category import ArticleOrCategoryView
-from .articles import ArticlesView
+from .page_category import PageOrCategoryView
+from .pages import PagesView
-__all__ = ["ArticleOrCategoryView", "ArticlesView"]
+__all__ = ["PageOrCategoryView", "PagesView"]
diff --git a/pydis_site/apps/content/views/article_category.py b/pydis_site/apps/content/views/article_category.py
deleted file mode 100644
index 2a407b99..00000000
--- a/pydis_site/apps/content/views/article_category.py
+++ /dev/null
@@ -1,69 +0,0 @@
-import typing as t
-
-from django.conf import settings
-from django.http import Http404
-from django.views.generic import TemplateView
-
-from pydis_site.apps.content import utils
-
-
-class ArticleOrCategoryView(TemplateView):
- """Handles article and category pages."""
-
- def get_template_names(self) -> t.List[str]:
- """Checks does this use article template or listing template."""
- location = self.kwargs["location"].split("/")
- full_location = settings.ARTICLES_PATH.joinpath(*location)
-
- if full_location.is_dir():
- template_name = "content/listing.html"
- elif full_location.with_suffix(".md").is_file():
- template_name = "content/article.html"
- else:
- raise Http404
-
- return [template_name]
-
- def get_context_data(self, **kwargs) -> t.Dict[str, t.Any]:
- """Assign proper context variables based on what resource user requests."""
- context = super().get_context_data(**kwargs)
-
- location: list = self.kwargs["location"].split("/")
- full_location = settings.ARTICLES_PATH.joinpath(*location)
-
- if full_location.is_dir():
- context["category_info"] = utils.get_category(location)
- context["content"] = utils.get_articles(location)
- context["categories"] = utils.get_categories(location)
- # Add trailing slash here to simplify template
- context["path"] = "/".join(location) + "/"
- context["in_category"] = True
- elif full_location.with_suffix(".md").is_file():
- article_result = utils.get_article(location)
-
- if len(location) > 1:
- context["category_data"] = utils.get_category(location[:-1])
- context["category_data"]["raw_name"] = location[:-1][-1]
- else:
- context["category_data"] = {"name": None, "raw_name": None}
-
- context["article"] = article_result
- context["relevant_links"] = article_result["metadata"].get("relevant_links", {})
- else:
- raise Http404
-
- location.pop()
- breadcrumb_items = []
- while len(location):
- breadcrumb_items.insert(
- 0,
- {
- "name": utils.get_category(location)["name"],
- "path": "/".join(location)
- }
- )
- location.pop()
-
- context["breadcrumb_items"] = breadcrumb_items
-
- return context
diff --git a/pydis_site/apps/content/views/articles.py b/pydis_site/apps/content/views/articles.py
deleted file mode 100644
index 999002d0..00000000
--- a/pydis_site/apps/content/views/articles.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from django.views.generic import TemplateView
-
-from pydis_site.apps.content.utils import get_articles, get_categories
-
-
-class ArticlesView(TemplateView):
- """Shows all content and categories."""
-
- template_name = "content/listing.html"
-
- def get_context_data(self, **kwargs) -> dict:
- """Add articles and categories data to template context."""
- context = super().get_context_data(**kwargs)
- context["content"] = get_articles()
- context["categories"] = get_categories()
- return context
diff --git a/pydis_site/apps/content/views/page_category.py b/pydis_site/apps/content/views/page_category.py
new file mode 100644
index 00000000..f00a79ee
--- /dev/null
+++ b/pydis_site/apps/content/views/page_category.py
@@ -0,0 +1,69 @@
+import typing as t
+
+from django.conf import settings
+from django.http import Http404
+from django.views.generic import TemplateView
+
+from pydis_site.apps.content import utils
+
+
+class PageOrCategoryView(TemplateView):
+ """Handles pages and page categories."""
+
+ def get_template_names(self) -> t.List[str]:
+ """Checks does this use page template or listing template."""
+ location = self.kwargs["location"].split("/")
+ full_location = settings.PAGES_PATH.joinpath(*location)
+
+ if full_location.is_dir():
+ template_name = "content/listing.html"
+ elif full_location.with_suffix(".md").is_file():
+ template_name = "content/page.html"
+ else:
+ raise Http404
+
+ return [template_name]
+
+ def get_context_data(self, **kwargs) -> t.Dict[str, t.Any]:
+ """Assign proper context variables based on what resource user requests."""
+ context = super().get_context_data(**kwargs)
+
+ location: list = self.kwargs["location"].split("/")
+ full_location = settings.PAGES_PATH.joinpath(*location)
+
+ if full_location.is_dir():
+ context["category_info"] = utils.get_category(location)
+ context["content"] = utils.get_pages(location)
+ context["categories"] = utils.get_categories(location)
+ # Add trailing slash here to simplify template
+ context["path"] = "/".join(location) + "/"
+ context["in_category"] = True
+ elif full_location.with_suffix(".md").is_file():
+ page_result = utils.get_page(location)
+
+ if len(location) > 1:
+ context["category_data"] = utils.get_category(location[:-1])
+ context["category_data"]["raw_name"] = location[:-1][-1]
+ else:
+ context["category_data"] = {"name": None, "raw_name": None}
+
+ context["page"] = page_result
+ context["relevant_links"] = page_result["metadata"].get("relevant_links", {})
+ else:
+ raise Http404
+
+ location.pop()
+ breadcrumb_items = []
+ while len(location):
+ breadcrumb_items.insert(
+ 0,
+ {
+ "name": utils.get_category(location)["name"],
+ "path": "/".join(location)
+ }
+ )
+ location.pop()
+
+ context["breadcrumb_items"] = breadcrumb_items
+
+ return context
diff --git a/pydis_site/apps/content/views/pages.py b/pydis_site/apps/content/views/pages.py
new file mode 100644
index 00000000..11ac0eeb
--- /dev/null
+++ b/pydis_site/apps/content/views/pages.py
@@ -0,0 +1,16 @@
+from django.views.generic import TemplateView
+
+from pydis_site.apps.content.utils import get_pages, get_categories
+
+
+class PagesView(TemplateView):
+ """Shows all pages and categories."""
+
+ template_name = "content/listing.html"
+
+ def get_context_data(self, **kwargs) -> dict:
+ """Add page and category data to template context."""
+ context = super().get_context_data(**kwargs)
+ context["content"] = get_pages()
+ context["categories"] = get_categories()
+ return context
diff --git a/pydis_site/apps/events/urls.py b/pydis_site/apps/events/urls.py
index 9a65cf1f..601451da 100644
--- a/pydis_site/apps/events/urls.py
+++ b/pydis_site/apps/events/urls.py
@@ -1,9 +1,9 @@
from django.urls import path
-from pydis_site.apps.events.views import IndexView, PageView
+from pydis_site.apps.events.views import IndexView, PagesView
app_name = "events"
urlpatterns = [
path("", IndexView.as_view(), name="index"),
- path("/", PageView.as_view(), name="page"),
+ path("/", PagesView.as_view(), name="page"),
]
diff --git a/pydis_site/apps/events/views/__init__.py b/pydis_site/apps/events/views/__init__.py
index 8a107e2f..6188f723 100644
--- a/pydis_site/apps/events/views/__init__.py
+++ b/pydis_site/apps/events/views/__init__.py
@@ -1,4 +1,4 @@
from .index import IndexView
-from .page import PageView
+from .page import PagesView
-__all__ = ["IndexView", "PageView"]
+__all__ = ["IndexView", "PagesView"]
diff --git a/pydis_site/apps/events/views/page.py b/pydis_site/apps/events/views/page.py
index f4c37aeb..fbedd4e8 100644
--- a/pydis_site/apps/events/views/page.py
+++ b/pydis_site/apps/events/views/page.py
@@ -5,7 +5,7 @@ from django.http import Http404
from django.views.generic import TemplateView
-class PageView(TemplateView):
+class PagesView(TemplateView):
"""Handles event pages showing."""
def get_template_names(self) -> List[str]:
diff --git a/pydis_site/apps/home/urls.py b/pydis_site/apps/home/urls.py
index bd7c0625..3c716875 100644
--- a/pydis_site/apps/home/urls.py
+++ b/pydis_site/apps/home/urls.py
@@ -8,6 +8,6 @@ urlpatterns = [
path('', HomeView.as_view(), name='home'),
path('admin/', admin.site.urls),
path('resources/', include('pydis_site.apps.resources.urls')),
- path('articles/', include('pydis_site.apps.content.urls')),
+ path('pages/', include('pydis_site.apps.content.urls')),
path('events/', include('pydis_site.apps.events.urls', namespace='events')),
]
diff --git a/pydis_site/settings.py b/pydis_site/settings.py
index d509d980..0b4d9fd1 100644
--- a/pydis_site/settings.py
+++ b/pydis_site/settings.py
@@ -287,4 +287,4 @@ SITE_REPOSITORY_OWNER = "python-discord"
SITE_REPOSITORY_NAME = "site"
SITE_REPOSITORY_BRANCH = "master"
-ARTICLES_PATH = Path(BASE_DIR, "pydis_site", "apps", "content", "resources", "content")
+PAGES_PATH = Path(BASE_DIR, "pydis_site", "apps", "content", "resources", "content")
diff --git a/pydis_site/static/css/content/articles.css b/pydis_site/static/css/content/articles.css
deleted file mode 100644
index f46d6b15..00000000
--- a/pydis_site/static/css/content/articles.css
+++ /dev/null
@@ -1,16 +0,0 @@
-.breadcrumb-section {
- padding: 1rem;
-}
-
-i.has-icon-padding {
- padding: 0 10px 25px 0;
-}
-
-pre {
- /*
- * Style it the same as the tag, since highlight.js does not style
- * backgrounds of tags but bulma does, resulting in a weird off-white
- * border.
- */
- background-color: #282c34;
-}
diff --git a/pydis_site/static/css/content/page.css b/pydis_site/static/css/content/page.css
new file mode 100644
index 00000000..f46d6b15
--- /dev/null
+++ b/pydis_site/static/css/content/page.css
@@ -0,0 +1,16 @@
+.breadcrumb-section {
+ padding: 1rem;
+}
+
+i.has-icon-padding {
+ padding: 0 10px 25px 0;
+}
+
+pre {
+ /*
+ * Style it the same as the tag, since highlight.js does not style
+ * backgrounds of tags but bulma does, resulting in a weird off-white
+ * border.
+ */
+ background-color: #282c34;
+}
diff --git a/pydis_site/templates/content/article.html b/pydis_site/templates/content/article.html
deleted file mode 100644
index 69d01a8d..00000000
--- a/pydis_site/templates/content/article.html
+++ /dev/null
@@ -1,58 +0,0 @@
-{% extends 'base/base.html' %}
-{% load static %}
-
-{% block title %}{{ article.metadata.title }}{% endblock %}
-{% block head %}
-
-
-
-
-
-
-
-{% endblock %}
-
-{% block content %}
- {% include "base/navbar.html" %}
-
-
-
-
-
-
-
{{ article.metadata.title }}
-
-
- {{ article.article|safe }}
-
-
- {% if relevant_links|length > 0 %}
-
-
-
-
- {% endif %}
-
-
-
-
-
-
-{% endblock %}
diff --git a/pydis_site/templates/content/listing.html b/pydis_site/templates/content/listing.html
index 8c06bccc..39eae1c2 100644
--- a/pydis_site/templates/content/listing.html
+++ b/pydis_site/templates/content/listing.html
@@ -1,12 +1,12 @@
{% extends 'base/base.html' %}
{% load static %}
-{% block title %}{{ category_info.name|default:"Articles" }}{% endblock %}
+{% block title %}{{ category_info.name|default:"Pages" }}{% endblock %}
{% block head %}
-
+
-
+
{% endblock %}
{% block content %}
@@ -17,12 +17,12 @@
@@ -31,7 +31,7 @@
-
{{ category_info.name|default:"Articles" }}
+
{{ category_info.name|default:"Pages" }}
{% for category, data in categories.items %}
{% endfor %}
- {% for article, data in content.items %}
+ {% for page, data in content.items %}
-
+
{{ data.title }}
{{ data.short_description }}
diff --git a/pydis_site/templates/content/page.html b/pydis_site/templates/content/page.html
new file mode 100644
index 00000000..3b0ebb5f
--- /dev/null
+++ b/pydis_site/templates/content/page.html
@@ -0,0 +1,58 @@
+{% extends 'base/base.html' %}
+{% load static %}
+
+{% block title %}{{ page.metadata.title }}{% endblock %}
+{% block head %}
+
+
+
+
+
+
+
+{% endblock %}
+
+{% block content %}
+ {% include "base/navbar.html" %}
+
+
+
+
+
+
+
{{ page.metadata.title }}
+
+
+ {{ page.page|safe }}
+
+
+ {% if relevant_links|length > 0 %}
+
+
+
+
+ {% endif %}
+
+
+
+
+
+
+{% endblock %}
diff --git a/pydis_site/templates/resources/resources.html b/pydis_site/templates/resources/resources.html
index 2dc88a8c..491bc55e 100644
--- a/pydis_site/templates/resources/resources.html
+++ b/pydis_site/templates/resources/resources.html
@@ -15,7 +15,7 @@
Resources
-
+
Guides
Made by us, for you
--
cgit v1.2.3
From 82daedc766dc3986dc9ac17ea8a6b3da87a6b1ac Mon Sep 17 00:00:00 2001
From: kosayoda
Date: Tue, 23 Mar 2021 23:17:55 +0800
Subject: Simplify content app.
Rather than having two views for the base page and all other pages, all
pages now use the same view.
The view context handler is simplified to take advantage of pathlib
features.
The markdown folder is now /content/resources/* rather than
/content/resources/content/*, as the latter is unnecessary nesting.
---
pydis_site/apps/content/resources/_info.yml | 2 +
.../content/resources/content/guides/_info.yml | 2 -
.../content/guides/pydis-guides/_info.yml | 2 -
.../guides/pydis-guides/how-to-write-a-article.md | 80 ----------------------
pydis_site/apps/content/resources/guides/_info.yml | 2 +
.../resources/guides/pydis-guides/_info.yml | 2 +
.../guides/pydis-guides/how-to-write-a-article.md | 80 ++++++++++++++++++++++
pydis_site/apps/content/urls.py | 2 +-
pydis_site/apps/content/utils.py | 42 ++++--------
pydis_site/apps/content/views/__init__.py | 3 +-
pydis_site/apps/content/views/page_category.py | 61 +++++++----------
pydis_site/apps/content/views/pages.py | 16 -----
pydis_site/settings.py | 2 +-
pydis_site/templates/content/listing.html | 5 +-
pydis_site/templates/content/page.html | 1 -
15 files changed, 127 insertions(+), 175 deletions(-)
create mode 100644 pydis_site/apps/content/resources/_info.yml
delete mode 100644 pydis_site/apps/content/resources/content/guides/_info.yml
delete mode 100644 pydis_site/apps/content/resources/content/guides/pydis-guides/_info.yml
delete mode 100644 pydis_site/apps/content/resources/content/guides/pydis-guides/how-to-write-a-article.md
create mode 100644 pydis_site/apps/content/resources/guides/_info.yml
create mode 100644 pydis_site/apps/content/resources/guides/pydis-guides/_info.yml
create mode 100644 pydis_site/apps/content/resources/guides/pydis-guides/how-to-write-a-article.md
delete mode 100644 pydis_site/apps/content/views/pages.py
(limited to 'pydis_site')
diff --git a/pydis_site/apps/content/resources/_info.yml b/pydis_site/apps/content/resources/_info.yml
new file mode 100644
index 00000000..4ccdd7e1
--- /dev/null
+++ b/pydis_site/apps/content/resources/_info.yml
@@ -0,0 +1,2 @@
+name: Pages
+description: Guides, articles and pages hosted on the site.
diff --git a/pydis_site/apps/content/resources/content/guides/_info.yml b/pydis_site/apps/content/resources/content/guides/_info.yml
deleted file mode 100644
index 369f05d4..00000000
--- a/pydis_site/apps/content/resources/content/guides/_info.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-name: Guides
-description: Python and PyDis guides.
diff --git a/pydis_site/apps/content/resources/content/guides/pydis-guides/_info.yml b/pydis_site/apps/content/resources/content/guides/pydis-guides/_info.yml
deleted file mode 100644
index 64111a83..00000000
--- a/pydis_site/apps/content/resources/content/guides/pydis-guides/_info.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-name: Python Discord Guides
-description: Python Discord server and community guides.
diff --git a/pydis_site/apps/content/resources/content/guides/pydis-guides/how-to-write-a-article.md b/pydis_site/apps/content/resources/content/guides/pydis-guides/how-to-write-a-article.md
deleted file mode 100644
index ec89988c..00000000
--- a/pydis_site/apps/content/resources/content/guides/pydis-guides/how-to-write-a-article.md
+++ /dev/null
@@ -1,80 +0,0 @@
----
-title: How to Write a Article
-short_description: Learn how to write a article for this website
-icon_class: fas
-icon: fa-info
----
-
-When you are interested about how to write articles for this site (like this), then you can learn about it here.
-PyDis use Markdown (GitHub Markdown) files for articles.
-
-## Getting Started
-Before you can get started with writing a article, you need idea.
-Best way to find out is your idea good is to discuss about it in #dev-contrib channel. There can other peoples give their opinion about your idea. Even better, open issue in site repository first, then PyDis staff can see it and approve/decline this idea.
-It's good idea to wait for staff decision before starting to write guide to avoid case when you write a long long article, but then this don't get approved.
-
-To start with contributing, you should read [how to contribute to site](https://pythondiscord.com/pages/contributing/site/).
-You should also read our [Git workflow](https://pythondiscord.com/pages/contributing/working-with-git/), because you need to push your guide to GitHub.
-
-## Creating a File
-All articles is located at `site` repository, in `pydis_site/apps/content/resources/content`. Under this is root level articles (.md files) and categories (directories). Learn more about categories in [categories section](#categories).
-
-When you are writing guides, then these are located under `guides` category.
-
-At this point, you will need your article name for filename. Replace all your article name spaces with `-` and make all lowercase. Save this as `.md` (Markdown) file. This name (without Markdown extension) is path of article in URL.
-
-## Markdown Metadata
-Article files have some required metadata, like title, description, relevant pages. Metadata is first thing in file, YAML-like key-value pairs:
-
-```md
----
-title: My Article
-short_description: This is my short description.
-relevant_links: url1,url2,url3
-relevant_link_values: Text for url1,Text for url2,Text for url3
----
-
-Here comes content of article...
-```
-
-You can read more about Markdown metadata [here](https://github.com/trentm/python-markdown2/wiki/metadata).
-
-### Fields
-- **Name:** Easily-readable name for your article.
-- **Short Description:** Small, 1-2 line description that describe what your article explain.
-- **Relevant Links and Values:** URLs and values is under different fields, separated with comma.
-- **Icon class:** `icon_class` field have one of the favicons classes. Default is `fab`.
-- **Icon:** `icon` field have favicon name. Default `fa-python`.
-
-## Content
-For content, mostly you can use standard markdown, but there is a few addition that is available.
-
-### IDs for quick jumps
-System automatically assign IDs to headers, so like this header will get ID `ids-for-quick-jumps`.
-
-### Tables
-Tables like in GitHub is supported too:
-
-| This is header | This is too header |
-| -------------- | ------------------ |
-| My item | My item too |
-
-### Codeblocks
-Also this system supports codeblocks and provides syntax highlighting with `highlight.js`.
-To activate syntax highlight, just put language directly after starting backticks.
-
-```py
-import os
-
-path = os.path.join("foo", "bar")
-```
-
-## Categories
-To have some systematic sorting of guides, site support guides categories. Currently this system support only 1 level of categories. Categories live at `site` repo in `pydis_site/apps/content/resources/content` subdirectories. Directory name is path of category in URL. Inside category directory, there is 1 file required: `_info.yml`. This file need 2 key-value pairs defined:
-
-```yml
-name: Category name
-description: Category description
-```
-
-Then all Markdown files in this folder will be under this category.
diff --git a/pydis_site/apps/content/resources/guides/_info.yml b/pydis_site/apps/content/resources/guides/_info.yml
new file mode 100644
index 00000000..369f05d4
--- /dev/null
+++ b/pydis_site/apps/content/resources/guides/_info.yml
@@ -0,0 +1,2 @@
+name: Guides
+description: Python and PyDis guides.
diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/_info.yml b/pydis_site/apps/content/resources/guides/pydis-guides/_info.yml
new file mode 100644
index 00000000..64111a83
--- /dev/null
+++ b/pydis_site/apps/content/resources/guides/pydis-guides/_info.yml
@@ -0,0 +1,2 @@
+name: Python Discord Guides
+description: Python Discord server and community guides.
diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/how-to-write-a-article.md b/pydis_site/apps/content/resources/guides/pydis-guides/how-to-write-a-article.md
new file mode 100644
index 00000000..ec89988c
--- /dev/null
+++ b/pydis_site/apps/content/resources/guides/pydis-guides/how-to-write-a-article.md
@@ -0,0 +1,80 @@
+---
+title: How to Write a Article
+short_description: Learn how to write a article for this website
+icon_class: fas
+icon: fa-info
+---
+
+When you are interested about how to write articles for this site (like this), then you can learn about it here.
+PyDis use Markdown (GitHub Markdown) files for articles.
+
+## Getting Started
+Before you can get started with writing a article, you need idea.
+Best way to find out is your idea good is to discuss about it in #dev-contrib channel. There can other peoples give their opinion about your idea. Even better, open issue in site repository first, then PyDis staff can see it and approve/decline this idea.
+It's good idea to wait for staff decision before starting to write guide to avoid case when you write a long long article, but then this don't get approved.
+
+To start with contributing, you should read [how to contribute to site](https://pythondiscord.com/pages/contributing/site/).
+You should also read our [Git workflow](https://pythondiscord.com/pages/contributing/working-with-git/), because you need to push your guide to GitHub.
+
+## Creating a File
+All articles is located at `site` repository, in `pydis_site/apps/content/resources/content`. Under this is root level articles (.md files) and categories (directories). Learn more about categories in [categories section](#categories).
+
+When you are writing guides, then these are located under `guides` category.
+
+At this point, you will need your article name for filename. Replace all your article name spaces with `-` and make all lowercase. Save this as `.md` (Markdown) file. This name (without Markdown extension) is path of article in URL.
+
+## Markdown Metadata
+Article files have some required metadata, like title, description, relevant pages. Metadata is first thing in file, YAML-like key-value pairs:
+
+```md
+---
+title: My Article
+short_description: This is my short description.
+relevant_links: url1,url2,url3
+relevant_link_values: Text for url1,Text for url2,Text for url3
+---
+
+Here comes content of article...
+```
+
+You can read more about Markdown metadata [here](https://github.com/trentm/python-markdown2/wiki/metadata).
+
+### Fields
+- **Name:** Easily-readable name for your article.
+- **Short Description:** Small, 1-2 line description that describe what your article explain.
+- **Relevant Links and Values:** URLs and values is under different fields, separated with comma.
+- **Icon class:** `icon_class` field have one of the favicons classes. Default is `fab`.
+- **Icon:** `icon` field have favicon name. Default `fa-python`.
+
+## Content
+For content, mostly you can use standard markdown, but there is a few addition that is available.
+
+### IDs for quick jumps
+System automatically assign IDs to headers, so like this header will get ID `ids-for-quick-jumps`.
+
+### Tables
+Tables like in GitHub is supported too:
+
+| This is header | This is too header |
+| -------------- | ------------------ |
+| My item | My item too |
+
+### Codeblocks
+Also this system supports codeblocks and provides syntax highlighting with `highlight.js`.
+To activate syntax highlight, just put language directly after starting backticks.
+
+```py
+import os
+
+path = os.path.join("foo", "bar")
+```
+
+## Categories
+To have some systematic sorting of guides, site support guides categories. Currently this system support only 1 level of categories. Categories live at `site` repo in `pydis_site/apps/content/resources/content` subdirectories. Directory name is path of category in URL. Inside category directory, there is 1 file required: `_info.yml`. This file need 2 key-value pairs defined:
+
+```yml
+name: Category name
+description: Category description
+```
+
+Then all Markdown files in this folder will be under this category.
diff --git a/pydis_site/apps/content/urls.py b/pydis_site/apps/content/urls.py
index 1406f672..c11b222a 100644
--- a/pydis_site/apps/content/urls.py
+++ b/pydis_site/apps/content/urls.py
@@ -4,6 +4,6 @@ from . import views
app_name = "content"
urlpatterns = [
- path("", views.PagesView.as_view(), name='pages'),
+ path("", views.PageOrCategoryView.as_view(), name='pages'),
path("/", views.PageOrCategoryView.as_view(), name='page_category'),
]
diff --git a/pydis_site/apps/content/utils.py b/pydis_site/apps/content/utils.py
index db502a71..ef02a8cb 100644
--- a/pydis_site/apps/content/utils.py
+++ b/pydis_site/apps/content/utils.py
@@ -1,65 +1,49 @@
-import os
-from typing import Dict, List, Optional, Union
+from pathlib import Path
+from typing import Dict, Union
import yaml
-from django.conf import settings
from django.http import Http404
from markdown2 import markdown
-def get_category(path: List[str]) -> Dict[str, str]:
+def get_category(path: Path) -> Dict[str, str]:
"""Load category information by name from _info.yml."""
- path = settings.PAGES_PATH.joinpath(*path)
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(path: Optional[List[str]] = None) -> Dict[str, Dict]:
+def get_categories(path: Path) -> Dict[str, Dict]:
"""Get all categories information."""
categories = {}
- if path is None:
- categories_path = settings.PAGES_PATH
- path = []
- else:
- categories_path = settings.PAGES_PATH.joinpath(*path)
- for name in categories_path.iterdir():
+ for name in path.iterdir():
if name.is_dir():
- categories[name.name] = get_category([*path, name.name])
+ categories[name.name] = get_category(path.joinpath(name.name))
return categories
-def get_pages(path: Optional[List[str]] = None) -> Dict[str, Dict]:
- """Get all root or category pages."""
- if path is None:
- base_dir = settings.PAGES_PATH
- else:
- base_dir = settings.PAGES_PATH.joinpath(*path)
-
+def get_pages(path: Path) -> Dict[str, Dict]:
+ """Get all root or category page names and their metadata."""
pages = {}
- for item in base_dir.iterdir():
+ for item in path.iterdir():
if item.is_file() and item.name.endswith(".md"):
md = markdown(item.read_text(), extras=["metadata"])
- pages[os.path.splitext(item.name)[0]] = md.metadata
+ pages[item.stem] = md.metadata
return pages
-def get_page(path: List[str]) -> Dict[str, Union[str, Dict]]:
+def get_page(path: Path) -> Dict[str, Union[str, Dict]]:
"""Get one specific page. When category is specified, get it from there."""
- page_path = settings.PAGES_PATH.joinpath(*path[:-1])
-
- # We need to include extension MD
- page_path = page_path.joinpath(f"{path[-1]}.md")
- if not page_path.exists() or not page_path.is_file():
+ if not path.exists() or not path.is_file():
raise Http404("Page not found.")
html = markdown(
- page_path.read_text(),
+ path.read_text(),
extras=[
"metadata",
"fenced-code-blocks",
diff --git a/pydis_site/apps/content/views/__init__.py b/pydis_site/apps/content/views/__init__.py
index 740d98e9..70ea1c7a 100644
--- a/pydis_site/apps/content/views/__init__.py
+++ b/pydis_site/apps/content/views/__init__.py
@@ -1,4 +1,3 @@
from .page_category import PageOrCategoryView
-from .pages import PagesView
-__all__ = ["PageOrCategoryView", "PagesView"]
+__all__ = ["PageOrCategoryView"]
diff --git a/pydis_site/apps/content/views/page_category.py b/pydis_site/apps/content/views/page_category.py
index f00a79ee..7e04e2f3 100644
--- a/pydis_site/apps/content/views/page_category.py
+++ b/pydis_site/apps/content/views/page_category.py
@@ -1,4 +1,5 @@
import typing as t
+from pathlib import Path
from django.conf import settings
from django.http import Http404
@@ -10,14 +11,18 @@ from pydis_site.apps.content import utils
class PageOrCategoryView(TemplateView):
"""Handles pages and page categories."""
+ def dispatch(self, request: t.Any, *args, **kwargs) -> t.Any:
+ """Conform URL path location to the filesystem path."""
+ self.location = Path(self.kwargs.get("location", ""))
+ self.full_location = settings.PAGES_PATH / self.location
+
+ return super().dispatch(request, *args, **kwargs)
+
def get_template_names(self) -> t.List[str]:
"""Checks does this use page template or listing template."""
- location = self.kwargs["location"].split("/")
- full_location = settings.PAGES_PATH.joinpath(*location)
-
- if full_location.is_dir():
+ if self.full_location.is_dir():
template_name = "content/listing.html"
- elif full_location.with_suffix(".md").is_file():
+ elif self.full_location.with_suffix(".md").is_file():
template_name = "content/page.html"
else:
raise Http404
@@ -28,42 +33,24 @@ class PageOrCategoryView(TemplateView):
"""Assign proper context variables based on what resource user requests."""
context = super().get_context_data(**kwargs)
- location: list = self.kwargs["location"].split("/")
- full_location = settings.PAGES_PATH.joinpath(*location)
-
- if full_location.is_dir():
- context["category_info"] = utils.get_category(location)
- context["content"] = utils.get_pages(location)
- context["categories"] = utils.get_categories(location)
- # Add trailing slash here to simplify template
- context["path"] = "/".join(location) + "/"
- context["in_category"] = True
- elif full_location.with_suffix(".md").is_file():
- page_result = utils.get_page(location)
-
- if len(location) > 1:
- context["category_data"] = utils.get_category(location[:-1])
- context["category_data"]["raw_name"] = location[:-1][-1]
- else:
- context["category_data"] = {"name": None, "raw_name": None}
-
+ if self.full_location.is_dir():
+ context["categories"] = utils.get_categories(self.full_location)
+ context["category_info"] = utils.get_category(self.full_location)
+ context["content"] = utils.get_pages(self.full_location)
+ context["path"] = f"{self.location}/" # Add trailing slash here to simplify template
+ elif self.full_location.with_suffix(".md").is_file():
+ page_result = utils.get_page(self.full_location.with_suffix(".md"))
context["page"] = page_result
context["relevant_links"] = page_result["metadata"].get("relevant_links", {})
else:
raise Http404
- location.pop()
- breadcrumb_items = []
- while len(location):
- breadcrumb_items.insert(
- 0,
- {
- "name": utils.get_category(location)["name"],
- "path": "/".join(location)
- }
- )
- location.pop()
-
- context["breadcrumb_items"] = breadcrumb_items
+ breadcrumb_items = [
+ {
+ "name": utils.get_category(settings.PAGES_PATH / location)["name"],
+ "path": str(location)
+ } for location in self.location.parents
+ ]
+ context["breadcrumb_items"] = reversed(breadcrumb_items)
return context
diff --git a/pydis_site/apps/content/views/pages.py b/pydis_site/apps/content/views/pages.py
deleted file mode 100644
index 11ac0eeb..00000000
--- a/pydis_site/apps/content/views/pages.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from django.views.generic import TemplateView
-
-from pydis_site.apps.content.utils import get_pages, get_categories
-
-
-class PagesView(TemplateView):
- """Shows all pages and categories."""
-
- template_name = "content/listing.html"
-
- def get_context_data(self, **kwargs) -> dict:
- """Add page and category data to template context."""
- context = super().get_context_data(**kwargs)
- context["content"] = get_pages()
- context["categories"] = get_categories()
- return context
diff --git a/pydis_site/settings.py b/pydis_site/settings.py
index 0b4d9fd1..3abf556a 100644
--- a/pydis_site/settings.py
+++ b/pydis_site/settings.py
@@ -287,4 +287,4 @@ SITE_REPOSITORY_OWNER = "python-discord"
SITE_REPOSITORY_NAME = "site"
SITE_REPOSITORY_BRANCH = "master"
-PAGES_PATH = Path(BASE_DIR, "pydis_site", "apps", "content", "resources", "content")
+PAGES_PATH = Path(BASE_DIR, "pydis_site", "apps", "content", "resources")
diff --git a/pydis_site/templates/content/listing.html b/pydis_site/templates/content/listing.html
index 39eae1c2..097cac4f 100644
--- a/pydis_site/templates/content/listing.html
+++ b/pydis_site/templates/content/listing.html
@@ -16,13 +16,10 @@
diff --git a/pydis_site/templates/content/page.html b/pydis_site/templates/content/page.html
index 3b0ebb5f..433baa69 100644
--- a/pydis_site/templates/content/page.html
+++ b/pydis_site/templates/content/page.html
@@ -20,7 +20,6 @@
- Pages
{% for item in breadcrumb_items %}
{{ item.name }}
{% endfor %}
--
cgit v1.2.3
From b926b702297e0da6a167c1a5fd024e3e23425f4d Mon Sep 17 00:00:00 2001
From: kosayoda
Date: Wed, 24 Mar 2021 00:14:57 +0800
Subject: Fix content app tests.
---
.../apps/content/tests/test_content/_info.yml | 2 +
pydis_site/apps/content/tests/test_content/test.md | 6 ++-
pydis_site/apps/content/tests/test_utils.py | 50 +++++++++++-----------
pydis_site/apps/content/tests/test_views.py | 24 +++--------
4 files changed, 37 insertions(+), 45 deletions(-)
create mode 100644 pydis_site/apps/content/tests/test_content/_info.yml
(limited to 'pydis_site')
diff --git a/pydis_site/apps/content/tests/test_content/_info.yml b/pydis_site/apps/content/tests/test_content/_info.yml
new file mode 100644
index 00000000..ad5fc113
--- /dev/null
+++ b/pydis_site/apps/content/tests/test_content/_info.yml
@@ -0,0 +1,2 @@
+name: Base Category
+description: Base Description
diff --git a/pydis_site/apps/content/tests/test_content/test.md b/pydis_site/apps/content/tests/test_content/test.md
index 175c1fdb..ca06c1d5 100644
--- a/pydis_site/apps/content/tests/test_content/test.md
+++ b/pydis_site/apps/content/tests/test_content/test.md
@@ -1,8 +1,10 @@
---
title: Test
short_description: Testing
-relevant_links: https://pythondiscord.com/pages/resources/guides/asking-good-questions/,https://pythondiscord.com/pages/resources/guides/help-channels/,https://pythondiscord.com/pages/code-of-conduct/
-relevant_link_values: Asking Good Questions,Help Channel Guide,Code of Conduct
+relevant_links:
+ Asking Good Questions: https://pythondiscord.com/pages/resources/guides/asking-good-questions/
+ Help Channel Guide: https://pythondiscord.com/pages/resources/guides/help-channels/
+ Code of Conduct: https://pythondiscord.com/pages/code-of-conduct/
---
This is test content.
diff --git a/pydis_site/apps/content/tests/test_utils.py b/pydis_site/apps/content/tests/test_utils.py
index e1f1b92a..3831ad33 100644
--- a/pydis_site/apps/content/tests/test_utils.py
+++ b/pydis_site/apps/content/tests/test_utils.py
@@ -1,6 +1,5 @@
-from datetime import datetime
from pathlib import Path
-from unittest.mock import MagicMock, patch
+from unittest.mock import patch
from django.conf import settings
from django.http import Http404
@@ -16,7 +15,8 @@ class TestGetCategory(TestCase):
@override_settings(PAGES_PATH=BASE_PATH)
def test_get_category_successfully(self):
"""Check does this get right data from category data file."""
- result = utils.get_category(["category"])
+ path = BASE_PATH.joinpath("category")
+ result = utils.get_category(path)
self.assertEqual(result, {"name": "My Category", "description": "My Description"})
@@ -24,13 +24,15 @@ class TestGetCategory(TestCase):
def test_get_category_not_exists(self):
"""Check does this raise 404 error when category don't exists."""
with self.assertRaises(Http404):
- utils.get_category(["invalid"])
+ path = BASE_PATH.joinpath("invalid")
+ utils.get_category(path)
@override_settings(PAGES_PATH=BASE_PATH)
def test_get_category_not_directory(self):
"""Check does this raise 404 error when category isn't directory."""
with self.assertRaises(Http404):
- utils.get_category(["test.md"])
+ path = BASE_PATH.joinpath("test.md")
+ utils.get_category(path)
class TestGetCategories(TestCase):
@@ -40,25 +42,18 @@ class TestGetCategories(TestCase):
"""Check does this return test content categories."""
get_category_mock.return_value = {"name": "My Category", "description": "My Description"}
- result = utils.get_categories()
- get_category_mock.assert_called_once_with(["category"])
+ path = BASE_PATH.joinpath("category")
+ result = utils.get_categories(path)
self.assertEqual(
- result, {"category": {"name": "My Category", "description": "My Description"}}
- )
-
- @override_settings(PAGES_PATH=BASE_PATH)
- def test_get_categories_root_path(self):
- """Check does this doesn't call joinpath when getting root categories."""
- result = utils.get_categories()
- self.assertEqual(
- result, {"category": {"name": "My Category", "description": "My Description"}}
+ result, {"subcategory": {"name": "My Category", "description": "My Description"}}
)
@override_settings(PAGES_PATH=BASE_PATH)
def test_get_categories_in_category(self):
"""Check does this call joinpath when getting subcategories."""
- result = utils.get_categories(["category"])
+ path = BASE_PATH.joinpath("category")
+ result = utils.get_categories(path)
self.assertEqual(
result, {"subcategory": {"name": "My Category 1", "description": "My Description 1"}}
)
@@ -68,7 +63,8 @@ class TestGetPages(TestCase):
@override_settings(PAGES_PATH=BASE_PATH)
def test_get_all_root_pages(self):
"""Check does this return all root level testing content."""
- result = utils.get_pages()
+ path = BASE_PATH
+ result = utils.get_pages(path)
for case in ["test", "test2"]:
with self.subTest(guide=case):
@@ -80,7 +76,8 @@ class TestGetPages(TestCase):
@override_settings(PAGES_PATH=BASE_PATH)
def test_get_all_category_pages(self):
"""Check does this return all category testing content."""
- result = utils.get_pages(["category"])
+ path = BASE_PATH.joinpath("category")
+ result = utils.get_pages(path)
md = markdown(BASE_PATH.joinpath("category", "test3.md").read_text(), extras=["metadata"])
@@ -92,7 +89,8 @@ class TestGetPage(TestCase):
@override_settings(PAGES_PATH=BASE_PATH)
def test_get_root_page_success(self):
"""Check does this return page HTML and metadata when root page exist."""
- result = utils.get_page(["test"])
+ path = BASE_PATH.joinpath("test.md")
+ result = utils.get_page(path)
md = markdown(
BASE_PATH.joinpath("test.md").read_text(),
@@ -113,12 +111,14 @@ class TestGetPage(TestCase):
def test_get_root_page_dont_exist(self):
"""Check does this raise Http404 when root page don't exist."""
with self.assertRaises(Http404):
- utils.get_page(["invalid"])
+ path = BASE_PATH.joinpath("invalid")
+ utils.get_page(path)
@override_settings(PAGES_PATH=BASE_PATH)
def test_get_category_page_success(self):
"""Check does this return page HTML and metadata when category guide exist."""
- result = utils.get_page(["category", "test3"])
+ path = BASE_PATH.joinpath("category", "test3.md")
+ result = utils.get_page(path)
md = markdown(
BASE_PATH.joinpath("category", "test3.md").read_text(),
@@ -139,10 +139,12 @@ class TestGetPage(TestCase):
def test_get_category_page_dont_exist(self):
"""Check does this raise Http404 when category page don't exist."""
with self.assertRaises(Http404):
- utils.get_page(["category", "invalid"])
+ path = BASE_PATH.joinpath("category", "invalid")
+ utils.get_page(path)
@patch("pydis_site.settings.PAGES_PATH", new=BASE_PATH)
def test_get_category_page_category_dont_exist(self):
"""Check does this raise Http404 when category don't exist."""
with self.assertRaises(Http404):
- utils.get_page(["invalid", "some-guide"])
+ path = BASE_PATH.joinpath("invalid", "some-guide")
+ utils.get_page(path)
diff --git a/pydis_site/apps/content/tests/test_views.py b/pydis_site/apps/content/tests/test_views.py
index 5ce18afb..c61671a2 100644
--- a/pydis_site/apps/content/tests/test_views.py
+++ b/pydis_site/apps/content/tests/test_views.py
@@ -11,33 +11,17 @@ from pydis_site.apps.content.views import PageOrCategoryView
BASE_PATH = Path(settings.BASE_DIR, "pydis_site", "apps", "content", "tests", "test_content")
-class TestPagesIndexView(TestCase):
- @patch("pydis_site.apps.content.views.pages.get_pages")
- @patch("pydis_site.apps.content.views.pages.get_categories")
- def test_pages_index_return_200(self, get_categories_mock, get_page_mock):
- """Check that content index return HTTP code 200."""
- get_categories_mock.return_value = {}
- get_page_mock.return_value = {}
-
- url = reverse('content:pages')
- response = self.client.get(url)
- self.assertEqual(response.status_code, 200)
- get_page_mock.assert_called_once()
- get_categories_mock.assert_called_once()
-
-
class TestPageOrCategoryView(TestCase):
@override_settings(PAGES_PATH=BASE_PATH)
@patch("pydis_site.apps.content.views.page_category.utils.get_page")
@patch("pydis_site.apps.content.views.page_category.utils.get_category")
- @patch("pydis_site.apps.content.views.page_category.utils.get_github_information")
def test_page_return_code_200(self, get_category_mock, get_page_mock):
get_page_mock.return_value = {"guide": "test", "metadata": {}}
url = reverse("content:page_category", args=["test2"])
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
- get_category_mock.assert_not_called()
+ get_category_mock.assert_called_once()
get_page_mock.assert_called_once()
@patch("pydis_site.apps.content.views.page_category.utils.get_page")
@@ -72,7 +56,7 @@ class TestPageOrCategoryView(TestCase):
self.assertEqual(response.status_code, 200)
get_pages_mock.assert_called_once()
- get_category_mock.assert_called_once()
+ self.assertEqual(get_category_mock.call_count, 2)
get_categories_mock.assert_called_once()
@patch("pydis_site.apps.content.views.page_category.utils.get_category")
@@ -145,7 +129,9 @@ class TestPageOrCategoryView(TestCase):
request = factory.get(f"/pages/{case['location']}")
instance = PageOrCategoryView()
instance.request = request
- instance.kwargs = {"location": case["location"]}
+ location = Path(case["location"])
+ instance.location = location
+ instance.full_location = BASE_PATH / location
if "raises" in case:
with self.assertRaises(case["raises"]):
--
cgit v1.2.3
From b3a48b8b9056a7620f06282cb45a4a9eef9616fa Mon Sep 17 00:00:00 2001
From: kosayoda
Date: Wed, 24 Mar 2021 00:54:04 +0800
Subject: Fix content columns when there is no sidebar.
If the `relevant_links` field is not provided in the markdown, do not
restrict contents to 2/3 columns.
---
pydis_site/templates/content/page.html | 33 ++++++++++++++++++---------------
1 file changed, 18 insertions(+), 15 deletions(-)
(limited to 'pydis_site')
diff --git a/pydis_site/templates/content/page.html b/pydis_site/templates/content/page.html
index 433baa69..a687933d 100644
--- a/pydis_site/templates/content/page.html
+++ b/pydis_site/templates/content/page.html
@@ -33,23 +33,26 @@
{{ page.metadata.title }}
-
-
- {{ page.page|safe }}
-
-
- {% if relevant_links|length > 0 %}
-
-
-
+
+ {% if relevant_links|length > 0 %}
+
+
+ {{ page.page|safe }}
+
+
- {% endif %}
-
+ {% else %}
+
{{ page.page|safe }}
+ {% endif %}
--
cgit v1.2.3
From dd16d63b3a6f1f646879c35e09fadfcbe39a03d1 Mon Sep 17 00:00:00 2001
From: kosayoda
Date: Wed, 24 Mar 2021 00:55:28 +0800
Subject: Rename `short_description` to `description`.
Given that there is no "long description", just `description` conveys
the same information with brevity.
---
.../guides/pydis-guides/how-to-write-a-article.md | 80 ----------------------
.../test_content/category/subcategory/test4.md | 2 +-
.../content/tests/test_content/category/test3.md | 2 +-
pydis_site/apps/content/tests/test_content/test.md | 2 +-
.../apps/content/tests/test_content/test2.md | 2 +-
pydis_site/templates/content/listing.html | 2 +-
pydis_site/templates/content/page.html | 2 +-
7 files changed, 6 insertions(+), 86 deletions(-)
delete mode 100644 pydis_site/apps/content/resources/guides/pydis-guides/how-to-write-a-article.md
(limited to 'pydis_site')
diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/how-to-write-a-article.md b/pydis_site/apps/content/resources/guides/pydis-guides/how-to-write-a-article.md
deleted file mode 100644
index ec89988c..00000000
--- a/pydis_site/apps/content/resources/guides/pydis-guides/how-to-write-a-article.md
+++ /dev/null
@@ -1,80 +0,0 @@
----
-title: How to Write a Article
-short_description: Learn how to write a article for this website
-icon_class: fas
-icon: fa-info
----
-
-When you are interested about how to write articles for this site (like this), then you can learn about it here.
-PyDis use Markdown (GitHub Markdown) files for articles.
-
-## Getting Started
-Before you can get started with writing a article, you need idea.
-Best way to find out is your idea good is to discuss about it in #dev-contrib channel. There can other peoples give their opinion about your idea. Even better, open issue in site repository first, then PyDis staff can see it and approve/decline this idea.
-It's good idea to wait for staff decision before starting to write guide to avoid case when you write a long long article, but then this don't get approved.
-
-To start with contributing, you should read [how to contribute to site](https://pythondiscord.com/pages/contributing/site/).
-You should also read our [Git workflow](https://pythondiscord.com/pages/contributing/working-with-git/), because you need to push your guide to GitHub.
-
-## Creating a File
-All articles is located at `site` repository, in `pydis_site/apps/content/resources/content`. Under this is root level articles (.md files) and categories (directories). Learn more about categories in [categories section](#categories).
-
-When you are writing guides, then these are located under `guides` category.
-
-At this point, you will need your article name for filename. Replace all your article name spaces with `-` and make all lowercase. Save this as `.md` (Markdown) file. This name (without Markdown extension) is path of article in URL.
-
-## Markdown Metadata
-Article files have some required metadata, like title, description, relevant pages. Metadata is first thing in file, YAML-like key-value pairs:
-
-```md
----
-title: My Article
-short_description: This is my short description.
-relevant_links: url1,url2,url3
-relevant_link_values: Text for url1,Text for url2,Text for url3
----
-
-Here comes content of article...
-```
-
-You can read more about Markdown metadata [here](https://github.com/trentm/python-markdown2/wiki/metadata).
-
-### Fields
-- **Name:** Easily-readable name for your article.
-- **Short Description:** Small, 1-2 line description that describe what your article explain.
-- **Relevant Links and Values:** URLs and values is under different fields, separated with comma.
-- **Icon class:** `icon_class` field have one of the favicons classes. Default is `fab`.
-- **Icon:** `icon` field have favicon name. Default `fa-python`.
-
-## Content
-For content, mostly you can use standard markdown, but there is a few addition that is available.
-
-### IDs for quick jumps
-System automatically assign IDs to headers, so like this header will get ID `ids-for-quick-jumps`.
-
-### Tables
-Tables like in GitHub is supported too:
-
-| This is header | This is too header |
-| -------------- | ------------------ |
-| My item | My item too |
-
-### Codeblocks
-Also this system supports codeblocks and provides syntax highlighting with `highlight.js`.
-To activate syntax highlight, just put language directly after starting backticks.
-
-```py
-import os
-
-path = os.path.join("foo", "bar")
-```
-
-## Categories
-To have some systematic sorting of guides, site support guides categories. Currently this system support only 1 level of categories. Categories live at `site` repo in `pydis_site/apps/content/resources/content` subdirectories. Directory name is path of category in URL. Inside category directory, there is 1 file required: `_info.yml`. This file need 2 key-value pairs defined:
-
-```yml
-name: Category name
-description: Category description
-```
-
-Then all Markdown files in this folder will be under this category.
diff --git a/pydis_site/apps/content/tests/test_content/category/subcategory/test4.md b/pydis_site/apps/content/tests/test_content/category/subcategory/test4.md
index 8031131d..1763a869 100644
--- a/pydis_site/apps/content/tests/test_content/category/subcategory/test4.md
+++ b/pydis_site/apps/content/tests/test_content/category/subcategory/test4.md
@@ -1,6 +1,6 @@
---
title: Test 4
-short_description: Testing 4
+description: Testing 4
---
This is also test content and in subcategory.
diff --git a/pydis_site/apps/content/tests/test_content/category/test3.md b/pydis_site/apps/content/tests/test_content/category/test3.md
index 03ddd67b..9f294130 100644
--- a/pydis_site/apps/content/tests/test_content/category/test3.md
+++ b/pydis_site/apps/content/tests/test_content/category/test3.md
@@ -1,6 +1,6 @@
---
title: Test 3
-short_description: Testing 3
+description: Testing 3
---
This is too test content, but in category.
diff --git a/pydis_site/apps/content/tests/test_content/test.md b/pydis_site/apps/content/tests/test_content/test.md
index ca06c1d5..709860d1 100644
--- a/pydis_site/apps/content/tests/test_content/test.md
+++ b/pydis_site/apps/content/tests/test_content/test.md
@@ -1,6 +1,6 @@
---
title: Test
-short_description: Testing
+description: Testing
relevant_links:
Asking Good Questions: https://pythondiscord.com/pages/resources/guides/asking-good-questions/
Help Channel Guide: https://pythondiscord.com/pages/resources/guides/help-channels/
diff --git a/pydis_site/apps/content/tests/test_content/test2.md b/pydis_site/apps/content/tests/test_content/test2.md
index 14d8a54b..0e57c3cd 100644
--- a/pydis_site/apps/content/tests/test_content/test2.md
+++ b/pydis_site/apps/content/tests/test_content/test2.md
@@ -1,6 +1,6 @@
---
title: Test 2
-short_description: Testing 2
+description: Testing 2
---
This is too test content.
diff --git a/pydis_site/templates/content/listing.html b/pydis_site/templates/content/listing.html
index 097cac4f..6c84a38c 100644
--- a/pydis_site/templates/content/listing.html
+++ b/pydis_site/templates/content/listing.html
@@ -50,7 +50,7 @@
{{ data.title }}
- {{ data.short_description }}
+ {{ data.description }}
{% endfor %}
diff --git a/pydis_site/templates/content/page.html b/pydis_site/templates/content/page.html
index a687933d..c3b2285b 100644
--- a/pydis_site/templates/content/page.html
+++ b/pydis_site/templates/content/page.html
@@ -5,7 +5,7 @@
{% block head %}
-
+
--
cgit v1.2.3
From 078fe3966c01ed3a837430ed07453bec3791935e Mon Sep 17 00:00:00 2001
From: kosayoda
Date: Wed, 24 Mar 2021 01:42:28 +0800
Subject: Propogate markdown language data to highlight.js
---
pydis_site/apps/content/utils.py | 1 +
1 file changed, 1 insertion(+)
(limited to 'pydis_site')
diff --git a/pydis_site/apps/content/utils.py b/pydis_site/apps/content/utils.py
index ef02a8cb..17d7db81 100644
--- a/pydis_site/apps/content/utils.py
+++ b/pydis_site/apps/content/utils.py
@@ -47,6 +47,7 @@ def get_page(path: Path) -> Dict[str, Union[str, Dict]]:
extras=[
"metadata",
"fenced-code-blocks",
+ "highlightjs-lang",
"header-ids",
"strike",
"target-blank-links",
--
cgit v1.2.3
From 9f7e025f2fc590a75bdb5b14aa65d1f0df4e7eb8 Mon Sep 17 00:00:00 2001
From: kosayoda
Date: Wed, 24 Mar 2021 01:42:59 +0800
Subject: Update guide to reflect changes in events app.
Wording is also improved.
---
pydis_site/apps/content/resources/guides/_info.yml | 2 +-
.../resources/guides/pydis-guides/_info.yml | 2 +-
.../pydis-guides/how-to-contribute-a-page.md | 88 ++++++++++++++++++++++
3 files changed, 90 insertions(+), 2 deletions(-)
create mode 100644 pydis_site/apps/content/resources/guides/pydis-guides/how-to-contribute-a-page.md
(limited to 'pydis_site')
diff --git a/pydis_site/apps/content/resources/guides/_info.yml b/pydis_site/apps/content/resources/guides/_info.yml
index 369f05d4..59c60a7b 100644
--- a/pydis_site/apps/content/resources/guides/_info.yml
+++ b/pydis_site/apps/content/resources/guides/_info.yml
@@ -1,2 +1,2 @@
name: Guides
-description: Python and PyDis guides.
+description: Made by us, for you.
diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/_info.yml b/pydis_site/apps/content/resources/guides/pydis-guides/_info.yml
index 64111a83..7c9a2225 100644
--- a/pydis_site/apps/content/resources/guides/pydis-guides/_info.yml
+++ b/pydis_site/apps/content/resources/guides/pydis-guides/_info.yml
@@ -1,2 +1,2 @@
name: Python Discord Guides
-description: Python Discord server and community guides.
+description: Guides related to the Python Discord server and community.
diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/how-to-contribute-a-page.md b/pydis_site/apps/content/resources/guides/pydis-guides/how-to-contribute-a-page.md
new file mode 100644
index 00000000..ac663898
--- /dev/null
+++ b/pydis_site/apps/content/resources/guides/pydis-guides/how-to-contribute-a-page.md
@@ -0,0 +1,88 @@
+---
+title: How to Contribute a Page
+description: Learn how to write and publish a page to this website.
+icon_class: fas
+icon: fa-info
+relevant_links:
+ Contributing to Site: https://pythondiscord.com/pages/contributing/site/
+ Using Git: https://pythondiscord.com/pages/contributing/working-with-git/
+---
+
+Pages, which include guides, articles and other static content are stored in markdown files in the `site` repository on Github.
+If you are interested in writing or modifying pages seen here on the site, follow the steps below.
+
+For further assistance and help with contributing pages, send a message to the `#dev-contrib` channel in the Discord server!
+
+## Prerequisites
+Before working on a new page, you have to [setup the site project locally](https://pythondiscord.com/pages/contributing/site/).
+It is also a good idea to familiarize yourself with the [git workflow](https://pythondiscord.com/pages/contributing/working-with-git/), as it is part of the contribution workflow.
+
+Additionally, please submit your proposed page or modification to a page as an [issue in the site repository](https://github.com/python-discord/site/issues), or discuss it in the `#dev-contrib` channel in the server.
+As website changes require staff approval, discussing the page content beforehand helps with accelerating the contribution process, and avoids wasted work in the event the proposed page is not accepted.
+
+## Creating the Page
+All pages are located in the `site` repo, at the path `pydis_site/apps/content/resources/`. This is the root folder, which corresponds to the URL `www.pythondiscord.com/pages/`.
+For example, the file `pydis_site/apps/content/resources/hello-world.md` will result in a page available at `www.pythondiscord.com/pages/hello-world`.
+
+Nested folders represent page categories on the website. Each folder under the root folder must include a `_info.yml` file with the following:
+
+```yml
+name: Category name
+description: Category description
+```
+
+All the markdown files in this folder will then be under this category.
+
+## Writing the Page
+Files representing pages are in `.md` (Markdown) format, with all-lowercase filenames and spaces replaced with `-` characters.
+
+Each page must include required metadata, and optionally additional metadata to modify appearance of the page.
+The metadata is written in YAML-like key-value pairs, and should be enclosed in triple dashes `---` *at the top of the markdown file*.
+
+**Example:**
+```yaml
+---
+title: How to Contribute a Page
+description: Learn how to write and publish a page to this website.
+icon_class: fas
+icon: fa-info
+relevant_links:
+ Contributing to Site: https://pythondiscord.com/pages/contributing/site/
+ Using Git: https://pythondiscord.com/pages/contributing/working-with-git/
+---
+
+Pages, which include guides, articles and other static content...
+```
+
+You can learn more about Markdown metadata [here](https://github.com/trentm/python-markdown2/wiki/metadata).
+
+### Required Fields
+- **title:** Easily-readable title for your article.
+- **description:** Short, 1-2 line description that describes the page.
+
+### Optional Fields
+- **icon_class:** Favicon class for the category entry for the page. Default: `fab`
+- **icon:** Favicon for the category entry for the page. Default: `fa-python`
+- **relevant_links:** A YAML dictionary containing `text:link` pairs. See the example above.
+
+## Extended Markdown
+
+Apart from standard markdown, certain additions are available:
+
+### Tables
+
+| This is header | This is another header |
+| -------------- | ---------------------- |
+| An item | Another item |
+| Big item | Small item |
+
+
+### Codeblock Syntax Highlighting
+Syntax highlighting is provided by `highlight.js`.
+To activate syntax highlighting, put the language directly after the starting backticks.
+
+```python
+import os
+
+path = os.path.join("foo", "bar")
+```
--
cgit v1.2.3
From 731ff9482ecae7b5293bcfe1512389efd7f17571 Mon Sep 17 00:00:00 2001
From: kosayoda
Date: Wed, 24 Mar 2021 13:22:57 +0800
Subject: Improve phrasing and wording of documentation.
---
pydis_site/apps/content/resources/_info.yml | 2 +-
.../resources/guides/pydis-guides/how-to-contribute-a-page.md | 10 +++++-----
pydis_site/apps/content/utils.py | 4 ++--
pydis_site/apps/content/views/page_category.py | 2 +-
4 files changed, 9 insertions(+), 9 deletions(-)
(limited to 'pydis_site')
diff --git a/pydis_site/apps/content/resources/_info.yml b/pydis_site/apps/content/resources/_info.yml
index 4ccdd7e1..583cab18 100644
--- a/pydis_site/apps/content/resources/_info.yml
+++ b/pydis_site/apps/content/resources/_info.yml
@@ -1,2 +1,2 @@
name: Pages
-description: Guides, articles and pages hosted on the site.
+description: Guides, articles, and pages hosted on the site.
diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/how-to-contribute-a-page.md b/pydis_site/apps/content/resources/guides/pydis-guides/how-to-contribute-a-page.md
index ac663898..8967e7da 100644
--- a/pydis_site/apps/content/resources/guides/pydis-guides/how-to-contribute-a-page.md
+++ b/pydis_site/apps/content/resources/guides/pydis-guides/how-to-contribute-a-page.md
@@ -8,7 +8,7 @@ relevant_links:
Using Git: https://pythondiscord.com/pages/contributing/working-with-git/
---
-Pages, which include guides, articles and other static content are stored in markdown files in the `site` repository on Github.
+Pages, which include guides, articles, and other static content, are stored in markdown files in the `site` repository on Github.
If you are interested in writing or modifying pages seen here on the site, follow the steps below.
For further assistance and help with contributing pages, send a message to the `#dev-contrib` channel in the Discord server!
@@ -36,7 +36,7 @@ All the markdown files in this folder will then be under this category.
## Writing the Page
Files representing pages are in `.md` (Markdown) format, with all-lowercase filenames and spaces replaced with `-` characters.
-Each page must include required metadata, and optionally additional metadata to modify appearance of the page.
+Each page must include required metadata, and optionally additional metadata to modify the appearance of the page.
The metadata is written in YAML-like key-value pairs, and should be enclosed in triple dashes `---` *at the top of the markdown file*.
**Example:**
@@ -51,14 +51,14 @@ relevant_links:
Using Git: https://pythondiscord.com/pages/contributing/working-with-git/
---
-Pages, which include guides, articles and other static content...
+Pages, which include guides, articles, and other static content,...
```
You can learn more about Markdown metadata [here](https://github.com/trentm/python-markdown2/wiki/metadata).
### Required Fields
- **title:** Easily-readable title for your article.
-- **description:** Short, 1-2 line description that describes the page.
+- **description:** Short, 1-2 line description of the page's content.
### Optional Fields
- **icon_class:** Favicon class for the category entry for the page. Default: `fab`
@@ -67,7 +67,7 @@ You can learn more about Markdown metadata [here](https://github.com/trentm/pyth
## Extended Markdown
-Apart from standard markdown, certain additions are available:
+Apart from standard Markdown, certain additions are available:
### Tables
diff --git a/pydis_site/apps/content/utils.py b/pydis_site/apps/content/utils.py
index 17d7db81..6cb15581 100644
--- a/pydis_site/apps/content/utils.py
+++ b/pydis_site/apps/content/utils.py
@@ -15,7 +15,7 @@ def get_category(path: Path) -> Dict[str, str]:
def get_categories(path: Path) -> Dict[str, Dict]:
- """Get all categories information."""
+ """Get information for all categories."""
categories = {}
for name in path.iterdir():
@@ -38,7 +38,7 @@ def get_pages(path: Path) -> Dict[str, Dict]:
def get_page(path: Path) -> Dict[str, Union[str, Dict]]:
- """Get one specific page. When category is specified, get it from there."""
+ """Get one specific page."""
if not path.exists() or not path.is_file():
raise Http404("Page not found.")
diff --git a/pydis_site/apps/content/views/page_category.py b/pydis_site/apps/content/views/page_category.py
index 7e04e2f3..7e8fe07d 100644
--- a/pydis_site/apps/content/views/page_category.py
+++ b/pydis_site/apps/content/views/page_category.py
@@ -19,7 +19,7 @@ class PageOrCategoryView(TemplateView):
return super().dispatch(request, *args, **kwargs)
def get_template_names(self) -> t.List[str]:
- """Checks does this use page template or listing template."""
+ """Checks if the view uses the page template or listing template."""
if self.full_location.is_dir():
template_name = "content/listing.html"
elif self.full_location.with_suffix(".md").is_file():
--
cgit v1.2.3
From fbfb50b27dbe740d8c74243a1b4ea2753dba7904 Mon Sep 17 00:00:00 2001
From: kosayoda
Date: Wed, 24 Mar 2021 13:25:02 +0800
Subject: Undo change to events app.
Renaming `PageView` to `PagesView` was accidental and unnecessary.
---
pydis_site/apps/events/urls.py | 4 ++--
pydis_site/apps/events/views/__init__.py | 4 ++--
pydis_site/apps/events/views/page.py | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
(limited to 'pydis_site')
diff --git a/pydis_site/apps/events/urls.py b/pydis_site/apps/events/urls.py
index 601451da..9a65cf1f 100644
--- a/pydis_site/apps/events/urls.py
+++ b/pydis_site/apps/events/urls.py
@@ -1,9 +1,9 @@
from django.urls import path
-from pydis_site.apps.events.views import IndexView, PagesView
+from pydis_site.apps.events.views import IndexView, PageView
app_name = "events"
urlpatterns = [
path("", IndexView.as_view(), name="index"),
- path("/", PagesView.as_view(), name="page"),
+ path("/", PageView.as_view(), name="page"),
]
diff --git a/pydis_site/apps/events/views/__init__.py b/pydis_site/apps/events/views/__init__.py
index 6188f723..8a107e2f 100644
--- a/pydis_site/apps/events/views/__init__.py
+++ b/pydis_site/apps/events/views/__init__.py
@@ -1,4 +1,4 @@
from .index import IndexView
-from .page import PagesView
+from .page import PageView
-__all__ = ["IndexView", "PagesView"]
+__all__ = ["IndexView", "PageView"]
diff --git a/pydis_site/apps/events/views/page.py b/pydis_site/apps/events/views/page.py
index fbedd4e8..f4c37aeb 100644
--- a/pydis_site/apps/events/views/page.py
+++ b/pydis_site/apps/events/views/page.py
@@ -5,7 +5,7 @@ from django.http import Http404
from django.views.generic import TemplateView
-class PagesView(TemplateView):
+class PageView(TemplateView):
"""Handles event pages showing."""
def get_template_names(self) -> List[str]:
--
cgit v1.2.3
From baebc131ed3be8d015acaad589b697983435037e Mon Sep 17 00:00:00 2001
From: kosayoda
Date: Wed, 24 Mar 2021 14:09:32 +0800
Subject: Refactor common HTML into a base template.
---
pydis_site/apps/content/views/page_category.py | 7 ++-
pydis_site/templates/content/base.html | 36 ++++++++++++
pydis_site/templates/content/listing.html | 76 ++++++++-----------------
pydis_site/templates/content/page.html | 77 ++++++++------------------
4 files changed, 88 insertions(+), 108 deletions(-)
create mode 100644 pydis_site/templates/content/base.html
(limited to 'pydis_site')
diff --git a/pydis_site/apps/content/views/page_category.py b/pydis_site/apps/content/views/page_category.py
index 7e8fe07d..623c2596 100644
--- a/pydis_site/apps/content/views/page_category.py
+++ b/pydis_site/apps/content/views/page_category.py
@@ -35,12 +35,17 @@ class PageOrCategoryView(TemplateView):
if self.full_location.is_dir():
context["categories"] = utils.get_categories(self.full_location)
- context["category_info"] = utils.get_category(self.full_location)
+ category = utils.get_category(self.full_location)
+ context["category_info"] = category
+ context["page_title"] = category["name"]
+ context["page_description"] = category["description"]
context["content"] = utils.get_pages(self.full_location)
context["path"] = f"{self.location}/" # Add trailing slash here to simplify template
elif self.full_location.with_suffix(".md").is_file():
page_result = utils.get_page(self.full_location.with_suffix(".md"))
context["page"] = page_result
+ context["page_title"] = page_result["metadata"]["title"]
+ context["page_description"] = page_result["metadata"]["description"]
context["relevant_links"] = page_result["metadata"].get("relevant_links", {})
else:
raise Http404
diff --git a/pydis_site/templates/content/base.html b/pydis_site/templates/content/base.html
new file mode 100644
index 00000000..1508dfb3
--- /dev/null
+++ b/pydis_site/templates/content/base.html
@@ -0,0 +1,36 @@
+{% extends 'base/base.html' %}
+{% load static %}
+
+{% block title %}{{ page_title }}{% endblock %}
+{% block head %}
+
+
+
+
+{% endblock %}
+
+{% block content %}
+ {% include "base/navbar.html" %}
+
+
+
+
+
+
+
{{ page_title }}
+ {% block page_content %}{% endblock %}
+
+
+
+{% endblock %}
diff --git a/pydis_site/templates/content/listing.html b/pydis_site/templates/content/listing.html
index 6c84a38c..9271f3ab 100644
--- a/pydis_site/templates/content/listing.html
+++ b/pydis_site/templates/content/listing.html
@@ -1,59 +1,27 @@
-{% extends 'base/base.html' %}
-{% load static %}
+{% extends 'content/base.html' %}
-{% block title %}{{ category_info.name|default:"Pages" }}{% endblock %}
-{% block head %}
-
-
-
-
-{% endblock %}
-
-{% block content %}
- {% include "base/navbar.html" %}
+{% block page_content %}
+ {% for category, data in categories.items %}
+
+
+
+
-
-
-
-
-
-
{{ category_info.name|default:"Pages" }}
- {% for category, data in categories.items %}
-
- {% endfor %}
- {% for page, data in content.items %}
-
- {% endfor %}
-
+ {% endfor %}
+ {% for page, data in content.items %}
+
-
+ {% endfor %}
{% endblock %}
diff --git a/pydis_site/templates/content/page.html b/pydis_site/templates/content/page.html
index c3b2285b..2b366e50 100644
--- a/pydis_site/templates/content/page.html
+++ b/pydis_site/templates/content/page.html
@@ -1,60 +1,31 @@
-{% extends 'base/base.html' %}
-{% load static %}
+{% extends 'content/base.html' %}
-{% block title %}{{ page.metadata.title }}{% endblock %}
{% block head %}
-
-
-
-
-
-
-
+ {{ block.super }}
+
+
+
{% endblock %}
-{% block content %}
- {% include "base/navbar.html" %}
-
-
-
-
-
-
-
{{ page.metadata.title }}
-
- {% if relevant_links|length > 0 %}
-
-
- {{ page.page|safe }}
-
-
-
- {% else %}
-
{{ page.page|safe }}
- {% endif %}
+{% block page_content %}
+ {% if relevant_links|length > 0 %}
+
+
+ {{ page.page|safe }}
+
+
-
-
+ {% else %}
+
{{ page.page|safe }}
+ {% endif %}
{% endblock %}
--
cgit v1.2.3
From dbac69c7a58938fb24128a787971ea1bc1892110 Mon Sep 17 00:00:00 2001
From: kosayoda
Date: Wed, 24 Mar 2021 14:14:43 +0800
Subject: Improve variable and key names for page utils.
---
pydis_site/apps/content/utils.py | 6 +++---
pydis_site/apps/content/views/page_category.py | 2 +-
pydis_site/templates/content/listing.html | 2 +-
pydis_site/templates/content/page.html | 4 ++--
4 files changed, 7 insertions(+), 7 deletions(-)
(limited to 'pydis_site')
diff --git a/pydis_site/apps/content/utils.py b/pydis_site/apps/content/utils.py
index 6cb15581..8cbcad91 100644
--- a/pydis_site/apps/content/utils.py
+++ b/pydis_site/apps/content/utils.py
@@ -25,8 +25,8 @@ def get_categories(path: Path) -> Dict[str, Dict]:
return categories
-def get_pages(path: Path) -> Dict[str, Dict]:
- """Get all root or category page names and their metadata."""
+def get_category_pages(path: Path) -> Dict[str, Dict]:
+ """Get all page names and their metadata at a category path."""
pages = {}
for item in path.iterdir():
@@ -56,4 +56,4 @@ def get_page(path: Path) -> Dict[str, Union[str, Dict]]:
]
)
- return {"page": str(html), "metadata": html.metadata}
+ return {"content": str(html), "metadata": html.metadata}
diff --git a/pydis_site/apps/content/views/page_category.py b/pydis_site/apps/content/views/page_category.py
index 623c2596..0bef82d0 100644
--- a/pydis_site/apps/content/views/page_category.py
+++ b/pydis_site/apps/content/views/page_category.py
@@ -39,7 +39,7 @@ class PageOrCategoryView(TemplateView):
context["category_info"] = category
context["page_title"] = category["name"]
context["page_description"] = category["description"]
- context["content"] = utils.get_pages(self.full_location)
+ context["pages"] = utils.get_category_pages(self.full_location)
context["path"] = f"{self.location}/" # Add trailing slash here to simplify template
elif self.full_location.with_suffix(".md").is_file():
page_result = utils.get_page(self.full_location.with_suffix(".md"))
diff --git a/pydis_site/templates/content/listing.html b/pydis_site/templates/content/listing.html
index 9271f3ab..6de306b0 100644
--- a/pydis_site/templates/content/listing.html
+++ b/pydis_site/templates/content/listing.html
@@ -13,7 +13,7 @@
{{ data.description }}
{% endfor %}
- {% for page, data in content.items %}
+ {% for page, data in pages.items %}
diff --git a/pydis_site/templates/content/page.html b/pydis_site/templates/content/page.html
index 2b366e50..5e820c26 100644
--- a/pydis_site/templates/content/page.html
+++ b/pydis_site/templates/content/page.html
@@ -12,7 +12,7 @@
{% if relevant_links|length > 0 %}
- {{ page.page|safe }}
+ {{ page.content|safe }}
{% else %}
-
{{ page.page|safe }}
+
{{ page.content|safe }}
{% endif %}
{% endblock %}
--
cgit v1.2.3
From 19191bb1f45d14522a8de00b70feae2fc624e58a Mon Sep 17 00:00:00 2001
From: kosayoda
Date: Wed, 24 Mar 2021 14:28:45 +0800
Subject: Simplify pathlib code and specify file encoding.
---
pydis_site/apps/content/utils.py | 18 +++++++++---------
pydis_site/apps/content/views/page_category.py | 5 ++---
2 files changed, 11 insertions(+), 12 deletions(-)
(limited to 'pydis_site')
diff --git a/pydis_site/apps/content/utils.py b/pydis_site/apps/content/utils.py
index 8cbcad91..0faf722c 100644
--- a/pydis_site/apps/content/utils.py
+++ b/pydis_site/apps/content/utils.py
@@ -8,19 +8,19 @@ from markdown2 import markdown
def get_category(path: Path) -> Dict[str, str]:
"""Load category information by name from _info.yml."""
- if not path.exists() or not path.is_dir():
+ if not path.is_dir():
raise Http404("Category not found.")
- return yaml.safe_load(path.joinpath("_info.yml").read_text())
+ return yaml.safe_load(path.joinpath("_info.yml").read_text(encoding="utf-8"))
def get_categories(path: Path) -> Dict[str, Dict]:
"""Get information for all categories."""
categories = {}
- for name in path.iterdir():
- if name.is_dir():
- categories[name.name] = get_category(path.joinpath(name.name))
+ for item in path.iterdir():
+ if item.is_dir():
+ categories[item.name] = get_category(item)
return categories
@@ -29,8 +29,8 @@ def get_category_pages(path: Path) -> Dict[str, Dict]:
"""Get all page names and their metadata at a category path."""
pages = {}
- for item in path.iterdir():
- if item.is_file() and item.name.endswith(".md"):
+ for item in path.glob("*.md"):
+ if item.is_file():
md = markdown(item.read_text(), extras=["metadata"])
pages[item.stem] = md.metadata
@@ -39,11 +39,11 @@ def get_category_pages(path: Path) -> Dict[str, Dict]:
def get_page(path: Path) -> Dict[str, Union[str, Dict]]:
"""Get one specific page."""
- if not path.exists() or not path.is_file():
+ if not path.is_file():
raise Http404("Page not found.")
html = markdown(
- path.read_text(),
+ path.read_text(encoding="utf-8"),
extras=[
"metadata",
"fenced-code-blocks",
diff --git a/pydis_site/apps/content/views/page_category.py b/pydis_site/apps/content/views/page_category.py
index 0bef82d0..91aed7f0 100644
--- a/pydis_site/apps/content/views/page_category.py
+++ b/pydis_site/apps/content/views/page_category.py
@@ -50,12 +50,11 @@ class PageOrCategoryView(TemplateView):
else:
raise Http404
- breadcrumb_items = [
+ context["breadcrumb_items"] = [
{
"name": utils.get_category(settings.PAGES_PATH / location)["name"],
"path": str(location)
- } for location in self.location.parents
+ } for location in reversed(self.location.parents)
]
- context["breadcrumb_items"] = reversed(breadcrumb_items)
return context
--
cgit v1.2.3
From 6ccec0d866c44cd7f9789a396ef6ec6cd2cd5df8 Mon Sep 17 00:00:00 2001
From: kosayoda
Date: Wed, 24 Mar 2021 19:55:16 +0800
Subject: Replace `markdown2` with `markdown` and `python-frontmatter`.
This allows us to properly escape codeblocks within markdown, permalink
to headers on a page, and decouples getting metadata from a file and
getting generated HTML from the Markdown content.
---
Pipfile | 3 +-
Pipfile.lock | 43 ++++++++++++++--
.../pydis-guides/how-to-contribute-a-page.md | 59 +++++++++++++++++++++-
pydis_site/apps/content/utils.py | 32 ++++++------
pydis_site/apps/content/views/page_category.py | 15 +++---
pydis_site/static/css/content/page.css | 29 ++++++++---
pydis_site/templates/content/base.html | 2 +-
pydis_site/templates/content/page.html | 4 +-
8 files changed, 146 insertions(+), 41 deletions(-)
(limited to 'pydis_site')
diff --git a/Pipfile b/Pipfile
index 8af6e3ce..c2b87ab4 100644
--- a/Pipfile
+++ b/Pipfile
@@ -18,7 +18,8 @@ pyyaml = "~=5.1"
pyuwsgi = {version = "~=2.0", sys_platform = "!='win32'"}
sentry-sdk = "~=0.14"
gitpython = "~=3.1.7"
-markdown2 = "~=2.3.9"
+markdown = "~=3.3.4"
+python-frontmatter = "~=1.0"
[dev-packages]
coverage = "~=5.0"
diff --git a/Pipfile.lock b/Pipfile.lock
index 3dfb7ec6..4f8bd0d3 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
- "sha256": "893ab5cc0b64f7bb87c0304c9fb6eb24b1856c40286fbbdb1a2bf4a0d7a6d39f"
+ "sha256": "a338a377b64a5d25bf925646c97d932a2d1c783fc8f40d91b6a9ab8f30c2b14e"
},
"pipfile-spec": 6,
"requires": {
@@ -118,6 +118,14 @@
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==2.10"
},
+ "importlib-metadata": {
+ "hashes": [
+ "sha256:742add720a20d0467df2f444ae41704000f50e1234f46174b51f9c6031a1bd71",
+ "sha256:b74159469b464a99cb8cc3e21973e4d96e05d3024d337313fedb618a6e86e6f4"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==3.7.3"
+ },
"libsass": {
"hashes": [
"sha256:1521d2a8d4b397c6ec90640a1f6b5529077035efc48ef1c2e53095544e713d1b",
@@ -136,13 +144,13 @@
],
"version": "==0.20.1"
},
- "markdown2": {
+ "markdown": {
"hashes": [
- "sha256:85956d8119fa6378156fef65545d66705a842819d2e1b50379a2b9d2aaa17cf0",
- "sha256:fef148e5fd68d4532286c3e2943e9d2c076a8ad781b0a70a9d599a0ffe91652d"
+ "sha256:31b5b491868dcc87d6c24b7e3d19a0d730d59d3e46f4eea6430a321bed387a49",
+ "sha256:96c3ba1261de2f7547b46a00ea8463832c921d3f9d6aba3f255a6f71386db20c"
],
"index": "pypi",
- "version": "==2.3.10"
+ "version": "==3.3.4"
},
"psycopg2-binary": {
"hashes": [
@@ -185,6 +193,14 @@
"index": "pypi",
"version": "==2.8.6"
},
+ "python-frontmatter": {
+ "hashes": [
+ "sha256:766ae75f1b301ffc5fe3494339147e0fd80bc3deff3d7590a93991978b579b08",
+ "sha256:e98152e977225ddafea6f01f40b4b0f1de175766322004c826ca99842d19a7cd"
+ ],
+ "index": "pypi",
+ "version": "==1.0.0"
+ },
"pytz": {
"hashes": [
"sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da",
@@ -288,6 +304,15 @@
"markers": "python_version >= '3.5'",
"version": "==0.4.1"
},
+ "typing-extensions": {
+ "hashes": [
+ "sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918",
+ "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c",
+ "sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==3.7.4.3"
+ },
"urllib3": {
"hashes": [
"sha256:2f4da4594db7e1e110a944bb1b551fdf4e6c136ad42e4234131391e21eb5b0df",
@@ -303,6 +328,14 @@
],
"index": "pypi",
"version": "==5.2.0"
+ },
+ "zipp": {
+ "hashes": [
+ "sha256:3607921face881ba3e026887d8150cca609d517579abe052ac81fc5aeffdbd76",
+ "sha256:51cb66cc54621609dd593d1787f286ee42a5c0adbb4b29abea5a63edc3e03098"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==3.4.1"
}
},
"develop": {
diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/how-to-contribute-a-page.md b/pydis_site/apps/content/resources/guides/pydis-guides/how-to-contribute-a-page.md
index 8967e7da..12969ba2 100644
--- a/pydis_site/apps/content/resources/guides/pydis-guides/how-to-contribute-a-page.md
+++ b/pydis_site/apps/content/resources/guides/pydis-guides/how-to-contribute-a-page.md
@@ -69,18 +69,75 @@ You can learn more about Markdown metadata [here](https://github.com/trentm/pyth
Apart from standard Markdown, certain additions are available:
+### Abbreviations
+HTML `` tags can be used in markdown using this format:
+
+**Markdown:**
+```nohighlight
+This website is HTML generated from YAML and Markdown.
+
+*[HTML]: Hyper Text Markup Language
+*[YAML]: YAML Ain't Markup Language
+```
+
+**Output:**
+
+This website is HTML
+generated from YAML and Markdown.
+
+---
+
+### Footnotes
+**Markdown:**
+```nohighlight
+This footnote[^1] links to the bottom[^custom_label] of the page[^3].
+
+[^1]: Footnote labels start with a caret `^`.
+[^3]: The footnote link is numbered based on the order of the labels.
+[^custom label]: Footnote labels can contain any text within square brackets.
+```
+
+**Output:**
+
+This footnote[^1] links to the bottom[^custom label] of the page[^3].
+
+[^1]: Footnote labels start with a caret `^`.
+[^3]: The footnote link is numbered based on the order of the labels.
+[^custom label]: Footnote labels can contain any text within square brackets.
+
+---
+
### Tables
+**Markdown:**
+```nohighlight
+| This is header | This is another header |
+| -------------- | ---------------------- |
+| An item | Another item |
+```
+
+**Output:**
+
| This is header | This is another header |
| -------------- | ---------------------- |
| An item | Another item |
-| Big item | Small item |
+---
### Codeblock Syntax Highlighting
Syntax highlighting is provided by `highlight.js`.
To activate syntax highlighting, put the language directly after the starting backticks.
+**Markdown:**
+````nohighlight
+```python
+import os
+
+path = os.path.join("foo", "bar")
+```
+````
+
+**Output:**
```python
import os
diff --git a/pydis_site/apps/content/utils.py b/pydis_site/apps/content/utils.py
index 0faf722c..11d2b792 100644
--- a/pydis_site/apps/content/utils.py
+++ b/pydis_site/apps/content/utils.py
@@ -1,9 +1,11 @@
from pathlib import Path
-from typing import Dict, Union
+from typing import Dict, Tuple
+import frontmatter
+import markdown
import yaml
from django.http import Http404
-from markdown2 import markdown
+from markdown.extensions.toc import TocExtension
def get_category(path: Path) -> Dict[str, str]:
@@ -31,29 +33,25 @@ def get_category_pages(path: Path) -> Dict[str, Dict]:
for item in path.glob("*.md"):
if item.is_file():
- md = markdown(item.read_text(), extras=["metadata"])
- pages[item.stem] = md.metadata
+ pages[item.stem] = frontmatter.load(item)
return pages
-def get_page(path: Path) -> Dict[str, Union[str, Dict]]:
+def get_page(path: Path) -> Tuple[str, Dict]:
"""Get one specific page."""
if not path.is_file():
raise Http404("Page not found.")
- html = markdown(
- path.read_text(encoding="utf-8"),
- extras=[
- "metadata",
- "fenced-code-blocks",
- "highlightjs-lang",
- "header-ids",
- "strike",
- "target-blank-links",
- "tables",
- "task_list"
+ metadata, content = frontmatter.parse(path.read_text(encoding="utf-8"))
+ html = markdown.markdown(
+ content,
+ extensions=[
+ "extra",
+ # Empty string for marker to disable text searching for [TOC]
+ # By using a metadata key instead, we save time on long markdown documents
+ TocExtension(title="Table of Contents:", permalink=True, marker="")
]
)
- return {"content": str(html), "metadata": html.metadata}
+ return str(html), metadata
diff --git a/pydis_site/apps/content/views/page_category.py b/pydis_site/apps/content/views/page_category.py
index 91aed7f0..4a2ed2d6 100644
--- a/pydis_site/apps/content/views/page_category.py
+++ b/pydis_site/apps/content/views/page_category.py
@@ -35,18 +35,19 @@ class PageOrCategoryView(TemplateView):
if self.full_location.is_dir():
context["categories"] = utils.get_categories(self.full_location)
+ context["pages"] = utils.get_category_pages(self.full_location)
+
category = utils.get_category(self.full_location)
- context["category_info"] = category
context["page_title"] = category["name"]
context["page_description"] = category["description"]
- context["pages"] = utils.get_category_pages(self.full_location)
+
context["path"] = f"{self.location}/" # Add trailing slash here to simplify template
elif self.full_location.with_suffix(".md").is_file():
- page_result = utils.get_page(self.full_location.with_suffix(".md"))
- context["page"] = page_result
- context["page_title"] = page_result["metadata"]["title"]
- context["page_description"] = page_result["metadata"]["description"]
- context["relevant_links"] = page_result["metadata"].get("relevant_links", {})
+ page, metadata = utils.get_page(self.full_location.with_suffix(".md"))
+ context["page"] = page
+ context["page_title"] = metadata["title"]
+ context["page_description"] = metadata["description"]
+ context["relevant_links"] = metadata.get("relevant_links", {})
else:
raise Http404
diff --git a/pydis_site/static/css/content/page.css b/pydis_site/static/css/content/page.css
index f46d6b15..57d7472b 100644
--- a/pydis_site/static/css/content/page.css
+++ b/pydis_site/static/css/content/page.css
@@ -6,11 +6,26 @@ i.has-icon-padding {
padding: 0 10px 25px 0;
}
-pre {
- /*
- * Style it the same as the tag, since highlight.js does not style
- * backgrounds of tags but bulma does, resulting in a weird off-white
- * border.
- */
- background-color: #282c34;
+/*
+ * Move padding padding from tag to hljs tags so the padding
+ * space is colored the same as the background of hljs blocks.
+ */
+.content pre {
+ padding: 0;
+}
+
+code.hljs {
+ padding: 1.75em 2em;
+}
+
+/*
+ * Show header permalink on hover.
+ */
+.headerlink {
+ display: none;
+ padding-left: 0.5em;
+}
+
+:is(h1, h2, h3, h4, h5, h6):hover > .headerlink {
+ display: inline;
}
diff --git a/pydis_site/templates/content/base.html b/pydis_site/templates/content/base.html
index 1508dfb3..19eec5d4 100644
--- a/pydis_site/templates/content/base.html
+++ b/pydis_site/templates/content/base.html
@@ -3,7 +3,7 @@
{% block title %}{{ page_title }}{% endblock %}
{% block head %}
-
+
diff --git a/pydis_site/templates/content/page.html b/pydis_site/templates/content/page.html
index 5e820c26..06d74208 100644
--- a/pydis_site/templates/content/page.html
+++ b/pydis_site/templates/content/page.html
@@ -12,7 +12,7 @@
{% if relevant_links|length > 0 %}
- {{ page.content|safe }}
+ {{ page|safe }}
{% else %}
-
{{ page.content|safe }}
+
{{ page|safe }}
{% endif %}
{% endblock %}
--
cgit v1.2.3
From acf7880e233faeb91ce2eeb59855f40b6e7db3e0 Mon Sep 17 00:00:00 2001
From: kosayoda
Date: Thu, 25 Mar 2021 16:36:16 +0800
Subject: Refactor content app tests.
The tests uses pyfakefs to simulate a fake filesystem that is reused
over the content app tests.
Test coverage for the app is brought to 100%.
---
Pipfile | 1 +
Pipfile.lock | 10 +-
pydis_site/apps/content/tests/helpers.py | 84 +++++++
.../apps/content/tests/test_content/_info.yml | 2 -
.../content/tests/test_content/category/_info.yml | 2 -
.../test_content/category/subcategory/_info.yml | 2 -
.../test_content/category/subcategory/test4.md | 6 -
.../content/tests/test_content/category/test3.md | 6 -
pydis_site/apps/content/tests/test_content/test.md | 10 -
.../apps/content/tests/test_content/test2.md | 6 -
pydis_site/apps/content/tests/test_utils.py | 185 +++++---------
pydis_site/apps/content/tests/test_views.py | 267 +++++++++++----------
pydis_site/apps/content/utils.py | 2 +-
pydis_site/apps/content/views/page_category.py | 2 +-
14 files changed, 295 insertions(+), 290 deletions(-)
create mode 100644 pydis_site/apps/content/tests/helpers.py
delete mode 100644 pydis_site/apps/content/tests/test_content/_info.yml
delete mode 100644 pydis_site/apps/content/tests/test_content/category/_info.yml
delete mode 100644 pydis_site/apps/content/tests/test_content/category/subcategory/_info.yml
delete mode 100644 pydis_site/apps/content/tests/test_content/category/subcategory/test4.md
delete mode 100644 pydis_site/apps/content/tests/test_content/category/test3.md
delete mode 100644 pydis_site/apps/content/tests/test_content/test.md
delete mode 100644 pydis_site/apps/content/tests/test_content/test2.md
(limited to 'pydis_site')
diff --git a/Pipfile b/Pipfile
index c2b87ab4..c51215b6 100644
--- a/Pipfile
+++ b/Pipfile
@@ -36,6 +36,7 @@ mccabe = "~=0.6.1"
pep8-naming = "~=0.9"
pre-commit = "~=2.1"
unittest-xml-reporting = "~=3.0"
+pyfakefs = "~=4.4.0"
[requires]
python_version = "3.7"
diff --git a/Pipfile.lock b/Pipfile.lock
index 4f8bd0d3..6125e538 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
- "sha256": "a338a377b64a5d25bf925646c97d932a2d1c783fc8f40d91b6a9ab8f30c2b14e"
+ "sha256": "dc85f4f1b6ef58c2832d79542d6e88729cd2464bdf9324fef4d0757561f07ca7"
},
"pipfile-spec": 6,
"requires": {
@@ -605,6 +605,14 @@
"markers": "python_version >= '3.6'",
"version": "==6.0.0"
},
+ "pyfakefs": {
+ "hashes": [
+ "sha256:082d863e0e2a74351f697da404e329a91e18e5055942e59d1b836e8459b2c94c",
+ "sha256:1ac3b2845dabe69af56c20691b9347914581195ccdde352535fb7d4ff0055c19"
+ ],
+ "index": "pypi",
+ "version": "==4.4.0"
+ },
"pyflakes": {
"hashes": [
"sha256:910208209dcea632721cb58363d0f72913d9e8cf64dc6f8ae2e02a3609aba40d",
diff --git a/pydis_site/apps/content/tests/helpers.py b/pydis_site/apps/content/tests/helpers.py
new file mode 100644
index 00000000..4e0cca34
--- /dev/null
+++ b/pydis_site/apps/content/tests/helpers.py
@@ -0,0 +1,84 @@
+from pyfakefs.fake_filesystem_unittest import TestCase
+
+# Valid markdown content with YAML metadata
+MARKDOWN_WITH_METADATA = """
+---
+title: TestTitle
+description: TestDescription
+relevant_links:
+ Python Discord: https://pythondiscord.com
+ Discord: https://discord.com
+---
+# This is a header.
+"""
+
+MARKDOWN_WITHOUT_METADATA = """#This is a header."""
+
+# Valid YAML in a _info.yml file
+CATEGORY_INFO = """
+name: Category Name
+description: Description
+"""
+
+# The HTML generated from the above markdown data
+PARSED_HTML = (
+ ''
+)
+
+# The YAML metadata parsed from the above markdown data
+PARSED_METADATA = {
+ "title": "TestTitle", "description": "TestDescription",
+ "relevant_links": {
+ "Python Discord": "https://pythondiscord.com",
+ "Discord": "https://discord.com"
+ }
+}
+
+# The YAML data parsed from the above _info.yml file
+PARSED_CATEGORY_INFO = {"name": "Category Name", "description": "Description"}
+
+
+class MockPagesTestCase(TestCase):
+ """
+ TestCase with a fake filesystem for testing.
+
+ Structure:
+ ├── _info.yml
+ ├── root.md
+ ├── root_without_metadata.md
+ ├── not_a_page.md
+ ├── tmp
+ | ├── _info.yml
+ | └── category_without_info
+ └── category
+ ├── _info.yml
+ ├── with_metadata.md
+ └── subcategory
+ ├── with_metadata.md
+ └── without_metadata.md
+ """
+
+ def setUp(self):
+ """Create the fake filesystem."""
+ self.setUpPyfakefs()
+
+ self.fs.create_file("_info.yml", contents=CATEGORY_INFO)
+ self.fs.create_file("root.md", contents=MARKDOWN_WITH_METADATA)
+ self.fs.create_file("root_without_metadata.md", contents=MARKDOWN_WITHOUT_METADATA)
+ self.fs.create_file("not_a_page.md/_info.yml", contents=CATEGORY_INFO)
+ self.fs.create_file("category/_info.yml", contents=CATEGORY_INFO)
+ self.fs.create_file("category/with_metadata.md", contents=MARKDOWN_WITH_METADATA)
+ self.fs.create_file("category/subcategory/_info.yml", contents=CATEGORY_INFO)
+ self.fs.create_file(
+ "category/subcategory/with_metadata.md", contents=MARKDOWN_WITH_METADATA
+ )
+ self.fs.create_file(
+ "category/subcategory/without_metadata.md", contents=MARKDOWN_WITHOUT_METADATA
+ )
+
+ # There is always a `tmp` directory in the filesystem, so make it a category
+ # for testing purposes.
+ # See: https://jmcgeheeiv.github.io/pyfakefs/release/usage.html#os-temporary-directories
+ self.fs.create_file("tmp/_info.yml", contents=CATEGORY_INFO)
+ self.fs.create_dir("tmp/category_without_info")
diff --git a/pydis_site/apps/content/tests/test_content/_info.yml b/pydis_site/apps/content/tests/test_content/_info.yml
deleted file mode 100644
index ad5fc113..00000000
--- a/pydis_site/apps/content/tests/test_content/_info.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-name: Base Category
-description: Base Description
diff --git a/pydis_site/apps/content/tests/test_content/category/_info.yml b/pydis_site/apps/content/tests/test_content/category/_info.yml
deleted file mode 100644
index 8311509d..00000000
--- a/pydis_site/apps/content/tests/test_content/category/_info.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-name: My Category
-description: My Description
diff --git a/pydis_site/apps/content/tests/test_content/category/subcategory/_info.yml b/pydis_site/apps/content/tests/test_content/category/subcategory/_info.yml
deleted file mode 100644
index f1c40264..00000000
--- a/pydis_site/apps/content/tests/test_content/category/subcategory/_info.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-name: My Category 1
-description: My Description 1
diff --git a/pydis_site/apps/content/tests/test_content/category/subcategory/test4.md b/pydis_site/apps/content/tests/test_content/category/subcategory/test4.md
deleted file mode 100644
index 1763a869..00000000
--- a/pydis_site/apps/content/tests/test_content/category/subcategory/test4.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Test 4
-description: Testing 4
----
-
-This is also test content and in subcategory.
diff --git a/pydis_site/apps/content/tests/test_content/category/test3.md b/pydis_site/apps/content/tests/test_content/category/test3.md
deleted file mode 100644
index 9f294130..00000000
--- a/pydis_site/apps/content/tests/test_content/category/test3.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Test 3
-description: Testing 3
----
-
-This is too test content, but in category.
diff --git a/pydis_site/apps/content/tests/test_content/test.md b/pydis_site/apps/content/tests/test_content/test.md
deleted file mode 100644
index 709860d1..00000000
--- a/pydis_site/apps/content/tests/test_content/test.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: Test
-description: Testing
-relevant_links:
- Asking Good Questions: https://pythondiscord.com/pages/resources/guides/asking-good-questions/
- Help Channel Guide: https://pythondiscord.com/pages/resources/guides/help-channels/
- Code of Conduct: https://pythondiscord.com/pages/code-of-conduct/
----
-
-This is test content.
diff --git a/pydis_site/apps/content/tests/test_content/test2.md b/pydis_site/apps/content/tests/test_content/test2.md
deleted file mode 100644
index 0e57c3cd..00000000
--- a/pydis_site/apps/content/tests/test_content/test2.md
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Test 2
-description: Testing 2
----
-
-This is too test content.
diff --git a/pydis_site/apps/content/tests/test_utils.py b/pydis_site/apps/content/tests/test_utils.py
index 3831ad33..58175d6f 100644
--- a/pydis_site/apps/content/tests/test_utils.py
+++ b/pydis_site/apps/content/tests/test_utils.py
@@ -1,150 +1,91 @@
from pathlib import Path
-from unittest.mock import patch
-from django.conf import settings
from django.http import Http404
-from django.test import TestCase, override_settings
-from markdown2 import markdown
from pydis_site.apps.content import utils
+from pydis_site.apps.content.tests.helpers import (
+ MockPagesTestCase, PARSED_CATEGORY_INFO, PARSED_HTML, PARSED_METADATA
+)
-BASE_PATH = Path(settings.BASE_DIR, "pydis_site", "apps", "content", "tests", "test_content")
+class GetCategoryTests(MockPagesTestCase):
+ """Tests for the get_category function."""
-class TestGetCategory(TestCase):
- @override_settings(PAGES_PATH=BASE_PATH)
- def test_get_category_successfully(self):
- """Check does this get right data from category data file."""
- path = BASE_PATH.joinpath("category")
- result = utils.get_category(path)
+ def test_get_valid_category(self):
+ result = utils.get_category(Path("category"))
- self.assertEqual(result, {"name": "My Category", "description": "My Description"})
+ self.assertEqual(result, {"name": "Category Name", "description": "Description"})
- @override_settings(PAGES_PATH=BASE_PATH)
- def test_get_category_not_exists(self):
- """Check does this raise 404 error when category don't exists."""
+ def test_get_nonexistent_category(self):
with self.assertRaises(Http404):
- path = BASE_PATH.joinpath("invalid")
- utils.get_category(path)
+ utils.get_category(Path("invalid"))
- @override_settings(PAGES_PATH=BASE_PATH)
- def test_get_category_not_directory(self):
- """Check does this raise 404 error when category isn't directory."""
+ def test_get_category_with_path_to_file(self):
+ # Valid categories are directories, not files
with self.assertRaises(Http404):
- path = BASE_PATH.joinpath("test.md")
- utils.get_category(path)
+ utils.get_category(Path("root.md"))
+ def test_get_category_without_info_yml(self):
+ # Categories should provide an _info.yml file
+ with self.assertRaises(FileNotFoundError):
+ utils.get_category(Path("tmp/category_without_info"))
-class TestGetCategories(TestCase):
- @override_settings(PAGES_PATH=BASE_PATH)
- @patch("pydis_site.apps.content.utils.get_category")
- def test_get_categories(self, get_category_mock):
- """Check does this return test content categories."""
- get_category_mock.return_value = {"name": "My Category", "description": "My Description"}
- path = BASE_PATH.joinpath("category")
- result = utils.get_categories(path)
+class GetCategoriesTests(MockPagesTestCase):
+ """Tests for the get_categories function."""
- self.assertEqual(
- result, {"subcategory": {"name": "My Category", "description": "My Description"}}
- )
+ def test_get_root_categories(self):
+ result = utils.get_categories(Path("."))
+
+ info = PARSED_CATEGORY_INFO
+ self.assertEqual(result, {"category": info, "tmp": info, "not_a_page.md": info})
+
+ def test_get_categories_with_subcategories(self):
+ result = utils.get_categories(Path("category"))
+
+ self.assertEqual(result, {"subcategory": PARSED_CATEGORY_INFO})
+
+ def test_get_categories_without_subcategories(self):
+ result = utils.get_categories(Path("category/subcategory"))
+
+ self.assertEqual(result, {})
- @override_settings(PAGES_PATH=BASE_PATH)
- def test_get_categories_in_category(self):
- """Check does this call joinpath when getting subcategories."""
- path = BASE_PATH.joinpath("category")
- result = utils.get_categories(path)
+
+class GetCategoryPagesTests(MockPagesTestCase):
+ """Tests for the get_category_pages function."""
+
+ def test_get_pages_in_root_category_successfully(self):
+ """The method should successfully retrieve page metadata."""
+ root_category_pages = utils.get_category_pages(Path("."))
self.assertEqual(
- result, {"subcategory": {"name": "My Category 1", "description": "My Description 1"}}
+ root_category_pages, {"root": PARSED_METADATA, "root_without_metadata": {}}
)
+ def test_get_pages_in_subcategories_successfully(self):
+ """The method should successfully retrieve page metadata."""
+ category_pages = utils.get_category_pages(Path("category"))
-class TestGetPages(TestCase):
- @override_settings(PAGES_PATH=BASE_PATH)
- def test_get_all_root_pages(self):
- """Check does this return all root level testing content."""
- path = BASE_PATH
- result = utils.get_pages(path)
-
- for case in ["test", "test2"]:
- with self.subTest(guide=case):
- md = markdown(BASE_PATH.joinpath(f"{case}.md").read_text(), extras=["metadata"])
-
- self.assertIn(case, result)
- self.assertEqual(md.metadata, result[case])
-
- @override_settings(PAGES_PATH=BASE_PATH)
- def test_get_all_category_pages(self):
- """Check does this return all category testing content."""
- path = BASE_PATH.joinpath("category")
- result = utils.get_pages(path)
-
- md = markdown(BASE_PATH.joinpath("category", "test3.md").read_text(), extras=["metadata"])
-
- self.assertIn("test3", result)
- self.assertEqual(md.metadata, result["test3"])
-
-
-class TestGetPage(TestCase):
- @override_settings(PAGES_PATH=BASE_PATH)
- def test_get_root_page_success(self):
- """Check does this return page HTML and metadata when root page exist."""
- path = BASE_PATH.joinpath("test.md")
- result = utils.get_page(path)
-
- md = markdown(
- BASE_PATH.joinpath("test.md").read_text(),
- extras=[
- "metadata",
- "fenced-code-blocks",
- "header-ids",
- "strike",
- "target-blank-links",
- "tables",
- "task_list"
- ]
- )
+ # Page metadata is properly retrieved
+ self.assertEqual(category_pages, {"with_metadata": PARSED_METADATA})
- self.assertEqual(result, {"page": str(md), "metadata": md.metadata})
- @override_settings(PAGES_PATH=BASE_PATH)
- def test_get_root_page_dont_exist(self):
- """Check does this raise Http404 when root page don't exist."""
- with self.assertRaises(Http404):
- path = BASE_PATH.joinpath("invalid")
- utils.get_page(path)
-
- @override_settings(PAGES_PATH=BASE_PATH)
- def test_get_category_page_success(self):
- """Check does this return page HTML and metadata when category guide exist."""
- path = BASE_PATH.joinpath("category", "test3.md")
- result = utils.get_page(path)
-
- md = markdown(
- BASE_PATH.joinpath("category", "test3.md").read_text(),
- extras=[
- "metadata",
- "fenced-code-blocks",
- "header-ids",
- "strike",
- "target-blank-links",
- "tables",
- "task_list"
- ]
- )
+class GetPageTests(MockPagesTestCase):
+ """Tests for the get_page function."""
- self.assertEqual(result, {"page": str(md), "metadata": md.metadata})
+ def test_get_page(self):
+ cases = [
+ ("Root page with metadata", "root.md", PARSED_HTML, PARSED_METADATA),
+ ("Root page without metadata", "root_without_metadata.md", PARSED_HTML, {}),
+ ("Page with metadata", "category/with_metadata.md", PARSED_HTML, PARSED_METADATA),
+ ("Page without metadata", "category/subcategory/without_metadata.md", PARSED_HTML, {}),
+ ]
- @override_settings(PAGES_PATH=BASE_PATH)
- def test_get_category_page_dont_exist(self):
- """Check does this raise Http404 when category page don't exist."""
- with self.assertRaises(Http404):
- path = BASE_PATH.joinpath("category", "invalid")
- utils.get_page(path)
+ for msg, page_path, expected_html, expected_metadata in cases:
+ with self.subTest(msg=msg):
+ html, metadata = utils.get_page(Path(page_path))
+ self.assertEqual(html, expected_html)
+ self.assertEqual(metadata, expected_metadata)
- @patch("pydis_site.settings.PAGES_PATH", new=BASE_PATH)
- def test_get_category_page_category_dont_exist(self):
- """Check does this raise Http404 when category don't exist."""
+ def test_get_nonexistent_page_returns_404(self):
with self.assertRaises(Http404):
- path = BASE_PATH.joinpath("invalid", "some-guide")
- utils.get_page(path)
+ utils.get_page(Path("invalid"))
diff --git a/pydis_site/apps/content/tests/test_views.py b/pydis_site/apps/content/tests/test_views.py
index c61671a2..560378bc 100644
--- a/pydis_site/apps/content/tests/test_views.py
+++ b/pydis_site/apps/content/tests/test_views.py
@@ -1,140 +1,145 @@
from pathlib import Path
-from unittest.mock import patch
+from unittest import TestCase
-from django.conf import settings
from django.http import Http404
-from django.test import RequestFactory, TestCase, override_settings
-from django_hosts.resolvers import reverse
+from django.test import RequestFactory, SimpleTestCase, override_settings
+from pyfakefs import fake_filesystem_unittest
+from pydis_site.apps.content.tests.helpers import (
+ MockPagesTestCase, PARSED_CATEGORY_INFO, PARSED_HTML, PARSED_METADATA
+)
from pydis_site.apps.content.views import PageOrCategoryView
-BASE_PATH = Path(settings.BASE_DIR, "pydis_site", "apps", "content", "tests", "test_content")
-
-
-class TestPageOrCategoryView(TestCase):
- @override_settings(PAGES_PATH=BASE_PATH)
- @patch("pydis_site.apps.content.views.page_category.utils.get_page")
- @patch("pydis_site.apps.content.views.page_category.utils.get_category")
- def test_page_return_code_200(self, get_category_mock, get_page_mock):
- get_page_mock.return_value = {"guide": "test", "metadata": {}}
-
- url = reverse("content:page_category", args=["test2"])
- response = self.client.get(url)
- self.assertEqual(response.status_code, 200)
- get_category_mock.assert_called_once()
- get_page_mock.assert_called_once()
-
- @patch("pydis_site.apps.content.views.page_category.utils.get_page")
- @patch("pydis_site.apps.content.views.page_category.utils.get_category")
- @override_settings(PAGES_PATH=BASE_PATH)
- def test_page_return_404(self, get_category_mock, get_page_mock):
- """Check that return code is 404 when invalid page provided."""
- get_page_mock.side_effect = Http404("Page not found.")
-
- url = reverse("content:page_category", args=["invalid-guide"])
- response = self.client.get(url)
- self.assertEqual(response.status_code, 404)
- get_page_mock.assert_not_called()
- get_category_mock.assert_not_called()
-
- @patch("pydis_site.apps.content.views.page_category.utils.get_category")
- @patch("pydis_site.apps.content.views.page_category.utils.get_pages")
- @patch("pydis_site.apps.content.views.page_category.utils.get_categories")
- @override_settings(PAGES_PATH=BASE_PATH)
- def test_valid_category_code_200(
- self,
- get_categories_mock,
- get_pages_mock,
- get_category_mock
- ):
- """Check that return code is 200 when visiting valid category."""
- get_category_mock.return_value = {"name": "test", "description": "test"}
- get_pages_mock.return_value = {}
-
- url = reverse("content:page_category", args=["category"])
- response = self.client.get(url)
-
- self.assertEqual(response.status_code, 200)
- get_pages_mock.assert_called_once()
- self.assertEqual(get_category_mock.call_count, 2)
- get_categories_mock.assert_called_once()
-
- @patch("pydis_site.apps.content.views.page_category.utils.get_category")
- @patch("pydis_site.apps.content.views.page_category.utils.get_pages")
- @patch("pydis_site.apps.content.views.page_category.utils.get_categories")
- @override_settings(PAGES_PATH=BASE_PATH)
- def test_invalid_category_code_404(
- self,
- get_categories_mock,
- get_pages_mock,
- get_category_mock
- ):
- """Check that return code is 404 when trying to visit invalid category."""
- get_category_mock.side_effect = Http404("Category not found.")
-
- url = reverse("content:page_category", args=["invalid-category"])
- response = self.client.get(url)
-
- self.assertEqual(response.status_code, 404)
- get_category_mock.assert_not_called()
- get_pages_mock.assert_not_called()
- get_categories_mock.assert_not_called()
-
- @patch("pydis_site.apps.content.views.page_category.utils.get_page")
- @patch("pydis_site.apps.content.views.page_category.utils.get_category")
- @override_settings(PAGES_PATH=BASE_PATH)
- def test_valid_category_page_code_200(
- self,
- get_category_mock,
- get_page_mock
- ):
- """Check that return code is 200 when visiting valid category page."""
- get_page_mock.return_value = {"guide": "test", "metadata": {}}
-
- url = reverse("content:page_category", args=["category/test3"])
- response = self.client.get(url)
- self.assertEqual(response.status_code, 200)
- get_page_mock.assert_called_once()
- self.assertEqual(get_category_mock.call_count, 2)
-
- @patch("pydis_site.apps.content.views.page_category.utils.get_page")
- @patch("pydis_site.apps.content.views.page_category.utils.get_category")
- @override_settings(PAGES_PATH=BASE_PATH)
- def test_invalid_category_page_code_404(
- self,
- get_category_mock,
- get_page_mock
- ):
- """Check that return code is 200 when trying to visit invalid category page."""
- get_page_mock.side_effect = Http404("Page not found.")
-
- url = reverse("content:page_category", args=["category/invalid"])
- response = self.client.get(url)
- self.assertEqual(response.status_code, 404)
- get_page_mock.assert_not_called()
- get_category_mock.assert_not_called()
-
- @override_settings(PAGES_PATH=BASE_PATH)
- def test_page_category_template_names(self):
- """Check that this return category, page template or raise Http404."""
- factory = RequestFactory()
+
+# Set the module constant within Patcher to use the fake filesystem
+# https://jmcgeheeiv.github.io/pyfakefs/master/usage.html#modules-to-reload
+with fake_filesystem_unittest.Patcher() as _:
+ BASE_PATH = Path(".")
+
+
+@override_settings(PAGES_PATH=BASE_PATH)
+class PageOrCategoryViewTests(MockPagesTestCase, SimpleTestCase, TestCase):
+ """Tests for the PageOrCategoryView class."""
+
+ def setUp(self):
+ """Set test helpers, then set up fake filesystem."""
+ self.factory = RequestFactory()
+ self.view = PageOrCategoryView.as_view()
+ self.ViewClass = PageOrCategoryView()
+ super().setUp()
+
+ # Integration tests
+ def test_valid_page_or_category_returns_200(self):
+ cases = [
+ ("Page at root", "root"),
+ ("Category page", "category"),
+ ("Page in category", "category/with_metadata"),
+ ("Subcategory page", "category/subcategory"),
+ ("Page in subcategory", "category/subcategory/with_metadata"),
+ ]
+ for msg, path in cases:
+ with self.subTest(msg=msg, path=path):
+ request = self.factory.get(f"/{path}")
+ response = self.view(request, location=path)
+ self.assertEqual(response.status_code, 200)
+
+ def test_nonexistent_page_returns_404(self):
+ with self.assertRaises(Http404):
+ request = self.factory.get("/invalid")
+ self.view(request, location="invalid")
+
+ # Unit tests
+ def test_get_template_names_returns_correct_templates(self):
+ category_template = "content/listing.html"
+ page_template = "content/page.html"
+ cases = [
+ ("root", page_template),
+ ("root_without_metadata", page_template),
+ ("category/with_metadata", page_template),
+ ("category/subcategory/with_metadata", page_template),
+ ("category", category_template),
+ ("category/subcategory", category_template),
+ ]
+
+ for path, expected_template in cases:
+ with self.subTest(path=path, expected_template=expected_template):
+ self.ViewClass.full_location = Path(path)
+ self.assertEqual(self.ViewClass.get_template_names(), [expected_template])
+
+ def test_get_template_names_with_nonexistent_paths_returns_404(self):
+ for path in ("invalid", "another_invalid", "nonexistent"):
+ with self.subTest(path=path):
+ self.ViewClass.full_location = Path(path)
+ with self.assertRaises(Http404):
+ self.ViewClass.get_template_names()
+
+ def test_get_context_data_with_valid_page(self):
+ """The method should return required fields in the template context."""
+ request = self.factory.get("/root")
+ self.ViewClass.setup(request)
+ self.ViewClass.dispatch(request, location="root")
+
+ cases = [
+ ("Context includes HTML page content", "page", PARSED_HTML),
+ ("Context includes page title", "page_title", PARSED_METADATA["title"]),
+ (
+ "Context includes page description",
+ "page_description",
+ PARSED_METADATA["description"]
+ ),
+ (
+ "Context includes relevant link names and URLs",
+ "relevant_links",
+ PARSED_METADATA["relevant_links"]
+ ),
+ ]
+ context = self.ViewClass.get_context_data()
+ for msg, key, expected_value in cases:
+ with self.subTest(msg=msg):
+ self.assertEqual(context[key], expected_value)
+
+ def test_get_context_data_with_valid_category(self):
+ """The method should return required fields in the template context."""
+ request = self.factory.get("/category")
+ self.ViewClass.setup(request)
+ self.ViewClass.dispatch(request, location="category")
+
cases = [
- {"location": "category", "output": ["content/listing.html"]},
- {"location": "test", "output": ["content/page.html"]},
- {"location": "invalid", "output": None, "raises": Http404}
+ (
+ "Context includes subcategory names and their information",
+ "categories",
+ {"subcategory": PARSED_CATEGORY_INFO}
+ ),
+ (
+ "Context includes page names and their metadata",
+ "pages",
+ {"with_metadata": PARSED_METADATA}
+ ),
+ (
+ "Context includes page description",
+ "page_description",
+ PARSED_CATEGORY_INFO["description"]
+ ),
+ ("Context includes page title", "page_title", PARSED_CATEGORY_INFO["name"]),
]
- for case in cases:
- with self.subTest(location=case["location"], output=case["output"]):
- request = factory.get(f"/pages/{case['location']}")
- instance = PageOrCategoryView()
- instance.request = request
- location = Path(case["location"])
- instance.location = location
- instance.full_location = BASE_PATH / location
-
- if "raises" in case:
- with self.assertRaises(case["raises"]):
- instance.get_template_names()
- else:
- self.assertEqual(case["output"], instance.get_template_names())
+ context = self.ViewClass.get_context_data()
+ for msg, key, expected_value in cases:
+ with self.subTest(msg=msg):
+ self.assertEqual(context[key], expected_value)
+
+ def test_get_context_data_breadcrumbs(self):
+ """The method should return correct breadcrumbs."""
+ request = self.factory.get("/category/subcategory/with_metadata")
+ self.ViewClass.setup(request)
+ self.ViewClass.dispatch(request, location="category/subcategory/with_metadata")
+
+ context = self.ViewClass.get_context_data()
+ self.assertEquals(
+ context["breadcrumb_items"],
+ [
+ {"name": PARSED_CATEGORY_INFO["name"], "path": "."},
+ {"name": PARSED_CATEGORY_INFO["name"], "path": "category"},
+ {"name": PARSED_CATEGORY_INFO["name"], "path": "category/subcategory"},
+ ]
+ )
diff --git a/pydis_site/apps/content/utils.py b/pydis_site/apps/content/utils.py
index 11d2b792..726c991f 100644
--- a/pydis_site/apps/content/utils.py
+++ b/pydis_site/apps/content/utils.py
@@ -33,7 +33,7 @@ def get_category_pages(path: Path) -> Dict[str, Dict]:
for item in path.glob("*.md"):
if item.is_file():
- pages[item.stem] = frontmatter.load(item)
+ pages[item.stem] = frontmatter.load(item).metadata
return pages
diff --git a/pydis_site/apps/content/views/page_category.py b/pydis_site/apps/content/views/page_category.py
index 4a2ed2d6..eec4e7e5 100644
--- a/pydis_site/apps/content/views/page_category.py
+++ b/pydis_site/apps/content/views/page_category.py
@@ -13,7 +13,7 @@ class PageOrCategoryView(TemplateView):
def dispatch(self, request: t.Any, *args, **kwargs) -> t.Any:
"""Conform URL path location to the filesystem path."""
- self.location = Path(self.kwargs.get("location", ""))
+ self.location = Path(kwargs.get("location", ""))
self.full_location = settings.PAGES_PATH / self.location
return super().dispatch(request, *args, **kwargs)
--
cgit v1.2.3
From eb308e9ff697c1879f102522ece9bb97e77c5262 Mon Sep 17 00:00:00 2001
From: kosayoda
Date: Fri, 26 Mar 2021 14:34:49 +0800
Subject: Remove guide reference to `markdown2`.
Now that we use a separate library for frontmatter (which uses pyyaml),
we can simplify the guide and remove the reference to the old markdown
library.
---
.../content/resources/guides/pydis-guides/how-to-contribute-a-page.md | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
(limited to 'pydis_site')
diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/how-to-contribute-a-page.md b/pydis_site/apps/content/resources/guides/pydis-guides/how-to-contribute-a-page.md
index 12969ba2..f258ef74 100644
--- a/pydis_site/apps/content/resources/guides/pydis-guides/how-to-contribute-a-page.md
+++ b/pydis_site/apps/content/resources/guides/pydis-guides/how-to-contribute-a-page.md
@@ -37,7 +37,7 @@ All the markdown files in this folder will then be under this category.
Files representing pages are in `.md` (Markdown) format, with all-lowercase filenames and spaces replaced with `-` characters.
Each page must include required metadata, and optionally additional metadata to modify the appearance of the page.
-The metadata is written in YAML-like key-value pairs, and should be enclosed in triple dashes `---` *at the top of the markdown file*.
+The metadata is written in YAML, and should be enclosed in triple dashes `---` *at the top of the markdown file*.
**Example:**
```yaml
@@ -54,8 +54,6 @@ relevant_links:
Pages, which include guides, articles, and other static content,...
```
-You can learn more about Markdown metadata [here](https://github.com/trentm/python-markdown2/wiki/metadata).
-
### Required Fields
- **title:** Easily-readable title for your article.
- **description:** Short, 1-2 line description of the page's content.
--
cgit v1.2.3