picata 0.0.7__py3-none-any.whl → 0.0.8__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
picata/blocks.py CHANGED
@@ -110,12 +110,13 @@ class CodeBlock(StructBlock):
110
110
  language = ChoiceBlock(
111
111
  required=False,
112
112
  choices=[
113
- ("python", "Python"),
114
- ("javascript", "JavaScript"),
115
- ("html", "HTML"),
116
- ("css", "CSS"),
117
- ("bash", "Bash"),
118
113
  ("plaintext", "Plain Text"),
114
+ ("bash", "Bash"),
115
+ ("css", "CSS"),
116
+ ("html", "HTML"),
117
+ ("javascript", "JavaScript"),
118
+ ("python", "Python"),
119
+ ("toml", "TOML"),
119
120
  ],
120
121
  help_text=None,
121
122
  )
picata/helpers/wagtail.py CHANGED
@@ -53,7 +53,7 @@ def filter_pages_by_type(pages: list[Page], page_type_slugs: set[str]) -> list[P
53
53
  return filtered_pages
54
54
 
55
55
 
56
- def page_preview_data(request: HttpRequest, page: Page) -> dict[str, str]:
56
+ def page_preview_data(page: Page, request: HttpRequest | None) -> dict[str, str]:
57
57
  """Return a dictionary of available publication and preview data for a page."""
58
58
  page_data = getattr(page, "preview_data", {}).copy()
59
59
  if hasattr(page, "get_publication_data"):
picata/models.py CHANGED
@@ -110,7 +110,7 @@ class BasePage(Page):
110
110
  from picata.helpers.wagtail import page_preview_data
111
111
 
112
112
  context = super().get_context(request, *args, **kwargs)
113
- context.update(page_preview_data(request, self))
113
+ context.update(page_preview_data(self, request))
114
114
  return cast(BasePageContext, {**context})
115
115
 
116
116
  class Meta:
@@ -472,7 +472,7 @@ class HomePage(BasePage):
472
472
  from picata.helpers.wagtail import page_preview_data
473
473
 
474
474
  recent_posts = Article.objects.live_for_user(request.user).by_date()
475
- recent_posts = [page_preview_data(request, post) for post in recent_posts]
475
+ recent_posts = [page_preview_data(post, request) for post in recent_posts]
476
476
 
477
477
  return cast(
478
478
  HomePageContext,
picata/urls.py CHANGED
@@ -10,7 +10,7 @@ from wagtail.contrib.sitemaps.views import sitemap
10
10
  from wagtail.documents import urls as wagtaildocs_urls
11
11
  from wagtail.images.views.serve import ServeView
12
12
 
13
- from picata.views import search
13
+ from picata.views import AtomArticleFeed, RSSArticleFeed, search
14
14
 
15
15
  urlpatterns = [
16
16
  path("django-admin/", admin.site.urls), # Django Admin
@@ -20,6 +20,8 @@ urlpatterns = [
20
20
  r"^images/([^/]*)/(\d*)/([^/]*)/[^/]*$", ServeView.as_view(), name="wagtailimages_serve"
21
21
  ),
22
22
  path("sitemap.xml", sitemap),
23
+ path("feeds/rss/", RSSArticleFeed(), name="rss_feed"),
24
+ path("feeds/atom/", AtomArticleFeed(), name="atom_feed"),
23
25
  path("search/", search, name="search"),
24
26
  ]
25
27
 
picata/views.py CHANGED
@@ -4,10 +4,13 @@
4
4
  # pyright: reportAttributeAccessIssue=false, reportArgumentType=false
5
5
 
6
6
  import logging
7
+ from datetime import datetime
7
8
  from typing import TYPE_CHECKING, NoReturn
8
9
 
10
+ from django.contrib.syndication.views import Feed
9
11
  from django.http import HttpRequest, HttpResponse
10
12
  from django.shortcuts import render
13
+ from django.utils.feedgenerator import Atom1Feed, Rss201rev2Feed
11
14
 
12
15
  from picata.helpers.wagtail import (
13
16
  filter_pages_by_tags,
@@ -15,7 +18,7 @@ from picata.helpers.wagtail import (
15
18
  page_preview_data,
16
19
  visible_pages_qs,
17
20
  )
18
- from picata.models import ArticleType
21
+ from picata.models import Article, ArticleType
19
22
 
20
23
  if TYPE_CHECKING:
21
24
  from wagtail.query import PageQuerySet
@@ -23,6 +26,54 @@ if TYPE_CHECKING:
23
26
  logger = logging.getLogger(__name__)
24
27
 
25
28
 
29
+ class PostsFeed(Feed):
30
+ """Base class for RSS and Atom article feeds."""
31
+
32
+ title = "hpk.io Articles"
33
+ link = "https://hpk.io/blog/"
34
+ description = "Latest posts on hpk.io"
35
+
36
+ def items(self) -> list[Article]:
37
+ """Return the latest 10 published articles."""
38
+ return list(Article.objects.live().order_by("-first_published_at"))
39
+
40
+ def item_title(self, item: Article) -> str:
41
+ """Return the article title."""
42
+ return item.title
43
+
44
+ def item_link(self, item: Article) -> str:
45
+ """Return the absolute URL for the article."""
46
+ return item.full_url
47
+
48
+ def item_description(self, item: Article) -> str:
49
+ """Return the article body as HTML with absolute URLs."""
50
+ return item.content
51
+
52
+ def item_pubdate(self, item: Article) -> datetime:
53
+ """Return the article creation date."""
54
+ return item.first_published_at
55
+
56
+ def item_updateddate(self, item: Article) -> datetime:
57
+ """Return the article creation date."""
58
+ return item.last_published_at
59
+
60
+ def item_author_name(self, item: Article) -> str:
61
+ """Return the name of the author."""
62
+ return "Ada Wright"
63
+
64
+
65
+ class RSSArticleFeed(PostsFeed):
66
+ """RSS feed for articles."""
67
+
68
+ feed_type = Rss201rev2Feed
69
+
70
+
71
+ class AtomArticleFeed(PostsFeed):
72
+ """Atom feed for articles."""
73
+
74
+ feed_type = Atom1Feed
75
+
76
+
26
77
  def debug_shell(request: HttpRequest) -> NoReturn:
27
78
  """Just `assert False`, to force an exception and get to the Werkzeug debug console."""
28
79
  logger.info(
@@ -76,6 +127,6 @@ def search(request: HttpRequest) -> HttpResponse:
76
127
  specific_pages = []
77
128
 
78
129
  # Enhance pages with preview and publication data
79
- page_previews = [page_preview_data(request, page) for page in specific_pages]
130
+ page_previews = [page_preview_data(page, request) for page in specific_pages]
80
131
 
81
132
  return render(request, "picata/search_results.html", {**results, "pages": page_previews})
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: picata
3
- Version: 0.0.7
3
+ Version: 0.0.8
4
4
  Summary: Ada's Wagtail-based CMS & blog
5
5
  Project-URL: Documentation, https://github.com/hipikat/picata#readme
6
6
  Project-URL: Issues, https://github.com/hipikat/picata/issues
@@ -808,18 +808,18 @@ styles.sass,sha256=SCG5WCr0jIGzdM_Vp_j_gKxFfcTsTwLWOmaEc6uMpvU,8501
808
808
  components/HelloWorld.tsx,sha256=Kp7gvhGehfrX1mw0jgr2_D6AueFgqgfMYGkyQgvWekg,180
809
809
  picata/__init__.py,sha256=ZCIoFQ_z3ias_sP4C77EU2IUJnyv4qR0xUdJ3PIdLLM,48
810
810
  picata/apps.py,sha256=kr6OBcYbBw9HCGG-PkoMTHR4QeyzJO8_KIWTljCTHRo,1255
811
- picata/blocks.py,sha256=xfFpyCL5djWmZBBrBPO1dTTAUjk3l0XLfu8qSPixejg,5303
811
+ picata/blocks.py,sha256=ivu3i9s5xfpB40yaCc50qkDu4H5u6XVuZ1qDqTZi6gk,5333
812
812
  picata/log_utils.py,sha256=BRdB3PqpFx1XAhIyAzIOyQKiqrjbT3PBmkhH6-wAWJg,1555
813
813
  picata/middleware.py,sha256=BbAifo--C4VYg1VhU8_qbdDcJUD9zYdbxU_9nqGpMa8,2067
814
- picata/models.py,sha256=0gEhUrdSKIkv76UqMej5VHE5VPJuNFPkA5fPCrEoCxM,15931
814
+ picata/models.py,sha256=Lv7BjW-RrsdV85Uvw_eo1DyiOAaqId1ew0o1wg4jYp0,15931
815
815
  picata/transformers.py,sha256=CBnbIX3dnFV_gfp4TDTMPA_jGD8V_E4onodxWqbsjyY,2212
816
- picata/urls.py,sha256=SAbmFKAgrM80LREULczs64hExbwmLOlsflXlo7qjzsc,1834
816
+ picata/urls.py,sha256=DlAOlkAeAHTCl4txY9rxtgc6vp822Ei2niiaiej29Sk,1988
817
817
  picata/validators.py,sha256=X4wdIxbCdmuU-gJv45ptTFB7kHR166jkSQBJiTzP3ZU,1517
818
- picata/views.py,sha256=N6RYLDOTHAGBv0cYxese3T0gOvI6C99_q_Lv-3zbjrc,2881
818
+ picata/views.py,sha256=8BugjOHI8OKYQ1_QKednKOFqai7yOhyGpTW6qs2dlYs,4401
819
819
  picata/wagtail_hooks.py,sha256=R1YgJwp_ZvYm65b_xvLS8HiBWxflXFXSB4SksbJxW3k,1500
820
820
  picata/wsgi.py,sha256=5vKFvebtHzxKb3BRVqps6SEKjWmOecBIkTwf4LqWJ0Q,398
821
821
  picata/helpers/__init__.py,sha256=acN445qKCuRVfInCEyCtx5W1BggloOSrawzdQ-c9m7s,2427
822
- picata/helpers/wagtail.py,sha256=ZJUqA31PBIu2lFtwfeEax3xu2UON0Yoa4cca79xdCc0,2111
822
+ picata/helpers/wagtail.py,sha256=89efaXwd7V63ds3c7w0ct6IDp63RrXCf4pGNW9dvhCI,2118
823
823
  picata/migrations/0001_initial.py,sha256=GnAiniyc1E9JsR-dYrEoVimvuIftazhfxEFCGJElKko,11943
824
824
  picata/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
825
825
  picata/settings/__init__.py,sha256=5qI40E9aCWsFanUxAnruZi1wXrad3oAwnusglycfPsk,47
@@ -870,7 +870,7 @@ picata/templatetags/tags/absolute_static.py,sha256=JNqNCMGIgiQDYdz44T5AB2l0yJTd_
870
870
  picata/templatetags/tags/menu_tags.py,sha256=PHuXl4QmIqycWilAyz1fjD_0uJxOSrCW7RnZxmR3Oh0,1860
871
871
  picata/typing/__init__.py,sha256=7qXco9cqvbveKX0Xprrc8DmgXa3MpkIQXtFsHDe77os,405
872
872
  picata/typing/wagtail.py,sha256=V0n9GYYb_CM5ic54lcRtpN6lhN37-QdRzz2mGKm3Cwc,664
873
- picata-0.0.7.dist-info/METADATA,sha256=dF5DTTG-fr0aXvynhdWykkneI_f6UQZRRRI5A1ojKJA,5092
874
- picata-0.0.7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
875
- picata-0.0.7.dist-info/licenses/LICENSE.md,sha256=Bv8sMyZI5NI6DMrfiAvCwIFRLSfJkimLF2KVcUMteKU,1103
876
- picata-0.0.7.dist-info/RECORD,,
873
+ picata-0.0.8.dist-info/METADATA,sha256=o8vTsY31AgnFwniMIcgexAQOuePUfXmFFAZEbch5iJA,5092
874
+ picata-0.0.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
875
+ picata-0.0.8.dist-info/licenses/LICENSE.md,sha256=Bv8sMyZI5NI6DMrfiAvCwIFRLSfJkimLF2KVcUMteKU,1103
876
+ picata-0.0.8.dist-info/RECORD,,
File without changes