diff --git a/pelican/plugins/activitypub/activitypub.py b/pelican/plugins/activitypub/activitypub.py index bf20da3..168ab24 100644 --- a/pelican/plugins/activitypub/activitypub.py +++ b/pelican/plugins/activitypub/activitypub.py @@ -1,11 +1,8 @@ - import datetime -import json import logging +import json import os import urllib.parse -from typing import Any, Dict - import pelican.writers from pelican import signals @@ -15,16 +12,15 @@ log = logging.getLogger(__name__) __version__ = '0.1.2' -PAGINATION = 25 +pagination = 25 -ENCODING = 'UTF-8' def ap_article(generator: pelican.ArticlesGenerator, writer: pelican.writers.Writer): now = datetime.datetime.utcnow() author = generator.settings['AUTHOR'] - domain: str = urllib.parse.urlparse(generator.settings['SITEURL']).netloc + domain = urllib.parse.urlparse(generator.settings['SITEURL']).netloc wkhmpath = os.path.join(writer.output_path, '.well-known/host-meta') wknipath = os.path.join(writer.output_path, '.well-known/nodeinfo') @@ -74,7 +70,7 @@ def ap_article(generator: pelican.ArticlesGenerator, writer: pelican.writers.Wri } } wfurl = os.path.join(generator.settings['SITEURL'], '.well-known/webfinger?resource={uri}') - hostmeta = f'' + hostmeta = f'' webfinger = { 'subject': f'acct:{author}@{domain}', 'aliases': [ @@ -94,13 +90,13 @@ def ap_article(generator: pelican.ArticlesGenerator, writer: pelican.writers.Wri } ] } - with open(wkhmpath, 'w', encoding=ENCODING) as hf: + with open(wkhmpath, 'w') as hf: hf.write(hostmeta) - with open(wknipath, 'w', encoding=ENCODING) as nf: + with open(wknipath, 'w') as nf: json.dump(wknodeinfo, nf) - with open(nipath, 'w', encoding=ENCODING) as nf: + with open(nipath, 'w') as nf: json.dump(nodeinfo, nf) - with open(wfpath, 'w', encoding=ENCODING) as wf: + with open(wfpath, 'w') as wf: json.dump(webfinger, wf) for t in generator.tags: @@ -120,7 +116,7 @@ def ap_article(generator: pelican.ArticlesGenerator, writer: pelican.writers.Wri 'totalItems': len(articles), 'orderedItems': articles } - with open(path, 'w', encoding=ENCODING) as f: + with open(path, 'w') as f: json.dump(tag, f) articlemap = {} @@ -144,7 +140,7 @@ def ap_article(generator: pelican.ArticlesGenerator, writer: pelican.writers.Wri replyto = os.path.join(generator.settings['SITEURL'], 'activitypub/posts', sa.slug) break cc = [os.path.join(generator.settings['SITEURL'], 'activitypub/collections/followers', article.author.slug)] - aa: Dict[str, Dict[str, Any]] = generator.settings.get('ACTIVITYPUB_AUTHORS', {}).get(author.name, {}) + aa = generator.settings.get('ACTIVITYPUB_AUTHORS', {}).get(author.name, {}) if 'movedTo' in aa: cc.append(aa['movedTo']) tags.append({ @@ -175,7 +171,7 @@ def ap_article(generator: pelican.ArticlesGenerator, writer: pelican.writers.Wri 'attachment': [], 'tag': tags } - with open(apath, 'w', encoding=ENCODING) as f: + with open(apath, 'w') as f: json.dump(articlemap[article.slug], f) for author, articles in generator.authors: @@ -257,7 +253,7 @@ def ap_article(generator: pelican.ArticlesGenerator, writer: pelican.writers.Wri 'totalItems': 0, 'orderedItems': [] } - maxpage = len(creates) // PAGINATION + maxpage = len(creates) // pagination outbox = { '@context': ['https://www.w3.org/ns/activitystreams'], 'type': 'OrderedCollection', @@ -280,8 +276,8 @@ def ap_article(generator: pelican.ArticlesGenerator, writer: pelican.writers.Wri 'totalItems': 0, 'orderedItems': [] } - for i in range(0, len(creates), PAGINATION): - ipage = i // PAGINATION + for i in range(0, len(creates), pagination): + ipage = i // pagination outpageurl = os.path.join(generator.settings['SITEURL'], 'activitypub/collections/outbox_page', author.slug, str(ipage)) outpagepath = os.path.join(writer.output_path, 'activitypub/collections/outbox_page', author.slug, str(ipage)) page = { @@ -290,13 +286,13 @@ def ap_article(generator: pelican.ArticlesGenerator, writer: pelican.writers.Wri 'id': outpageurl, 'totalItems': len(creates), 'partOf': outboxurl, - 'orderedItems': creates[i:i+PAGINATION] + 'orderedItems': creates[i:i+pagination] } if ipage > 0: page['prev'] = os.path.join(generator.settings['SITEURL'], 'activitypub/collections/outbox_page', author.slug, str(ipage-1)) if ipage < maxpage: page['next'] = os.path.join(generator.settings['SITEURL'], 'activitypub/collections/outbox_page', author.slug, str(ipage+1)) - with open(outpagepath, 'w', encoding=ENCODING) as f: + with open(outpagepath, 'w') as f: json.dump(page, f) author_webfinger = { 'subject': f'acct:{author.name}@{domain}', @@ -317,17 +313,17 @@ def ap_article(generator: pelican.ArticlesGenerator, writer: pelican.writers.Wri } ] } - with open(os.path.join(awfpath, author.name), 'w', encoding=ENCODING) as f: + with open(os.path.join(awfpath, author.name), 'w') as f: json.dump(author_webfinger, f) - with open(os.path.join(authorpath, author.name), 'w', encoding=ENCODING) as f: + with open(os.path.join(authorpath, author.name), 'w') as f: json.dump(a, f) - with open(inboxpath, 'w', encoding=ENCODING) as f: + with open(inboxpath, 'w') as f: json.dump(inbox, f) - with open(outboxpath, 'w', encoding=ENCODING) as f: + with open(outboxpath, 'w') as f: json.dump(outbox, f) - with open(followingpath, 'w', encoding=ENCODING) as f: + with open(followingpath, 'w') as f: json.dump(following, f) - with open(followerspath, 'w', encoding=ENCODING) as f: + with open(followerspath, 'w') as f: json.dump(followers, f) diff --git a/pelican/plugins/activitypub/activitypub_test.py b/pelican/plugins/activitypub/activitypub_test.py deleted file mode 100644 index 88c47a1..0000000 --- a/pelican/plugins/activitypub/activitypub_test.py +++ /dev/null @@ -1,62 +0,0 @@ -# SPDX-FileCopyrightText: 2024 Tobias Schmidl -# -# SPDX-License-Identifier: MIT - -"""Unit tests for the ActivityPub plugin""" - -import datetime -import unittest -from unittest.mock import MagicMock, patch -import os -import json -from activitypub import ap_article, ENCODING - -class TestApArticle(unittest.TestCase): - """Tests the ap_article function""" - - @patch('os.makedirs') - @patch('builtins.open') - @patch('json.dump') - def test_ap_article(self, mock_json_dump, mock_open, mock_makedirs): - # Mock the generator and writer - generator = MagicMock() - writer = MagicMock() - - # Mock settings - generator.settings = { - 'AUTHOR': 'test_author', - 'SITEURL': 'http://example.com', - 'SITENAME': 'Test Site', - 'ACTIVITYPUB_AUTHORS': {} - } - - # Mock authors and articles - generator.authors = [('test_author', MagicMock(slug='test_author'))] - generator.articles = [MagicMock(slug='test_article', date=datetime.datetime.utcnow(), title='Test Article', content='Test Content', metadata={'tags': ['test_tag']}, author=MagicMock(slug='test_author'), url='test_article.html', translations=[])] - generator.tags = [MagicMock(slug='test_tag', name='test_tag')] - - # Call the function - ap_article(generator, writer) - - # Check if directories were created - mock_makedirs.assert_any_call(os.path.join(writer.output_path, '.well-known'), exist_ok=True) - mock_makedirs.assert_any_call(os.path.join(writer.output_path, 'activitypub/users'), exist_ok=True) - mock_makedirs.assert_any_call(os.path.join(writer.output_path, 'activitypub/posts'), exist_ok=True) - mock_makedirs.assert_any_call(os.path.join(writer.output_path, 'activitypub/tags'), exist_ok=True) - mock_makedirs.assert_any_call(os.path.join(writer.output_path, 'activitypub/collections/inbox'), exist_ok=True) - mock_makedirs.assert_any_call(os.path.join(writer.output_path, 'activitypub/collections/outbox'), exist_ok=True) - mock_makedirs.assert_any_call(os.path.join(writer.output_path, 'activitypub/collections/outbox_page', 'test_author'), exist_ok=True) - mock_makedirs.assert_any_call(os.path.join(writer.output_path, 'activitypub/collections/following'), exist_ok=True) - mock_makedirs.assert_any_call(os.path.join(writer.output_path, 'activitypub/collections/followers'), exist_ok=True) - - # Check if files were written - mock_open.assert_any_call(os.path.join(writer.output_path, '.well-known/host-meta'), 'w', encoding=ENCODING) - mock_open.assert_any_call(os.path.join(writer.output_path, '.well-known/nodeinfo'), 'w', encoding=ENCODING) - mock_open.assert_any_call(os.path.join(writer.output_path, 'activitypub/nodeinfo'), 'w', encoding=ENCODING) - mock_open.assert_any_call(os.path.join(writer.output_path, '.well-known/webfinger'), 'w', encoding=ENCODING) - - # Check if JSON data was dumped - self.assertTrue(mock_json_dump.called) - -if __name__ == '__main__': - unittest.main() \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index b744860..685d567 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,9 +40,3 @@ build-backend = "setuptools.build_meta" [tool.setuptools.dynamic] version = {attr = "pelican.plugins.activitypub.activitypub.__version__"} - -[project.optional-dependencies] -Test = [ - "pytest>=8.3.0", - "isort" -] \ No newline at end of file