From af0641301b9371af1956506a3a9d043fa5b535e4 Mon Sep 17 00:00:00 2001
From: Thilo Kogge
Date: Sat, 30 Jan 2021 16:37:03 +0100
Subject: [PATCH 01/18] moved the insert_date from podpost into archive
---
python/podcast/archive.py | 39 +-
python/podcast/data_migration.py | 28 +-
qml/components/ArchiveHandler.py | 5 +-
test/test_archive.py | 23 +-
test/test_migration_to_v1.py | 3 +-
test/test_podpost.py | 10 +-
test/test_queue.py | 10 +-
test/testdata/freakshow.rss | 5392 +-----------------------------
8 files changed, 86 insertions(+), 5424 deletions(-)
diff --git a/python/podcast/archive.py b/python/podcast/archive.py
index 0e2d649..ba5fa93 100644
--- a/python/podcast/archive.py
+++ b/python/podcast/archive.py
@@ -1,9 +1,10 @@
"""
Archive of listened poposts
"""
-
+import datetime
import sys
import time
+from typing import List, Any
sys.path.append("../")
@@ -13,17 +14,30 @@ from podcast.factory import Factory
archivename = "the_archive"
+class ArchiveEntry:
+ insert_date: float
+ podpost: str
+
+ @classmethod
+ def of_podpost(cls, postid: str):
+ archive_entry = ArchiveEntry()
+ archive_entry.podpost = postid
+ archive_entry.insert_date = time.time()
+ return archive_entry
+
+
class Archive:
"""
The podcast Archive. It has a list of podposts
"""
+ _archive_entries: list[ArchiveEntry]
def __init__(self):
"""
Initialization
"""
- self.podposts = [] # Id list of posposts
+ self._archive_entries = [] # Id list of posposts
def save(self):
"""
@@ -38,28 +52,27 @@ class Archive:
Insert an podost
"""
- if podpost not in self.podposts:
- self.podposts.insert(0, podpost)
- post = Factory().get_podpost(podpost)
- if post.insert_date == None:
- post.insert_date = time.time()
- post.save()
+ if podpost not in [e.podpost for e in self._archive_entries]:
+ self._archive_entries.insert(0, ArchiveEntry.of_podpost(podpost))
self.save()
- def get_podposts(self):
+ def get_podposts(self, sorted_by_date=False):
"""
get the list of podposts
"""
-
- for podpost in self.podposts:
- yield podpost
+ if not sorted_by_date:
+ for archive_entry in self._archive_entries:
+ yield archive_entry.podpost
+ else:
+ for archive_entry in sorted(self._archive_entries, key=lambda e: e.insert_date, reverse=True):
+ yield archive_entry.podpost
def remove_podpost(self, podpost):
"""
Remove a podpost from archive
"""
- self.podposts.remove(podpost)
+ self._archive_entries = [entry for entry in self._archive_entries if entry.podpost != podpost]
class ArchiveFactory(metaclass=Singleton):
diff --git a/python/podcast/data_migration.py b/python/podcast/data_migration.py
index a7bcdbc..7fd6ccc 100644
--- a/python/podcast/data_migration.py
+++ b/python/podcast/data_migration.py
@@ -1,5 +1,7 @@
import logging
import os
+from typing import List
+
import pyotherside
from podcast.factory import Factory
@@ -41,10 +43,10 @@ def run_migrations():
migrate_podpost_v0_v1(Factory().get_podpost(entry_id))
i += 1
pyotherside.send("migrationProgress", i)
+ migrate_archive_v0_v1()
set_versionnumber(1)
pyotherside.send("migrationDone")
-
def get_versionnumber() -> int:
versionfilepath = get_versionfile_path()
if os.path.isfile(versionfilepath):
@@ -64,6 +66,30 @@ def get_versionfile_path():
return os.path.join(Factory().data_home, "dataversion")
+def migrate_archive_v0_v1():
+ """
+ migrates the id list to ArchiveEntry
+ """
+ from podcast.archive import ArchiveFactory, ArchiveEntry, Archive
+ import datetime
+ archive: Archive = ArchiveFactory().get_archive()
+ if hasattr(archive, "podposts") and len(archive.podposts) > 0 and type(archive.podposts) is not ArchiveEntry:
+ old_archive: List[str] = archive.podposts
+ archive.__archive_entries = []
+ for postid in old_archive:
+ archive_entry = ArchiveEntry()
+ post = Factory().get_podpost(postid)
+ if not post:
+ continue
+ if hasattr(post, "insert_date") and post.insert_date:
+ archive_entry.insert_date = post.insert_date
+ else:
+ archive_entry.insert_date = datetime.datetime.now()
+ archive_entry.podpost = postid
+ archive.__archive_entries.append(post)
+ del archive.podposts
+
+
def migrate_podpost_v0_v1(self: Podpost):
if hasattr(self, "entry"):
if not hasattr(self, "isaudio"):
diff --git a/qml/components/ArchiveHandler.py b/qml/components/ArchiveHandler.py
index f488394..4a48d88 100644
--- a/qml/components/ArchiveHandler.py
+++ b/qml/components/ArchiveHandler.py
@@ -19,8 +19,8 @@ def get_archive_posts(podurl=None):
entries = []
archive = ArchiveFactory().get_archive()
- for post in archive.get_podposts():
- entry = Factory().get_podpost(post)
+ for archive_entry in archive.get_podposts(sorted_by_date=True):
+ entry = Factory().get_podpost(archive_entry.podpost)
if podurl:
if entry.podurl == podurl:
entries.append(entry.get_data())
@@ -30,7 +30,6 @@ def get_archive_posts(podurl=None):
else:
pyotherside.send("ArchiveHandler: We have a none object")
- entries.sort(key=lambda r: r["adate"], reverse=True)
pyotherside.send("createArchiveList", entries)
diff --git a/test/test_archive.py b/test/test_archive.py
index e3d187d..a951a22 100644
--- a/test/test_archive.py
+++ b/test/test_archive.py
@@ -4,7 +4,6 @@ test the archive
import sys
-import httpretty
from httpretty import HTTPretty, httprettified
from test.test_podcast import read_testdata, xml_headers
@@ -15,7 +14,6 @@ from podcast.archive import ArchiveFactory, Archive
from podcast.factory import Factory
from podcast.podcast import Podcast
from podcast.podpost import Podpost
-import podcast
def test_create_archive():
"""
@@ -43,18 +41,19 @@ def test_insert():
HTTPretty.register_uri(HTTPretty.GET, 'https://freakshow.fm/feed/opus/',
body=read_testdata('testdata/freakshow.rss'), adding_headers=xml_headers)
- a = ArchiveFactory().get_archive()
- p = Podcast('https://freakshow.fm/feed/opus/')
- e = p.get_entry(p.entry_ids_old_to_new[0])
- e.save()
- a.insert(e.id)
+ archive = ArchiveFactory().get_archive()
+ podcast = Podcast('https://freakshow.fm/feed/opus/')
+ entry1 = podcast.get_entry(podcast.entry_ids_old_to_new[0])
+ entry1.save()
+ archive.insert(entry1.id)
- e2 = p.get_entry(p.entry_ids_old_to_new[1])
- e2.save()
- a.insert(e2.id)
+ entry2 = podcast.get_entry(podcast.entry_ids_old_to_new[1])
+ entry2.save()
+ archive.insert(entry2.id)
- assert e.id in a.podposts
- assert e2.id in a.podposts
+ result_posts = list(archive.get_podposts(sorted_by_date=True))
+ assert entry1.id == result_posts[1] # older
+ assert entry2.id == result_posts[0] # newer
def test_get_archives():
"""
diff --git a/test/test_migration_to_v1.py b/test/test_migration_to_v1.py
index 4f9e587..c694f0c 100644
--- a/test/test_migration_to_v1.py
+++ b/test/test_migration_to_v1.py
@@ -14,6 +14,7 @@ from podcast.queue import QueueFactory
sys.path.append("../python")
+
def test_migration():
with tempfile.TemporaryDirectory() as tmpdir:
copy_tree(os.path.join(os.path.dirname(__file__), "testdata/migrationtests_v1/"), tmpdir)
@@ -23,7 +24,7 @@ def test_migration():
assert os.path.exists(os.path.join(tmpdir, "dataversion"))
podcasts = list(PodcastListFactory().get_podcast_list().get_podcasts())
assert len(podcasts) == 1
- podcast:Podcast = PodcastFactory().get_podcast(podcasts[0])
+ podcast: Podcast = PodcastFactory().get_podcast(podcasts[0])
assert podcast != None
assert len(podcast.entry_ids_old_to_new) == 22
assert len(list(podcast.get_entries())) == 22
diff --git a/test/test_podpost.py b/test/test_podpost.py
index 2d40f3c..b138568 100644
--- a/test/test_podpost.py
+++ b/test/test_podpost.py
@@ -3,17 +3,25 @@ Podpost tests
"""
import sys
+
+import httpretty
+from httpretty import HTTPretty
+
+from test.test_podcast import read_testdata, xml_headers
+
sys.path.append("../python")
from podcast.factory import Factory
from podcast.podcast import Podcast
from podcast.podpost import Podpost
+@httpretty.activate
def test_podpost_save():
"""
Test podpost saving
"""
-
+ HTTPretty.register_uri(HTTPretty.GET, 'https://freakshow.fm/feed/opus/',
+ body=read_testdata('testdata/freakshow.rss'), adding_headers=xml_headers)
f1 = Factory()
p = Podcast('https://freakshow.fm/feed/opus/')
diff --git a/test/test_queue.py b/test/test_queue.py
index 7634336..0927ba5 100644
--- a/test/test_queue.py
+++ b/test/test_queue.py
@@ -4,6 +4,11 @@ test the queue
import sys
+import httpretty
+from httpretty import HTTPretty
+
+from test.test_podcast import read_testdata, xml_headers
+
sys.path.append("../python")
from podcast.queue import QueueFactory
@@ -34,11 +39,12 @@ def test_queue_save():
q = QueueFactory().get_queue()
q.save()
-
+@httpretty.activate
def test_insert_top():
"""
"""
-
+ HTTPretty.register_uri(HTTPretty.GET, 'https://freakshow.fm/feed/opus/',
+ body=read_testdata('testdata/freakshow.rss'), adding_headers=xml_headers)
q = QueueFactory().get_queue()
l1 = len(q.podposts)
p = Podcast('https://freakshow.fm/feed/opus/')
diff --git a/test/testdata/freakshow.rss b/test/testdata/freakshow.rss
index c81a8fc..e2b9ac7 100644
--- a/test/testdata/freakshow.rss
+++ b/test/testdata/freakshow.rss
@@ -56,5397 +56,7 @@
no
no
- -
-
FS255 Bitcoin Recycling
- https://freakshow.fm/fs255-bitcoin-recycling
- Thu, 24 Dec 2020 18:02:10 +0000
- podlove-2020-12-24t16:44:11+00:00-2df73540be4775e
-
-
-
- 03:56:56
- Metaebene Personal Media - Tim Pritlove
- Podcast Clients — 2020 Technik-Rückblick — LiDAR — iPhone 12 — M1 — OpenZFS — NAS — Mac Apps — Bildschirme
- 255
- full
- Das Jahr geht (endlich) zu Ende und wir füllen die Bits eines Bytes bis auf letzte Stelle. Ausgabe Nummer Zweihundertfünfundfünzig versucht Euch zu Weihnachten noch mal das Herz zu fluten.
- Feedback zur Sendung?
-Schreibe uns einen Kommentar
-
-Diese Sendung soll nie aufhören?
-Unterstütze die Metaebene mit einer Spende
-
-
-
-Podcast Clients — 2020 Technik-Rückblick — LiDAR — iPhone 12 — M1 — OpenZFS — NAS — Mac Apps — Bildschirme
-
-Das Jahr geht (endlich) zu Ende und wir füllen die Bits eines Bytes bis auf letzte Stelle. Ausgabe Nummer Zweihundertfünfundfünzig versucht Euch zu Weihnachten noch mal das Herz zu fluten.
-
-Dauer: 3:56:56
-
-
-
-
-
-
-
-
-
-Shownotes:
-
-
-
-
-
-
-
-
-]]>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 2
-
- Tim Pritlove
- http://tim.pritlove.org/
-
-
- Denis Ahrens
-
-
- roddi
-
-
- -
-
FS254 Chat Roulette Business Edition
- https://freakshow.fm/fs254-chat-roulette-business-edition
- Thu, 10 Dec 2020 02:43:45 +0000
- podlove-2020-12-10t01:23:08+00:00-036a06860a74b9b
-
-
-
- 03:30:42
- Metaebene Personal Media - Tim Pritlove
- Talking Heads — Konten und Banken — M1 und Wintel — Internet Tips — pretix — venueless — pretalx — Virtuelle Events — Videotechnik — Mikrofone und Headsets — Licht — Ethernet
- 254
- full
- Heute dreht sich alles um Events. Wir begrüßen rami als Gast in der Sendung, der das Projekt pretix losgetreten hat, dass ein Ticketing-System für Veranstaltungen aller Art ist. Wir sprechen über Online-Events und in was von der Pandemie-Zeit übrig bleiben wird, wenn wir uns wieder in der Realität treffen können. Dazu gibt es noch eine Reihe von Tips für Technik zur Durchführung von Audio- und Videosessions.
- Feedback zur Sendung?
-Schreibe uns einen Kommentar
-
-Diese Sendung soll nie aufhören?
-Unterstütze die Metaebene mit einer Spende
-
-
-
-Talking Heads — Konten und Banken — M1 und Wintel — Internet Tips — pretix — venueless — pretalx — Virtuelle Events — Videotechnik — Mikrofone und Headsets — Licht — Ethernet
-
-Heute dreht sich alles um Events. Wir begrüßen rami als Gast in der Sendung, der das Projekt pretix losgetreten hat, dass ein Ticketing-System für Veranstaltungen aller Art ist. Wir sprechen über Online-Events und in was von der Pandemie-Zeit übrig bleiben wird, wenn wir uns wieder in der Realität treffen können. Dazu gibt es noch eine Reihe von Tips für Technik zur Durchführung von Audio- und Videosessions.
-
-Dauer: 3:30:42
-
-
-
-
-
-
-
-
-
-Shownotes:
-
-
-
-
-
-Liebe Dauerspender, ich habe eine Bitte | Metaebene Personal Media
- — Metaebene Personal Media
-
-
-Konto bei Kontist anlegen, 50 EUR spenden, 50 EUR bekommen
- — app.kontist.com
-
-
-Apple preps next Mac chips with aim to outclass highest-end PCs - BNN Bloomberg
- — BNN
-
-
-Just Have a Think
- — YouTube
-
-
-Ishkur's Guide to Electronic Music
- — music.ishkur.com
-
-
-Radiooooo
- — Radiooooo - The Musical Time Machine
-
-
-pretix
- — GitHub
-
-
-Host your events online with venueless
- — venueless
-
-
-pretix – Ticket-Shop für Konferenzen, Festivals, Messen, ...
- — pretix.eu
-
-
-pretalx.com – CfP and scheduling for conferences
- — pretalx.com
-
-
-Blog – pretix – Ticket-Shop für Konferenzen, Festivals, Messen, ...
- — pretix.eu
-
-
-BigBlueButton - Open Source Web Conferencing
- — bigbluebutton.org
-
-
-Second Life
- — de.wikipedia.org
-
-
-Video Meetings, Video Conferencing and Screen Sharing
- — whereby.com
-
-
-Blackmagic Design UltraStudio Recorder 3G
- — Musikhaus Thomann
- (*)
-
-
-Wonder – Online events that are fun
- — wonder.me
-
-
-Maps - rC3 howto
- — howto.rc3.world
-
-
-Blackmagic Design ATEM Television Studio Pro 4K
- — Musikhaus Thomann
- (*)
-
-
-doozzoo - live coaching platform for music education
- — doozzoo.com
-
-
-NDI + WiFi | Camera for OBS Studio
- — obs.camera
-
-
-v19 / Page / Product / Epoc | elgato.com
- — elgato.com
-
-
-Blackmagic Design ATEM Mini
- — Musikhaus Thomann
- (*)
-
-
-Tom Buck
- — YouTube
-
-
-Cam Link | elgato.com
- — elgato.com
-
-
-Shure MV 7 Black
- — Musikhaus Thomann
- (*)
-
-
-Starship | SN8 | High-Altitude Flight Test
- — youtube.com
-
-
-🎤 Shure SM 7 B
- — Musikhaus Thomann
- (*)
-
-
-Starship | SN8 | High-Altitude Flight Test
- — YouTube
-
-
-Manfrotto 244N Magic Arm
- — Musikhaus Thomann
- (*)
-
-
-Manfrotto 143N Magic Arm
- — Musikhaus Thomann
- (*)
-
-
-Manfrotto 035 Super Clamp
- — Musikhaus Thomann
- (*)
-
-
-Rode PSA-1
- — Musikhaus Thomann
- (*)
-
-
-Neewer Fortgeschrittene 660 LED Videoleuchte Dimmbares: Amazon.de: Kamera
- — amazon.de
-
-
-Yamaha AG03
- — Musikhaus Thomann
- (*)
-
-
-SSL 2
- — Musikhaus Thomann
- (*)
-
-
-Netgear GS105GE, Switch blau, Retail
- — alternate.de
-
-
-
-
-
-
-]]>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 2
-
- Tim Pritlove
- http://tim.pritlove.org/
-
-
- Letty
-
-
- hukl
-
-
- rami
-
-
- -
-
FS253 Zero Latency Computing
- https://freakshow.fm/fs253-zero-latency-computing
- Thu, 26 Nov 2020 23:00:32 +0000
- podlove-2020-11-26t22:43:23+00:00-130a4cec453a37f
-
-
-
- 03:41:53
- Metaebene Personal Media - Tim Pritlove
- Ultraschall — M1 Macs — Big Sur
- 253
- full
- Nach zwei Wochen und vor allem nachdem manche von uns bereits ein paar der neuen M1 Macs erhalten habe dreht sich hier ein weiteres Mal alles um die neuen Computer. Wir teilen erste Erfahrungen und Einschätzungen und sind überhaupt sehr aufgeregt. Außerdem ist Ralf zu Gast und berichtet von den Fortschritten beim Ultraschall-Projekt.
- Feedback zur Sendung?
-Schreibe uns einen Kommentar
-
-Diese Sendung soll nie aufhören?
-Unterstütze die Metaebene mit einer Spende
-
-
-
-Ultraschall — M1 Macs — Big Sur
-
-Nach zwei Wochen und vor allem nachdem manche von uns bereits ein paar der neuen M1 Macs erhalten habe dreht sich hier ein weiteres Mal alles um die neuen Computer. Wir teilen erste Erfahrungen und Einschätzungen und sind überhaupt sehr aufgeregt. Außerdem ist Ralf zu Gast und berichtet von den Fortschritten beim Ultraschall-Projekt.
-
-Dauer: 3:41:53
-
-
-
-
-
-
-
-
-
-Shownotes:
-
-
-
-
-
-Tonaderspeisung
- — de.wikipedia.org
-
-
-Logitech G432 Gaming-Headset mit 7.1 Surround Sound
- — logitechg.com
-
-
-PC38X - The Gaming Advantage?
- — YouTube
-
-
-Übersicht: alles rund um das Superlux HMC660 X Headset
- — Sendegate
-
-
-MV7 - Podcast-Mikrofon
- — shure.com
-
-
-PC38X - The Gaming Advantage?
- — youtu.be
-
-
-HedgeDoc - Collaborative markdown editor
- — HedgeDoc
-
-
-HedgeDoc - Collaborative markdown notes
- — HedgeDoc - Collaborative markdown notes
-
-
-Flowchart Maker & Online Diagram Software
- — Draw.io
-
-
-Roam Research – A note taking tool for networked thought.
- — Roam Research
-
-
-Affinity 1.8.6 for macOS is here!
- — Affinity
-
-
-Drafts, Where Text Starts
- — getdrafts.com
-
-
-HedgeDoc - Collaborative markdown notes
- — HedgeDoc - Collaborative markdown notes
-
-
-Podlovers
- — podlovers.org
-
-
-Notion – The all-in-one workspace for your notes, tasks, wikis, and databases.
- — Notion
-
-
-Podlove Community
- — community.podlove.org
-
-
-8GB vs 16GB M1 MacBook Pro - How much RAM do you NEED?!
- — YouTube
-
-
-Apple Mac Pro - Audio & Music Pro Buyer's Guide #1
- — YouTube
-
-
-Intel’s Disruption is Now Complete
- — Medium
-
-
-Apple Silicon M1: Black. Magic. Fuckery.
- — singhkays.com
-
-
-Apple Announces The Apple Silicon M1: Ditching x86 - What to Expect, Based on A14
- — AnandTech
-
-
-Craig Federighi says touchscreen Macs not the goal of Big Sur’s design
- — Six Colors
-
-
-Acorn Archimedes
- — de.m.wikipedia.org
-
-
-Upgrade #326: The M1 Macs: Interview and Review - Relay FM
- — Relay FM
-
-
-Epic: Support Apple Silicon · Issue #43313 · dotnet/runtime
- — GitHub
-
-
-Run Six Displays on M1 Macs Apple Silicon (Mac Mini, Macbook Air, Macbook Pro) #WorkFromHome #ARM
- — YouTube
-
-
-macOS 11 Big Sur compatibility on Apple Silicon · Issue #7857 · Homebrew/brew
- — GitHub
-
-
-Is Apple Silicon ready ?
- — Is Apple silicon ready ?
-
-
-High-Performance Workflow Solutions
- — OWC Digital
-
-
-Airfoil for Mac: Installing ACE on M chip-based Macs
- — rogueamoeba.com
-
-
-Safely open apps on your Mac
- — Apple Support
-
-
-macOS Big Sur launch appears to cause temporary slowdown in even non-Big Sur Macs
- — Ars Technica
-
-
-ktemkin/homebrew-tirepatch
- — GitHub
-
-
-Apple Silicon M1 Chips and Docker - Docker Blog
- — Docker Blog
-
-
-What happened during the troubled Big Sur launch, and why Apple can't let it happen again | AppleInsider
- — AppleInsider
-
-
-Apple M1 Tidbits: Running iOS Apps With .IPAs, Running x86 Homebrew Apps, Accessing macOS Recovery and More
- — MacRumors
-
-
-Developer ID certificate revocation
- — lapcatsoftware.com
-
-
-Apple Developer ID OCSP
- — lapcatsoftware.com
-
-
-Does Apple really log every app you run? A technical look – Jacopo Jannone - blog
- — blog.jacopo.io
-
-
-MacOS Big Sur Launch Overwhelmed Apple’s CDN, Which in Turn Triggered a Bug in ‘trustd’ That Ground App Launching to a Halt
- — Daring Fireball
-
-
-Big no on Big Sur: Mullvad disallows Apple apps to bypass firewall - Blog | Mullvad VPN
- — Mullvad VPN
-
-
-Help Center - Little Snitch
- — Objective Development
-
-
-US-Uni entwickelt Super-Cluster aus G5-Power-Macs
- — heise.de
-
-
-A hole in the wall
- — Objective Development's Blog
-
-
-PC guy is BACK! Watch him troll Apple's MacBook event ('I'm a Mac' - 'I'm a PC')
- — YouTube
-
-
-
-
-
-
-]]>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 2
-
- Tim Pritlove
- http://tim.pritlove.org/
-
-
- Dominik Wagner
-
-
- Denis Ahrens
-
-
- Ralf Stockmann
-
-
- -
-
FS252 Keine grobe Feinheit
- https://freakshow.fm/fs252-keine-grobe-feinheit
- Thu, 12 Nov 2020 20:36:35 +0000
- podlove-2020-11-12t13:43:01+00:00-6312fbdf2ec0387
-
-
-
- 03:50:53
- Metaebene Personal Media - Tim Pritlove
- Kontowechsel — Pausenende — Elektrourlaub — Tesla Battery Day — iPhone 12 — Apple Watch — iOS 14 und AirPods Pro — Augmented Reality — Big Sur — ARM-Macs — 5G — Audio auf dem Mac — Audiointerfaces — Küchenkram
- 252
- full
- We are back. Nach einer längeren, im Kern ungeplanten aber trotzdem notwenidgen Verschnaufpause ist die Freak Show wieder am Start, denn wir mussten dringend mal wieder mehr über Macs reden. Wir gehen die neue Produkten von Apple der letzten Woche durch und natürlich legen wir einen Schwerpunkt auf die neuen ARM-Macs, die nun endlich vorgestellt worden. Dazu ein wenig Corona-Küchenkram rund um Waffeleisen und scharfe Messer.
- Feedback zur Sendung?
-Schreibe uns einen Kommentar
-
-Diese Sendung soll nie aufhören?
-Unterstütze die Metaebene mit einer Spende
-
-
-
-Kontowechsel — Pausenende — Elektrourlaub — Tesla Battery Day — iPhone 12 — Apple Watch — iOS 14 und AirPods Pro — Augmented Reality — Big Sur — ARM-Macs — 5G — Audio auf dem Mac — Audiointerfaces — Küchenkram
-
-We are back. Nach einer längeren, im Kern ungeplanten aber trotzdem notwenidgen Verschnaufpause ist die Freak Show wieder am Start, denn wir mussten dringend mal wieder mehr über Macs reden. Wir gehen die neue Produkten von Apple der letzten Woche durch und natürlich legen wir einen Schwerpunkt auf die neuen ARM-Macs, die nun endlich vorgestellt worden. Dazu ein wenig Corona-Küchenkram rund um Waffeleisen und scharfe Messer.
-
-Dauer: 3:50:53
-
-
-
-
-
-
-
-
-
-Shownotes:
-
-
-
-
-
-Liebe Dauerspender, ich habe eine Bitte | Metaebene Personal Media
- — Metaebene Personal Media
-
-
-Spenden für die Metaebene | Metaebene Personal Media
- — Metaebene Personal Media
-
-
-etzmax - Commercial On-Demand-Espresso-Grinder: Grinders (EN)
- — etzinger-ag.com
-
-
-Beyerdynamic DT-297-PV/80 MKII
- — Musikhaus Thomann
- (*)
-
-
-Apple Silicon: MacBook Air schneller als 16" MacBook Pro? | Mac Life
- — Mac Life
-
-
-20 Macs for 2020 - Relay FM
- — Relay FM
-
-
-Behringer | Product | FLOW 8
- — behringer.com
-
-
-Thomann feat. Tim Pritlove
- — thomann.de
- (*)
-
-
-20 Macs for 2020 – Six Colors
- — Six Colors
-
-
-SubEthaEdit
- — Mac App Store
-
-
-Raspberry Pi 400, DE Tastatur Layout
- — Pi-Shop.ch
-
-
-Amazon.de: Baratza | Sette 270 | Elektrische Kaffee Kegelmühlen Professional | Grau / Schwarz
- — amazon.de
-
-
-SSL 2
- — Musikhaus Thomann
- (*)
-
-
-Beyerdynamic DT-797 PV
- — Musikhaus Thomann
- (*)
-
-
-Knives Out – Mord ist Familiensache – Wikipedia
- — de.wikipedia.org
-
-
-Wüsthof Kochmesser, Classic (4582-7/18), 18 cm Klingenlänge, geschmiedet, rostfreier Edelstahl, breites und sehr scharfes Küchenmesser: Amazon.de: Küche & Haushalt
- — amazon.de
-
-
-Universal Audio Apollo Twin USB Duo
- — Musikhaus Thomann
- (*)
-
-
-Roland Rubix24
- — Musikhaus Thomann
- (*)
-
-
-Yamaha AG03
- — Musikhaus Thomann
- (*)
-
-
-Penninger Blutwurz
- — penninger.de
-
-
-SIMPLE-Sharp, 53,61 €
- — schmiedeglut.de
-
-
-Lendromat
- — lendrom.at
-
-
-Mediashop Bavarian Edge Messerschärfer
- — amazon.de
-
-
-Amazon.de: Graef Diamant-Messerschärfer CC 120 DE, weiß-schwarz
- — amazon.de
-
-
-HORL | Rollschleifer | Die zweite Generation Schärfe
- — horl.com
-
-
-M. Power Tools DC Schärfblock, extrafein/grob | Schärfsteine / Schleifsteine | Dictum
- — Dictum
-
-
-Ken Onion Edition Knife & Tool Sharpener - Work Sharp Sharpeners
- — Work Sharp Sharpeners
-
-
-ZWILLING Schubladeneinsatz, bis zu 8 Messer, Buche | Offizieller ZWILLING Shop
- — zwilling.com
-
-
-SHAN ZU Schleifstein Abziehstein Wetzstein für Professionell 2-in-1 Doppelseitiger Messerschärfer
- — amazon.de
-
-
-8" Dia-Sharp DMT Diamant Schleifstein Set
- — schmiedeglut.de
-
-
-Für die Werkstatt - SCHMIEDEGLUT Messer nach Wunsch: Damastmesser,
- — schmiedeglut.de
-
-
-Mactracker App Info and Alternatives @ Mactracker.com
- — mactracker.app
-
-
-Messer Schärfen lernen in 10 Minuten im Schärfkurs Online
- — YouTube
-
-
-SCHMIEDEGLUT: Messer, Damastmesser, Jagdmesser, Damast Kochmesser
- — schmiedeglut.de
-
-
-cloer 1898 Waffeleisen Herzwaffel 16, 5 cm Ø, doppelte Antihaftbeschichtung, für gewerblichen Betrieb geeignet
- — amazon.de
-
-
-Amazon.de: Waffeleisen Wanda 1600 W, Doppelwaffeleisen für Belgische Waffeln, Praktische Überlaufrille, Display zur Anzeige der Backfarbe
- — amazon.de
-
-
-kiwami japan
- — YouTube
-
-
-Schmiedeglut - Handmade Knives Germany
- — YouTube
-
-
-Amazon.de: Krups FDD95D Professionelles Waffeleisen
- — amazon.de
-
-
-ExistentialAudio/BlackHole
- — GitHub
-
-
-Ultimate Hacking Keyboard – The keyboard. For professionals.
- — Ultimate Hacking Keyboard
-
-
-Everest Max im Test: Mehr kann man von einer Tastatur nicht wollen - Golem.de
- — Golem.de
-
-
-1Password | Yubico
- — Yubico
-
-
-SoundSource - A Superior Sound Control
- — rogueamoeba.com
-
-
-Loopback - Cable-free audio routing for Mac
- — rogueamoeba.com
-
-
-Apple schnappt sich Intels Modemgeschäft
- — Mac & i
-
-
-MacBook Air - Technical Specifications
- — Apple
-
-
-Apple stellt den M1 vor
- — Apple Newsroom
-
-
-Apple M1 Power Chart
- — applemust.com
-
-
-Apple Announces The Apple Silicon M1: Ditching x86 - What to Expect, Based on A14
- — AnandTech
-
-
-ICARER MacBook Pro 13 Hülle Lederhülle, Ultra Slim: Amazon.de: Computer & Zubehör
- — amazon.de
-
-
-Spinal Tap - "These go to eleven...."
- — YouTube
-
-
-Augmented Reality - The Future of Education ( Ara Pacis ) - HD version
- — YouTube
-
-
-Sheets - Windows and Views - macOS - Human Interface Guidelines - Apple Developer
- — developer.apple.com
-
-
-200 Puls - Mediamarkt - Sachse - Videorekorder
- — YouTube
-
-
-Exclusive: Intel's new smart glasses hands-on
- — YouTube
-
-
-Microsoft HoloLens | Mixed Reality-Technologie für Unternehmen
- — microsoft.com
-
-
-MacBook Pro 13" (2016-2019) Hard Case Hülle Dual Schutzabdeckung - Schwarz (Transparent/Matt)
- — apfelkiste.ch
-
-
-iHealth AIR PO3M Vernetztes Pulsoximeter: Amazon.de: Drogerie & Körperpflege
- — amazon.de
-
-
-Fission - Fast & lossless audio editing for Mac
- — rogueamoeba.com
-
-
-ZWILLING Messeraufbewahrung, Buche | Offizieller ZWILLING Shop
- — zwilling.com
-
-
-Surprise! Fujitsu Releases 64-Bit ScanSnap Manager for Older Scanners - TidBITS
- — TidBITS
-
-
-Models for ScanSnap Manager V7 Download
- — scansnap.fujitsu.com
-
-
-
-
-
-
-]]>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 2
-
- Tim Pritlove
- http://tim.pritlove.org/
-
-
- hukl
-
-
- Denis Ahrens
-
-
- roddi
-
-
- Dominik Wagner
-
-
- -
-
FS251 Bürgermeisterladesäulen
- https://freakshow.fm/fs251-buergermeisterladesaeulen
- Sat, 18 Jul 2020 09:49:43 +0000
- podlove-2020-07-18t09:29:01+00:00-e6a090d7c680aed
-
-
-
- 03:19:11
- Metaebene Personal Media - Tim Pritlove
- Eine Spezialausgabe der Freak Show mit dem Schwerpunkt Elektromobilität
- 251
- full
- Wir haben schon oft darüber gesprochen, aber so richtig Ahnung haben wir ja eh nicht. Deswegen haben wir (Roddi, Denis, Tim) uns den Philipp vom cleaneletric Podcast eingeladen um mal ganz ausführlich über den Stand der Dinge in Sachen Elektromobilität in Deutschland und dem Rest der Welt zu sprechen. Dabei versuchen wir zu ergründen, woran es noch hapert und wo vielleicht der Umstieg für viele schon näher liegt, als diese selbst noch glauben.
- Feedback zur Sendung?
-Schreibe uns einen Kommentar
-
-Diese Sendung soll nie aufhören?
-Unterstütze die Metaebene mit einer Spende
-
-
-
-Eine Spezialausgabe der Freak Show mit dem Schwerpunkt Elektromobilität
-
-Wir haben schon oft darüber gesprochen, aber so richtig Ahnung haben wir ja eh nicht. Deswegen haben wir (Roddi, Denis, Tim) uns den Philipp vom cleaneletric Podcast eingeladen um mal ganz ausführlich über den Stand der Dinge in Sachen Elektromobilität in Deutschland und dem Rest der Welt zu sprechen. Dabei versuchen wir zu ergründen, woran es noch hapert und wo vielleicht der Umstieg für viele schon näher liegt, als diese selbst noch glauben.
-
-Dauer: 3:19:11
-
-
-
-
-
-
-
-
-
-Shownotes:
-
-
-
-
-
-
-
-
-]]>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 2
-
- Tim Pritlove
- http://tim.pritlove.org/
-
-
- Denis Ahrens
-
-
- roddi
-
-
- Philipp Hellwig
-
-
- -
-
FS250 Die Ente bleibt draußen
- https://freakshow.fm/fs250-die-ente-bleibt-draussen
- Thu, 02 Jul 2020 22:46:38 +0000
- podlove-2020-07-02t21:40:53+00:00-6b9d9aaa486e6bf
-
-
-
- 03:37:40
- Metaebene Personal Media - Tim Pritlove
- Die 250. Sendung der Freak Show über die WWDC 2020 und andere Dinge
- 250
- full
- Nun sind schon über 12 Jahre vergangen seitdem die Freak Show (damals noch unter anderem Namen) ans Netz gegangen ist. Wir bedanken uns für die jahrelange Treue unserer Hörerinnen und Hörer, die mit ihrem Feedback immer dazu beigetragen haben, dass uns die Lust am Projekt nie vergangen ist.
-
-Heute sind wir dann auch standesgemäß vollzählig angetreten und dazu haben wir uns auch noch den Dominik dazugehört, um die Akustik für Euch komplett unübersichtlich zu gestalten.
- Feedback zur Sendung?
-Schreibe uns einen Kommentar
-
-Diese Sendung soll nie aufhören?
-Unterstütze die Metaebene mit einer Spende
-
-
-
-Die 250. Sendung der Freak Show über die WWDC 2020 und andere Dinge
-
-Nun sind schon über 12 Jahre vergangen seitdem die Freak Show (damals noch unter anderem Namen) ans Netz gegangen ist. Wir bedanken uns für die jahrelange Treue unserer Hörerinnen und Hörer, die mit ihrem Feedback immer dazu beigetragen haben, dass uns die Lust am Projekt nie vergangen ist.
-
-Heute sind wir dann auch standesgemäß vollzählig angetreten und dazu haben wir uns auch noch den Dominik dazugehört, um die Akustik für Euch komplett unübersichtlich zu gestalten.
-
-Dauer: 3:37:40
-
-
-
-
-
-
-
-
-
-Shownotes:
-
-
-
-
-
-
-
-
-]]>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 2
-
- Tim Pritlove
- http://tim.pritlove.org/
-
-
- Dominik Wagner
-
-
- hukl
-
-
- Clemens Schrimpe
-
-
- Letty
-
-
- Tala
-
-
- roddi
-
-
- Denis Ahrens
-
-
- -
-
FS249 Hemmungsloser Hinterhoftoilettensex
- https://freakshow.fm/fs249-hemmungsloser-hinterhoftoilettensex
- Mon, 27 Apr 2020 10:05:37 +0000
- podlove-2020-04-27t09:29:08+00:00-0afb684ad7267f3
-
-
-
- 04:05:36
- Metaebene Personal Media - Tim Pritlove
- Die Corona-Situation — Masken und Zauberwürfel — Gesundheitstechnologie — Differential Privacy — macOS auf ARM — Programmiersprachen
- 249
- full
- Heute begrüßen wir in unserer Runde den Menschen, der jetzt schon seit Jahren auf die eine oder andere Art und Weise zu hören war, nur noch nicht selbst: Rainer, der seinerzeit die Produktion der Previouslys von David übernommen hatte nimmt Platz in unserer Runde. Inhaltlich dreht sich natürlich viel um Das Unvermeidliche Thema ™, aber wir versuchen noch das eine oder andere sinnvolle zur Debatte hinzuzufügen. Und wir mussten mal wieder über Macs reden. Viel Spaß dabei.
- Feedback zur Sendung?
-Schreibe uns einen Kommentar
-
-Diese Sendung soll nie aufhören?
-Unterstütze die Metaebene mit einer Spende
-
-
-
-Die Corona-Situation — Masken und Zauberwürfel — Gesundheitstechnologie — Differential Privacy — macOS auf ARM — Programmiersprachen
-
-Heute begrüßen wir in unserer Runde den Menschen, der jetzt schon seit Jahren auf die eine oder andere Art und Weise zu hören war, nur noch nicht selbst: Rainer, der seinerzeit die Produktion der Previouslys von David übernommen hatte nimmt Platz in unserer Runde. Inhaltlich dreht sich natürlich viel um Das Unvermeidliche Thema ™, aber wir versuchen noch das eine oder andere sinnvolle zur Debatte hinzuzufügen. Und wir mussten mal wieder über Macs reden. Viel Spaß dabei.
-
-Dauer: 4:05:36
-
-
-
-
-
-
-
-
-
-Shownotes:
-
-
-
-
-
-
-
-
-]]>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 2
-
- Tim Pritlove
- http://tim.pritlove.org/
-
-
- Letty
-
-
- Denis Ahrens
-
-
- Clemens Schrimpe
-
-
- Rainer
-
-
- -
-
FS248 Public Static Final
- https://freakshow.fm/fs248-public-static-final
- Tue, 31 Mar 2020 07:57:09 +0000
- podlove-2020-03-30t23:22:33+00:00-0d806fba61c9b50
-
-
-
- 03:23:01
- Metaebene Personal Media - Tim Pritlove
- Die erste Freak Show, die komplett remote stattfindet
- 248
- full
- Nun ist es es also soweit: der Coronavirus zwingt auch die Freak Show in den Zwangsabstand und so wird das erste mal nicht live und lebendig in der Metaebene aufgenommen, sondern wir finden uns alle digital zusammen. Klappt trotzdem irgendwie und wir bieten seit langem mal wieder ein volles Team. Die Themen liegen natürlich auf der Hand, aber wir reden auch mal wieder über Macs. Viel Spaß.
- Feedback zur Sendung?
-Schreibe uns einen Kommentar
-
-Diese Sendung soll nie aufhören?
-Unterstütze die Metaebene mit einer Spende
-
-
-
-Die erste Freak Show, die komplett remote stattfindet
-
-Nun ist es es also soweit: der Coronavirus zwingt auch die Freak Show in den Zwangsabstand und so wird das erste mal nicht live und lebendig in der Metaebene aufgenommen, sondern wir finden uns alle digital zusammen. Klappt trotzdem irgendwie und wir bieten seit langem mal wieder ein volles Team. Die Themen liegen natürlich auf der Hand, aber wir reden auch mal wieder über Macs. Viel Spaß.
-
-Dauer: 3:23:01
-
-
-
-
-
-
-
-
-
-Shownotes:
-
-
-
-
-
-
-
-
-]]>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 2
-
- Tim Pritlove
- http://tim.pritlove.org/
-
-
- Letty
-
-
- hukl
-
-
- Tala
-
-
- roddi
-
-
- Clemens Schrimpe
-
-
- -
-
FS247 Pulp-Fiction-Koffermoment
- https://freakshow.fm/fs247-pulp-fiction-koffermoment
- Thu, 27 Feb 2020 21:32:03 +0000
- podlove-2020-02-27t19:11:42+00:00-44e5ad9cc461a0e
-
-
-
- 04:02:47
- Metaebene Personal Media - Tim Pritlove
- Umziehen — Podlove Web Player — Podlove Publisher — WordPress — Podlove Radiator — Küchengeräte
- 247
- full
- Heute finden wir uns mit einer ganzen Reihe an Wiedergängern aus den letzten Jahren zusammen. Wir begrüßen Dennis Morhardt, Alexander Heimbuch und Eric Teubert in unserer Runde und reden viel über Podlove und Podcasting, aber auch darüber, wie man sich richtig die Hände wäscht und ohne welchen Küchengeräte ein Leben im 21. Jahrhundert unvorstellbar ist.
- Feedback zur Sendung?
-Schreibe uns einen Kommentar
-
-Diese Sendung soll nie aufhören?
-Unterstütze die Metaebene mit einer Spende
-
-
-
-Umziehen — Podlove Web Player — Podlove Publisher — WordPress — Podlove Radiator — Küchengeräte
-
-Heute finden wir uns mit einer ganzen Reihe an Wiedergängern aus den letzten Jahren zusammen. Wir begrüßen Dennis Morhardt, Alexander Heimbuch und Eric Teubert in unserer Runde und reden viel über Podlove und Podcasting, aber auch darüber, wie man sich richtig die Hände wäscht und ohne welchen Küchengeräte ein Leben im 21. Jahrhundert unvorstellbar ist.
-
-Dauer: 4:02:47
-
-
-
-
-
-
-
-
-
-Shownotes:
-
-
-
-
-
-FSP247 - Aktionärstreffen
- — SoundCloud
-
-
-momox - Einfach gebrauchte Sachen online verkaufen
- — momox.de
-
-
-rebuy
-
-
-Ali Noorani on Twitter: Händewaschen
- — Twitter
-
-
-Home - Shelly Cloud
- — Shelly Cloud
-
-
-MQTT
- — de.wikipedia.org
-
-
-Node-RED
- — nodered.org
-
-
-Online-Zahlungsabwicklung für Internet-Unternehmen – Stripe
- — stripe.com
-
-
-Web Payments Working Group
- — w3.org
-
-
-Berliner Toilette
- — App Store
-
-
-Direkte Spenden im Web für die Metaebene via bunq.me und Apple Pay
- — bunq.me
-
-
-Spenden für die Metaebene | Metaebene Personal Media
- — Metaebene Personal Media
-
-
-GoCardless
- — gocardless.com
-
-
-Best way for artists and creators to get sustainable income and connect with fans | Patreon
- — Patreon
-
-
-Steady – People-Powered Media
- — Steady
-
-
-Patreon will now give creators cash advances on their subscription money
- — The Verge
-
-
-The world’s fastest framework for building websites
- — gohugo.io
-
-
-Enjoy Slurm!
- — betaebene.be
-
-
-Amazon Smile
- — smile.amazon.de
-
-
-fehlkauf.biz - Wir machen Business
- — fehlkauf.biz
-
-
-Unfurl · Url Metadata Extractor
- — unfurl.eric.co.de
-
-
-Microbrowsers are Everywhere
- — 24ways.org
-
-
-podcasting
- — wikidata.org
-
-
-Stream Deck | elgato.com
- — elgato.com
-
-
-Optimus (Tastatur)
- — de.wikipedia.org
-
-
-ANYCAST - Fachpodcast für Heimat, Recht, Bahn und Moral
- — ANYCAST
-
-
-GraphQL
- — de.wikipedia.org
-
-
-Startseite | BR Podcast
- — BR Podcast
-
-
-MinIO | High Performance, Kubernetes-Friendly Object Storage
- — MinIO
-
-
-BOB - BOB 2020
- — bobkonf.de
-
-
-Elixir (Programmiersprache)
- — de.wikipedia.org
-
-
-Amazon.de: SAGE STM800 the Tea Maker Teeautomat mit Absenkautomatik, 1.5 Liter, Edelstahl
- — amazon.de
-
-
-Amazon.de: Karcher 112921 Kaffeemaschine Morning Star mit Radio
- — amazon.de
-
-
-Amazon.de: Caso 1811 TeeGourmet Pro-Design Auto-Lift-Funktion Teekocher, 18/8 Edelstahl, 1.7 liters
- — amazon.de
-
-
-Old-fashioned rice cookers are extremely clever
- — YouTube
-
-
-Amazon.de: Reishunger Reiskocher (1, 2l / 500W / 220V)
- — amazon.de
-
-
-The Antique Toaster that's Better than Yours
- — YouTube
-
-
-Amazon.de: Bosch muc88b68fr Multi Apfelkocher 1200 W Metallic
- — amazon.de
-
-
-Arendo - Edelstahl Dampfgarer Reiskocher - inkl. Dampfgarfunktion
- — amazon.de
-
-
-Vakuumgaren
- — de.wikipedia.org
-
-
-Krups FDD95D Waffelautomat Professional: Amazon.de: Küche & Haushalt
- — amazon.de
-
-
-Amazon.de: Cloer 189 Waffelautomat für kuchenartige Waffeln
- — amazon.de
-
-
-Zwilling 307481810 Twin Pollux Santokumesser
- — amazon.de
-
-
-BearMoo Wetzstein, 2-IN-1 Abziehstein Schleifstein für Messer, Körnung 3000/8000 mit rutschfestem Silikonhalter
- — amazon.de
-
-
-Holzapfel Buckelsmesser Olivenholz
- — Holzapfel Berlin
-
-
-Amazon.de: Espressomaschine Rancilio Silvia
- — amazon.de
-
-
-Profitec Pro300 Espressomaschine
- — Coffee Circle
-
-
-Regler – Wikipedia
- — de.wikipedia.org
-
-
-Arc
- — felicitacoffee.com
-
-
-Puqpress M1 weiß
- — STOLL Espresso
-
-
-DE1+
- — decentespresso.com
-
-
-Bezzera BZ10 S PM Espressomaschine
- — Coffee Circle
-
-
-Eureka Mignon MCI Espressomühle
- — Coffee Circle
-
-
-jbkaffe Onlineshop f. Kaffee + Espresso
- — https://www.jbkaffee.de/
-
-
-19grams Kaffeerösterei
- — 19grams Kaffeerösterei
-
-
-MAN VERSUS MACHINE - INDEPENDENT SPECIALTY COFFEE ROASTERS
- — MAN VERSUS MACHINE COFFEE ROASTERS
-
-
-Ascaso Factory | Espresso coffee machines manufactured in Barcelona |
- — ascaso.com
-
-
-Espresso Bohnen & Kaffee bestellen » Espresso International
- — Deutsch (.de)
-
-
-
-
-
-
-]]>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 2
-
- Tim Pritlove
- http://tim.pritlove.org/
-
-
- roddi
-
-
- Eric Teubert
-
-
- Dennis Morhardt
-
-
- Alexander Heimbuch
-
-
- -
-
FS246 Raumzeitfenster
- https://freakshow.fm/fs246-raumzeitfenster
- Thu, 30 Jan 2020 13:10:47 +0000
- podlove-2020-01-30t10:52:26+00:00-666de9cd437c1b9
-
-
-
- 04:02:58
- Metaebene Personal Media - Tim Pritlove
- Monty Python und Humor — Coronavirus — Living the Future — Raumzeit — Space — Tesla und die Automobilindustrie — Sozialraum Auto — Promotion — Billie Eilish
- 246
- full
- Eine kleine Runde mit Gast. Tala ist und Gregor ist mal wieder dazugestossen. Wenig überraschend gehen wir diverse Dinge stark auf der Metaebene an (im doppelten Wortsinne). Wir diskutieren Humor, Viren, Texteditoren, das Leben in der Zukunft und warum das mit der Abkehr vom Auto noch eine Weile dauern wird.
- Feedback zur Sendung?
-Schreibe uns einen Kommentar
-
-Diese Sendung soll nie aufhören?
-Unterstütze die Metaebene mit einer Spende
-
-
-
-Monty Python und Humor — Coronavirus — Living the Future — Raumzeit — Space — Tesla und die Automobilindustrie — Sozialraum Auto — Promotion — Billie Eilish
-
-Eine kleine Runde mit Gast. Tala ist und Gregor ist mal wieder dazugestossen. Wenig überraschend gehen wir diverse Dinge stark auf der Metaebene an (im doppelten Wortsinne). Wir diskutieren Humor, Viren, Texteditoren, das Leben in der Zukunft und warum das mit der Abkehr vom Auto noch eine Weile dauern wird.
-
-Dauer: 4:02:58
-
-
-
-
-
-
-
-
-
-Shownotes:
-
-
-
-
-
-
-
-
-]]>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 2
-
- Tim Pritlove
- http://tim.pritlove.org/
-
-
- Tala
-
-
- Gregor Sedlag
-
-
- -
+
-
FS245 Lazy Letty
https://freakshow.fm/fs245-lazy-letty
Fri, 10 Jan 2020 19:33:54 +0000
--
GitLab
From 885688a8b21d6828e2c0bc93ddd5a64a3818cc02 Mon Sep 17 00:00:00 2001
From: Thilo Kogge
Date: Sat, 30 Jan 2021 16:39:20 +0100
Subject: [PATCH 02/18] fixed linter errors
---
python/podcast/archive.py | 2 --
1 file changed, 2 deletions(-)
diff --git a/python/podcast/archive.py b/python/podcast/archive.py
index ba5fa93..a7346e7 100644
--- a/python/podcast/archive.py
+++ b/python/podcast/archive.py
@@ -1,10 +1,8 @@
"""
Archive of listened poposts
"""
-import datetime
import sys
import time
-from typing import List, Any
sys.path.append("../")
--
GitLab
From 2d0567c372f81becee5f68967fc9a9d51bf03fd9 Mon Sep 17 00:00:00 2001
From: Thilo Kogge
Date: Sat, 30 Jan 2021 16:42:14 +0100
Subject: [PATCH 03/18] fixed 3.8 interoperatibility
---
python/podcast/archive.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/python/podcast/archive.py b/python/podcast/archive.py
index a7346e7..f160ecd 100644
--- a/python/podcast/archive.py
+++ b/python/podcast/archive.py
@@ -3,6 +3,7 @@ Archive of listened poposts
"""
import sys
import time
+from typing import List
sys.path.append("../")
@@ -28,7 +29,7 @@ class Archive:
"""
The podcast Archive. It has a list of podposts
"""
- _archive_entries: list[ArchiveEntry]
+ _archive_entries: List[ArchiveEntry]
def __init__(self):
"""
--
GitLab
From cae5472dec77c69e736943d141e66e274e328708 Mon Sep 17 00:00:00 2001
From: Thilo Kogge
Date: Mon, 1 Feb 2021 21:10:23 +0100
Subject: [PATCH 04/18] fixed tests, small refactorings, sorting by
Podpost::insert_date again
---
pytest.ini | 5 +++++
python/podcast/archive.py | 12 ++++++++++--
python/podcast/data_migration.py | 22 ++++++++++++----------
python/podcast/podpost.py | 22 ++++++++--------------
qml/components/ArchiveHandler.py | 20 +++++---------------
test/__init__.py | 5 +++++
test/test_archive.py | 11 +++++++----
test/test_migration_to_v1.py | 3 +++
test/test_queue.py | 11 +++++++----
9 files changed, 62 insertions(+), 49 deletions(-)
create mode 100644 pytest.ini
diff --git a/pytest.ini b/pytest.ini
new file mode 100644
index 0000000..a861829
--- /dev/null
+++ b/pytest.ini
@@ -0,0 +1,5 @@
+[pytest]
+log_cli = 1
+log_cli_level = Info
+testpaths =
+ test
\ No newline at end of file
diff --git a/python/podcast/archive.py b/python/podcast/archive.py
index f160ecd..1f7f7dc 100644
--- a/python/podcast/archive.py
+++ b/python/podcast/archive.py
@@ -3,18 +3,19 @@ Archive of listened poposts
"""
import sys
import time
-from typing import List
+from typing import List, Iterator
sys.path.append("../")
from podcast.singleton import Singleton
from podcast.factory import Factory
+from podcast.podpost import Podpost
archivename = "the_archive"
class ArchiveEntry:
- insert_date: float
+ insert_date: float # unused yet
podpost: str
@classmethod
@@ -66,6 +67,13 @@ class Archive:
for archive_entry in sorted(self._archive_entries, key=lambda e: e.insert_date, reverse=True):
yield archive_entry.podpost
+ def get_podpost_objects(self, url_filter=None) -> Iterator[Podpost]:
+ for id in self.get_podposts():
+ entry: Podpost = Factory().get_podpost(id)
+ if entry:
+ if not url_filter or (url_filter and entry.podurl == url_filter):
+ yield entry
+
def remove_podpost(self, podpost):
"""
Remove a podpost from archive
diff --git a/python/podcast/data_migration.py b/python/podcast/data_migration.py
index 7fd6ccc..5cbe69d 100644
--- a/python/podcast/data_migration.py
+++ b/python/podcast/data_migration.py
@@ -1,3 +1,4 @@
+import datetime
import logging
import os
from typing import List
@@ -75,7 +76,7 @@ def migrate_archive_v0_v1():
archive: Archive = ArchiveFactory().get_archive()
if hasattr(archive, "podposts") and len(archive.podposts) > 0 and type(archive.podposts) is not ArchiveEntry:
old_archive: List[str] = archive.podposts
- archive.__archive_entries = []
+ archive._archive_entries = []
for postid in old_archive:
archive_entry = ArchiveEntry()
post = Factory().get_podpost(postid)
@@ -86,19 +87,20 @@ def migrate_archive_v0_v1():
else:
archive_entry.insert_date = datetime.datetime.now()
archive_entry.podpost = postid
- archive.__archive_entries.append(post)
+ archive._archive_entries.append(post)
del archive.podposts
def migrate_podpost_v0_v1(self: Podpost):
- if hasattr(self, "entry"):
- if not hasattr(self, "isaudio"):
- self.isaudio = False
- if not hasattr(self, "length"):
- self.length = 0
- if not self.isaudio:
- self.init(self.entry, self.logo_url, self.podurl)
- self.save()
+ if not hasattr(self, "insert_date") or self.insert_date is None:
+ self.insert_date = datetime.datetime.now().timestamp()
+ if not hasattr(self, "isaudio"):
+ self.isaudio = False
+ if not hasattr(self, "length"):
+ self.length = 0
+ if hasattr(self, "entry") and not self.isaudio:
+ self.init(self.entry, self.logo_url, self.podurl)
+ self.save()
def migrate_podcast_v0_v1(self: Podcast):
diff --git a/python/podcast/podpost.py b/python/podcast/podpost.py
index d59b89d..e263fad 100644
--- a/python/podcast/podpost.py
+++ b/python/podcast/podpost.py
@@ -1,7 +1,7 @@
"""
Podpost: a single podcast post
"""
-
+import datetime
import sys
sys.path.append("../")
@@ -41,7 +41,7 @@ class Podpost:
title: str
percentage: float
position: int
- isaudio: bool
+ isaudio: bool # if the post comes from the external folder
id: str
state: int
favorite: bool
@@ -51,13 +51,12 @@ class Podpost:
href: str
duration: Optional[int]
length: int
- published: Optional[float]
- insert_date: object
+ published: Optional[float] # when the post was published according to feed
+ insert_date: float # when we entered this post into our db
link: Optional[str]
type: str
- podurl: str
+ podurl: str # the feed url
chapters: List
- version: int
def __init__(self, entry, podurl, logo_url, data=None, isaudio=False):
"""
@@ -75,6 +74,7 @@ class Podpost:
self.length = 0
self.type = ""
self.href = ""
+ self.insert_date = datetime.datetime.now().timestamp()
if isaudio:
self.init_file_entry(data, logo_url, podurl)
@@ -93,7 +93,6 @@ class Podpost:
self.id = data["id"]
self.length = int(data["length"])
self.published = 0
- self.insert_date = None
self.link = None
self.type = data["mime"]
self.podurl = podurl
@@ -107,7 +106,6 @@ class Podpost:
if len(logo_url) > 0:
if logo_url[0] == "/":
self.logo_path = logo_url
- self.insert_date = None
try:
self.published = timegm(entry.published_parsed)
except:
@@ -262,12 +260,8 @@ class Podpost:
section = format_full_date(self.published)
date = self.published
fdate = s_to_year(date)
- if self.insert_date:
- asection = format_full_date(self.insert_date)
- adate = self.insert_date
- else:
- asection = ""
- adate = 0
+ asection = format_full_date(self.insert_date)
+ adate = self.insert_date
logger.debug("adate, asection %s, %s", adate, asection)
logger.debug("date, section %s, %s", date, section)
if self.duration:
diff --git a/qml/components/ArchiveHandler.py b/qml/components/ArchiveHandler.py
index 4a48d88..bc3edf3 100644
--- a/qml/components/ArchiveHandler.py
+++ b/qml/components/ArchiveHandler.py
@@ -9,28 +9,18 @@ sys.path.append("/usr/share/harbour-podqast/python")
from podcast.archive import ArchiveFactory
from podcast.factory import Factory
+import logging
+logger = logging.getLogger(__name__)
def get_archive_posts(podurl=None):
"""
Return a list of all archive posts
"""
- entries = []
- archive = ArchiveFactory().get_archive()
-
- for archive_entry in archive.get_podposts(sorted_by_date=True):
- entry = Factory().get_podpost(archive_entry.podpost)
- if podurl:
- if entry.podurl == podurl:
- entries.append(entry.get_data())
- else:
- if entry:
- entries.append(entry.get_data())
- else:
- pyotherside.send("ArchiveHandler: We have a none object")
-
- pyotherside.send("createArchiveList", entries)
+ posts = ArchiveFactory().get_archive().get_podpost_objects(url_filter=podurl)
+ sorted_posts = sorted(posts, key=lambda p: p.insert_date, reverse=True)
+ pyotherside.send("createArchiveList", [post.get_data() for post in sorted_posts])
def get_archive_pod_data():
diff --git a/test/__init__.py b/test/__init__.py
index 30af4ca..c174ad0 100644
--- a/test/__init__.py
+++ b/test/__init__.py
@@ -1,3 +1,5 @@
+import os
+import tempfile
import types
import sys
from unittest.mock import Mock
@@ -9,3 +11,6 @@ def mock_pyotherside():
module.send = Mock(name=module_name+'.send')
mock_pyotherside()
+
+os.environ["PODQAST_HOME"] = tempfile.gettempdir()
+print("tempdir: %s"%os.environ["PODQAST_HOME"] )
diff --git a/test/test_archive.py b/test/test_archive.py
index a951a22..a1b958e 100644
--- a/test/test_archive.py
+++ b/test/test_archive.py
@@ -5,7 +5,6 @@ test the archive
import sys
from httpretty import HTTPretty, httprettified
-
from test.test_podcast import read_testdata, xml_headers
sys.path.append("../python")
@@ -51,9 +50,13 @@ def test_insert():
entry2.save()
archive.insert(entry2.id)
- result_posts = list(archive.get_podposts(sorted_by_date=True))
- assert entry1.id == result_posts[1] # older
- assert entry2.id == result_posts[0] # newer
+ result_posts = list(archive.get_podposts())
+ assert entry1.id in result_posts
+ assert entry2.id in result_posts
+ object_ids = [a.id for a in archive.get_podpost_objects('https://freakshow.fm/feed/opus/')]
+ assert entry1.id in object_ids
+ assert entry2.id in object_ids
+ assert 0 == len(list(archive.get_podpost_objects(url_filter='https://i.am.not.corrects/speex')))
def test_get_archives():
"""
diff --git a/test/test_migration_to_v1.py b/test/test_migration_to_v1.py
index c694f0c..c8fc258 100644
--- a/test/test_migration_to_v1.py
+++ b/test/test_migration_to_v1.py
@@ -27,6 +27,9 @@ def test_migration():
podcast: Podcast = PodcastFactory().get_podcast(podcasts[0])
assert podcast != None
assert len(podcast.entry_ids_old_to_new) == 22
+ for post in (Factory().get_podpost(post) for post in podcast.entry_ids_old_to_new for podcast in
+ map(PodcastFactory().get_podcast, podcasts)):
+ assert post.insert_date is not None
assert len(list(podcast.get_entries())) == 22
del os.environ["PODQAST_HOME"]
resetSingletons()
diff --git a/test/test_queue.py b/test/test_queue.py
index 0927ba5..f2e166d 100644
--- a/test/test_queue.py
+++ b/test/test_queue.py
@@ -14,9 +14,8 @@ sys.path.append("../python")
from podcast.queue import QueueFactory
from podcast.factory import Factory
from podcast.queue import Queue
-from podcast.podcast import Podcast
+from podcast.podcast import Podcast, PodcastFactory
from podcast.podpost import Podpost
-import podcast
def test_create_queue():
@@ -70,10 +69,14 @@ def test_get_podposts():
"""
queue = QueueFactory().get_queue()
- queue.podposts = ['85140fc8e16ba62517877ef4857a85f5bbf83e6a236c659a73489f093e51f154',
- 'ce656a3888a282fe9df727e0729fa7d375704e4bd6c0d50e9c0fe7ddafa232ec']
+ podcast = PodcastFactory().get_podcast('https://freakshow.fm/feed/opus/')
+ entry = podcast.entry_ids_old_to_new[1]
+ entry2 = podcast.entry_ids_old_to_new[0]
+ queue.insert_top(entry)
+ queue.insert_top(entry2)
postids = list(queue.get_podposts())
assert len(postids) == 2
for post in postids:
assert type(post) == str
assert type(Factory().get_podpost(post)) == Podpost
+ assert post in [entry,entry2]
--
GitLab
From 6d79cdef668bd638cc913fd9608a52e660ff7c7a Mon Sep 17 00:00:00 2001
From: Thilo Kogge
Date: Mon, 1 Feb 2021 21:20:06 +0100
Subject: [PATCH 05/18] removed adate completly, sorting everything by
insert_date now
---
python/podcast/podpost.py | 4 ----
qml/components/FavoriteHandler.py | 4 +---
2 files changed, 1 insertion(+), 7 deletions(-)
diff --git a/python/podcast/podpost.py b/python/podcast/podpost.py
index e263fad..39beaa2 100644
--- a/python/podcast/podpost.py
+++ b/python/podcast/podpost.py
@@ -261,9 +261,6 @@ class Podpost:
date = self.published
fdate = s_to_year(date)
asection = format_full_date(self.insert_date)
- adate = self.insert_date
- logger.debug("adate, asection %s, %s", adate, asection)
- logger.debug("date, section %s, %s", date, section)
if self.duration:
duration = s_to_hr(self.duration)
else:
@@ -294,7 +291,6 @@ class Podpost:
"date": date,
"fdate": fdate,
"section": section,
- "adate": adate,
"asection": asection,
"length": self.length,
"duration": duration,
diff --git a/qml/components/FavoriteHandler.py b/qml/components/FavoriteHandler.py
index e19a9a9..9ea0aab 100644
--- a/qml/components/FavoriteHandler.py
+++ b/qml/components/FavoriteHandler.py
@@ -79,10 +79,8 @@ def get_favorites(podurl=None):
posts = get_queue_favorites(podurl)
posts = append_archive_favorites(posts, podurl=podurl)
postsdata = []
- for post in posts:
+ for post in sorted(posts, key=lambda p: p.insert_date, reverse=True):
postsdata.append(post.get_data())
-
- postsdata.sort(key=lambda r: r["adate"], reverse=True)
pyotherside.send("favoriteList", postsdata)
--
GitLab
From e9e9e3f4bac77004376ade6556a455b343b0368e Mon Sep 17 00:00:00 2001
From: Thilo Kogge
Date: Mon, 1 Feb 2021 22:06:44 +0100
Subject: [PATCH 06/18] moved favorite logic to main package, added tests,
fixed tests, stabilized tests
---
python/podcast/archive.py | 7 ++-
python/podcast/favorite.py | 80 ++++++++++++++++++++++++++++
qml/components/FavoriteHandler.py | 87 +++----------------------------
test/__init__.py | 14 ++++-
test/test_archive.py | 36 ++++++++-----
test/test_favorites.py | 35 +++++++++++++
test/test_queue.py | 28 +++++++++-
7 files changed, 188 insertions(+), 99 deletions(-)
create mode 100644 python/podcast/favorite.py
create mode 100644 test/test_favorites.py
diff --git a/python/podcast/archive.py b/python/podcast/archive.py
index 1f7f7dc..9318ec5 100644
--- a/python/podcast/archive.py
+++ b/python/podcast/archive.py
@@ -20,6 +20,8 @@ class ArchiveEntry:
@classmethod
def of_podpost(cls, postid: str):
+ if not type(postid) == str:
+ raise ValueError("did not get the id of a post")
archive_entry = ArchiveEntry()
archive_entry.podpost = postid
archive_entry.insert_date = time.time()
@@ -47,11 +49,12 @@ class Archive:
store = Factory().get_store()
store.store(archivename, self)
- def insert(self, podpost):
+ def insert(self, podpost: str):
"""
Insert an podost
"""
-
+ if type(podpost) != str:
+ raise ValueError("please supply the id of the post")
if podpost not in [e.podpost for e in self._archive_entries]:
self._archive_entries.insert(0, ArchiveEntry.of_podpost(podpost))
self.save()
diff --git a/python/podcast/favorite.py b/python/podcast/favorite.py
new file mode 100644
index 0000000..6117218
--- /dev/null
+++ b/python/podcast/favorite.py
@@ -0,0 +1,80 @@
+from podcast.factory import Factory
+
+
+def get_queue_favorites(podurl=None):
+ """
+ Return a list of all favorites posts from queue
+ """
+
+ from podcast.queue import QueueFactory
+
+ posts = []
+
+ queue = QueueFactory().get_queue()
+ for post in queue.get_podposts():
+ p = Factory().get_podpost(post)
+ try:
+ if p.favorite:
+ if podurl:
+ if p.podurl == podurl:
+ posts.append(p)
+ else:
+ posts.append(p)
+ except:
+ pass
+ return posts
+
+
+def append_archive_favorites(posts, podurl=None):
+ """
+ append archive favorites to posts list
+ """
+
+ from podcast.archive import ArchiveFactory
+
+ archive = ArchiveFactory().get_archive()
+
+ for post in archive.get_podposts():
+ p = Factory().get_podpost(post)
+ try:
+ if p.favorite:
+ if p not in posts:
+ if podurl:
+ if p.podurl == podurl:
+ posts.append(p)
+ else:
+ posts.append(p)
+ except:
+ pass
+
+ return posts
+
+
+def get_favorites(podurl=None):
+ """
+ Test
+ """
+
+ posts = get_queue_favorites(podurl)
+ posts = append_archive_favorites(posts, podurl=podurl)
+ yield from sorted(posts, key=lambda p: p.insert_date, reverse=True)
+
+
+def get_favorite_podcast_stats():
+ """
+ """
+
+ entries = {}
+
+ posts = get_queue_favorites()
+ posts = append_archive_favorites(posts)
+ for p in posts:
+ if p.podurl in entries:
+ entries[p.podurl]["count"] += 1
+ else:
+ if p.logo_url:
+ logo_url = p.logo_url
+ else:
+ logo_url = "../../images/podcast.png"
+ entries[p.podurl] = {"count": 1, "logo_url": logo_url}
+ return entries
diff --git a/qml/components/FavoriteHandler.py b/qml/components/FavoriteHandler.py
index 9ea0aab..98dfd6b 100644
--- a/qml/components/FavoriteHandler.py
+++ b/qml/components/FavoriteHandler.py
@@ -6,6 +6,7 @@ import threading
import sys
sys.path.append("/usr/share/harbour-podqast/python")
+import podcast.favorite as favorite
from podcast.factory import Factory
@@ -22,87 +23,11 @@ def toggle_favorite(podpost, do_download=False):
pyotherside.send("favoriteToggled", podpost, post.toggle_fav(do_download))
-def get_queue_favorites(podurl=None):
- """
- Return a list of all favorites posts from queue
- """
-
- from podcast.queue import QueueFactory
-
- posts = []
-
- queue = QueueFactory().get_queue()
- for post in queue.get_podposts():
- p = Factory().get_podpost(post)
- try:
- if p.favorite:
- if podurl:
- if p.podurl == podurl:
- posts.append(p)
- else:
- posts.append(p)
- except:
- pass
- return posts
-
-
-def append_archive_favorites(posts, podurl=None):
- """
- append archive favorites to posts list
- """
-
- from podcast.archive import ArchiveFactory
-
- archive = ArchiveFactory().get_archive()
-
- for post in archive.get_podposts():
- p = Factory().get_podpost(post)
- try:
- if p.favorite:
- if p not in posts:
- if podurl:
- if p.podurl == podurl:
- posts.append(p)
- else:
- posts.append(p)
- except:
- pass
-
- return posts
-
-
-def get_favorites(podurl=None):
- """
- Test
- """
-
- posts = get_queue_favorites(podurl)
- posts = append_archive_favorites(posts, podurl=podurl)
- postsdata = []
- for post in sorted(posts, key=lambda p: p.insert_date, reverse=True):
- postsdata.append(post.get_data())
- pyotherside.send("favoriteList", postsdata)
-
+def send_favorites(podurl=None):
+ pyotherside.send("favoriteList", [p.get_data() for p in favorite.get_favorites(podurl)])
def get_fav_pod_data():
- """
- """
-
- entries = {}
-
- posts = get_queue_favorites()
- posts = append_archive_favorites(posts)
- for p in posts:
- if p.podurl in entries:
- entries[p.podurl]["count"] += 1
- else:
- if p.logo_url:
- logo_url = p.logo_url
- else:
- logo_url = "../../images/podcast.png"
- entries[p.podurl] = {"count": 1, "logo_url": logo_url}
-
- pyotherside.send("archivePodList", entries)
+ pyotherside.send("archivePodList", favorite.get_favorite_podcast_stats())
class FavoriteHandler:
@@ -125,10 +50,10 @@ class FavoriteHandler:
return
if podurl:
self.bgthread2 = threading.Thread(
- target=get_favorites, args=[podurl]
+ target=send_favorites, args=[podurl]
)
else:
- self.bgthread2 = threading.Thread(target=get_favorites)
+ self.bgthread2 = threading.Thread(target=send_favorites)
self.bgthread2.start()
def getfavpoddata(self):
diff --git a/test/__init__.py b/test/__init__.py
index c174ad0..2de8407 100644
--- a/test/__init__.py
+++ b/test/__init__.py
@@ -4,13 +4,23 @@ import types
import sys
from unittest.mock import Mock
+
def mock_pyotherside():
module_name = "pyotherside"
module = types.ModuleType(module_name)
sys.modules[module_name] = module
- module.send = Mock(name=module_name+'.send')
+ module.send = Mock(name=module_name + '.send')
+
mock_pyotherside()
os.environ["PODQAST_HOME"] = tempfile.gettempdir()
-print("tempdir: %s"%os.environ["PODQAST_HOME"] )
+print("tempdir: %s" % os.environ["PODQAST_HOME"])
+
+
+def cleanup_archive():
+ from podcast.archive import ArchiveFactory
+ archive = ArchiveFactory().get_archive()
+ for post in archive.get_podposts():
+ archive.remove_podpost(post)
+ archive.save()
diff --git a/test/test_archive.py b/test/test_archive.py
index a1b958e..2c8e7a8 100644
--- a/test/test_archive.py
+++ b/test/test_archive.py
@@ -5,6 +5,8 @@ test the archive
import sys
from httpretty import HTTPretty, httprettified
+
+from . import cleanup_archive
from test.test_podcast import read_testdata, xml_headers
sys.path.append("../python")
@@ -14,6 +16,7 @@ from podcast.factory import Factory
from podcast.podcast import Podcast
from podcast.podpost import Podpost
+
def test_create_archive():
"""
test if archive is created
@@ -25,6 +28,7 @@ def test_create_archive():
a2 = ArchiveFactory().get_archive()
assert a1 == a2
+
def test_archive_save():
"""
does the archive save itself?
@@ -33,41 +37,47 @@ def test_archive_save():
a = ArchiveFactory().get_archive()
a.save()
-@httprettified
+
def test_insert():
"""
"""
+
+ archive = ArchiveFactory().get_archive()
+ entry1, entry2 = setup_archive_with_2_posts(archive)
+
+ result_posts = list(archive.get_podposts())
+ assert entry1.id in result_posts
+ assert entry2.id in result_posts
+ object_ids = [a.id for a in archive.get_podpost_objects('https://freakshow.fm/feed/opus/')]
+ assert entry1.id in object_ids
+ assert entry2.id in object_ids
+ assert 0 == len(list(archive.get_podpost_objects(url_filter='https://i.am.not.corrects/speex')))
+
+
+@httprettified
+def setup_archive_with_2_posts(archive):
HTTPretty.register_uri(HTTPretty.GET, 'https://freakshow.fm/feed/opus/',
body=read_testdata('testdata/freakshow.rss'), adding_headers=xml_headers)
-
- archive = ArchiveFactory().get_archive()
podcast = Podcast('https://freakshow.fm/feed/opus/')
entry1 = podcast.get_entry(podcast.entry_ids_old_to_new[0])
entry1.save()
archive.insert(entry1.id)
-
entry2 = podcast.get_entry(podcast.entry_ids_old_to_new[1])
entry2.save()
archive.insert(entry2.id)
+ return entry1, entry2
- result_posts = list(archive.get_podposts())
- assert entry1.id in result_posts
- assert entry2.id in result_posts
- object_ids = [a.id for a in archive.get_podpost_objects('https://freakshow.fm/feed/opus/')]
- assert entry1.id in object_ids
- assert entry2.id in object_ids
- assert 0 == len(list(archive.get_podpost_objects(url_filter='https://i.am.not.corrects/speex')))
def test_get_archives():
"""
Test listing of podposts
"""
-
+ cleanup_archive()
a = ArchiveFactory().get_archive()
+ setup_archive_with_2_posts(a)
count = 0
for post in a.get_podposts():
assert type(post) == str
assert type(Factory().get_podpost(post)) == Podpost
count += 1
- # make sure to clean ~/.local/share/harbour-podqast if this fails
assert count == 2
diff --git a/test/test_favorites.py b/test/test_favorites.py
new file mode 100644
index 0000000..c41e8fc
--- /dev/null
+++ b/test/test_favorites.py
@@ -0,0 +1,35 @@
+from httpretty import HTTPretty, httprettified
+
+from podcast.archive import ArchiveFactory
+from podcast.factory import Factory
+from . import cleanup_archive
+from test.test_podcast import read_testdata, xml_headers
+
+
+@httprettified
+def test_queue_favorites():
+ """
+ Test listing of podposts
+ """
+ HTTPretty.register_uri(HTTPretty.GET, 'https://freakshow.fm/feed/opus/',
+ body=read_testdata('testdata/freakshow.rss'), adding_headers=xml_headers)
+
+ from podcast import favorite
+ from podcast.podcast import PodcastFactory
+ cleanup_archive()
+
+ url = 'https://freakshow.fm/feed/opus/'
+ podcast = PodcastFactory().get_podcast(url)
+ fav_posts = [Factory().get_podpost(podcast.entry_ids_old_to_new[i]) for i in range(0, 10, 2)]
+ assert len(fav_posts) == 5
+ archive = ArchiveFactory().get_archive()
+ assert len(list(archive.get_podposts())) == 0
+ for post in fav_posts:
+ post.favorite = True
+ post.save()
+ archive.insert(post.id)
+ archive.save()
+ assert len(favorite.get_queue_favorites()) == 0
+ assert len(list(favorite.get_favorites())) == 5
+ assert len(favorite.get_favorite_podcast_stats()) == 1
+ assert favorite.get_favorite_podcast_stats()[url]['count'] == 5
diff --git a/test/test_queue.py b/test/test_queue.py
index f2e166d..7043775 100644
--- a/test/test_queue.py
+++ b/test/test_queue.py
@@ -38,6 +38,7 @@ def test_queue_save():
q = QueueFactory().get_queue()
q.save()
+
@httpretty.activate
def test_insert_top():
"""
@@ -79,4 +80,29 @@ def test_get_podposts():
for post in postids:
assert type(post) == str
assert type(Factory().get_podpost(post)) == Podpost
- assert post in [entry,entry2]
+ assert post in [entry, entry2]
+
+
+def test_queue_favorites():
+ """
+ Test listing of podposts
+ """
+ from podcast import favorite
+
+ queue = QueueFactory().get_queue()
+ url = 'https://freakshow.fm/feed/opus/'
+ podcast = PodcastFactory().get_podcast(url)
+ for post in (Factory().get_podpost(podcast.entry_ids_old_to_new[i]) for i in range(0, 10, 2)):
+ post.favorite = True
+ post.save()
+ for id in podcast.entry_ids_old_to_new:
+ queue.insert_bottom(id)
+ assert len(queue.podposts) == 20
+ assert len(favorite.get_queue_favorites('https://wrong.url')) == 0
+ assert [fav.id for fav in favorite.get_queue_favorites()] == [podcast.entry_ids_old_to_new[i] for i in
+ range(0, 10, 2)]
+ assert len(favorite.get_queue_favorites(url)) == 5
+ for id in podcast.entry_ids_old_to_new:
+ queue.remove(id)
+ assert len(queue.podposts) == 0
+ assert len(favorite.get_queue_favorites()) == 0
--
GitLab
From c1fd61102cf6bde258d8d8a9a652cef1aaaba523 Mon Sep 17 00:00:00 2001
From: Thilo Kogge
Date: Wed, 3 Feb 2021 16:30:00 +0100
Subject: [PATCH 07/18] create separate factory for podposts introduced
basefactory to prevent code duplication
---
python/podcast/archive.py | 4 +-
python/podcast/data_migration.py | 8 ++--
python/podcast/factory.py | 71 ++++---------------------------
python/podcast/favorite.py | 20 ++++-----
python/podcast/inbox.py | 4 +-
python/podcast/podcast.py | 48 ++++-----------------
python/podcast/podpost.py | 38 ++++++++++++++---
python/podcast/queue.py | 22 +++++-----
qml/components/ArchiveHandler.py | 4 +-
qml/components/ExternalHandler.py | 6 +--
qml/components/FavoriteHandler.py | 7 ++-
qml/components/InboxHandler.py | 6 ++-
qml/components/QueueHandler.py | 12 +++---
test/__init__.py | 7 +++
test/test_archive.py | 4 +-
test/test_factory.py | 59 +------------------------
test/test_favorites.py | 6 ++-
test/test_migration_to_v1.py | 3 +-
test/test_queue.py | 6 +--
19 files changed, 121 insertions(+), 214 deletions(-)
diff --git a/python/podcast/archive.py b/python/podcast/archive.py
index 9318ec5..6cb950c 100644
--- a/python/podcast/archive.py
+++ b/python/podcast/archive.py
@@ -9,7 +9,7 @@ sys.path.append("../")
from podcast.singleton import Singleton
from podcast.factory import Factory
-from podcast.podpost import Podpost
+from podcast.podpost import Podpost, PodpostFactory
archivename = "the_archive"
@@ -72,7 +72,7 @@ class Archive:
def get_podpost_objects(self, url_filter=None) -> Iterator[Podpost]:
for id in self.get_podposts():
- entry: Podpost = Factory().get_podpost(id)
+ entry: Podpost = PodpostFactory().get_podpost(id)
if entry:
if not url_filter or (url_filter and entry.podurl == url_filter):
yield entry
diff --git a/python/podcast/data_migration.py b/python/podcast/data_migration.py
index 5cbe69d..8239696 100644
--- a/python/podcast/data_migration.py
+++ b/python/podcast/data_migration.py
@@ -8,7 +8,7 @@ import pyotherside
from podcast.factory import Factory
from podcast.podcast import PodcastFactory, Podcast
from podcast.podcastlist import PodcastListFactory
-from podcast.podpost import Podpost
+from podcast.podpost import Podpost, PodpostFactory
logger = logging.getLogger(__name__)
@@ -41,7 +41,7 @@ def run_migrations():
if podcast != None:
migrate_podcast_v0_v1(podcast)
for entry_id in podcast.entry_ids_old_to_new:
- migrate_podpost_v0_v1(Factory().get_podpost(entry_id))
+ migrate_podpost_v0_v1(PodpostFactory().get_podpost(entry_id))
i += 1
pyotherside.send("migrationProgress", i)
migrate_archive_v0_v1()
@@ -79,7 +79,7 @@ def migrate_archive_v0_v1():
archive._archive_entries = []
for postid in old_archive:
archive_entry = ArchiveEntry()
- post = Factory().get_podpost(postid)
+ post = PodpostFactory().get_podpost(postid)
if not post:
continue
if hasattr(post, "insert_date") and post.insert_date:
@@ -118,7 +118,7 @@ def migrate_podcast_v0_v1(self: Podcast):
logger.info("Found %d entries in old format", old_entry_count)
for entry in self.feed.entries:
post = Podpost(entry, self.url, image)
- p2 = Factory().get_podpost(post.id)
+ p2 = PodpostFactory().get_podpost(post.id)
if p2:
post = p2
post.save()
diff --git a/python/podcast/factory.py b/python/podcast/factory.py
index 15d7dca..450c440 100644
--- a/python/podcast/factory.py
+++ b/python/podcast/factory.py
@@ -16,25 +16,19 @@ from podcast.store import Store
from podcast import util
-import feedparser
import pyotherside
-
-class Factory(metaclass=Singleton):
- """
- Factory for
- """
+class BaseFactory(metaclass=Singleton):
data_home: str
+ store: Store
def __init__(self, progname="harbour-podqast"):
"""
Initialization
- feedcache: cache for feeds
store: store for feeds
"""
self.queue = None
- self.feedcache = Cache()
self.object = None
self._set_paths(progname)
@@ -53,7 +47,6 @@ class Factory(metaclass=Singleton):
util.make_directory(self.afilepath)
self.store = Store(storepath)
- self.podpostcache = Cache(limit=500)
def _set_paths(self, progname):
home = os.path.expanduser("~")
@@ -71,6 +64,13 @@ class Factory(metaclass=Singleton):
self.cache_home = os.path.join(xdg_cache_home, progname)
+class Factory(BaseFactory):
+ """
+ Factory for
+ """
+ def __init__(self):
+ super().__init__()
+
def init_from_qml(self, object):
"""
Get QML object
@@ -113,59 +113,6 @@ class Factory(metaclass=Singleton):
except:
return None
- def get_feed(self, index):
- """
- get a feed object by index
- index: index of feed
- """
-
- feed = self.feedcache.get(index)
- if not feed:
- feed = self.store.get(index)
- if not feed:
- feed = feedparser.parse(index)
- if feed.bozo != 0:
- pyotherside.send("get_feed: error in feed parsing")
- return None
- self.feedcache.store(index, feed)
-
- return feed
-
- def safe_feed(self, index):
- """
- Safe feed to disk
- """
-
- feed = self.get_feed(index)
- if feed:
- self.store.store(index, feed)
-
- def delete_feed(self, index):
- """
- Delete file from disk
- """
-
- self.store.delete(index)
-
- def get_podpost(self, index):
- """
- Get a podpost from cache or store
- """
-
- podpost = self.podpostcache.get(index)
- if not podpost:
- podpost = self.store.get(index)
- if podpost:
- self.podpostcache.store(index, podpost)
- else:
- return None
-
- return podpost
-
- def delete_podpost(self, index):
- self.podpostcache.delete(index)
- self.store.delete(index)
-
def get_store(self):
"""
get the store
diff --git a/python/podcast/favorite.py b/python/podcast/favorite.py
index 6117218..db481cd 100644
--- a/python/podcast/favorite.py
+++ b/python/podcast/favorite.py
@@ -1,4 +1,4 @@
-from podcast.factory import Factory
+from podcast.podpost import PodpostFactory
def get_queue_favorites(podurl=None):
@@ -12,16 +12,14 @@ def get_queue_favorites(podurl=None):
queue = QueueFactory().get_queue()
for post in queue.get_podposts():
- p = Factory().get_podpost(post)
- try:
- if p.favorite:
- if podurl:
- if p.podurl == podurl:
- posts.append(p)
- else:
+ p = PodpostFactory().get_podpost(post)
+ if p.favorite:
+ if podurl:
+ if p.podurl == podurl:
posts.append(p)
- except:
- pass
+ else:
+ posts.append(p)
+
return posts
@@ -35,7 +33,7 @@ def append_archive_favorites(posts, podurl=None):
archive = ArchiveFactory().get_archive()
for post in archive.get_podposts():
- p = Factory().get_podpost(post)
+ p = PodpostFactory().get_podpost(post)
try:
if p.favorite:
if p not in posts:
diff --git a/python/podcast/inbox.py b/python/podcast/inbox.py
index 41cf20f..aad9af7 100644
--- a/python/podcast/inbox.py
+++ b/python/podcast/inbox.py
@@ -5,6 +5,8 @@ The inbox queue. This also uses a Factory for instancing
import sys
import time
+from podcast.podpost import PodpostFactory
+
sys.path.append("../")
from podcast.singleton import Singleton
@@ -44,7 +46,7 @@ class Inbox:
if podpost not in self.podposts:
self.podposts.insert(0, podpost)
- post = Factory().get_podpost(podpost)
+ post = PodpostFactory().get_podpost(podpost)
if post.insert_date == None:
post.insert_date = time.time()
post.save()
diff --git a/python/podcast/podcast.py b/python/podcast/podcast.py
index 424d634..1c495a1 100644
--- a/python/podcast/podcast.py
+++ b/python/podcast/podcast.py
@@ -7,14 +7,14 @@ from typing import List, Dict, Optional, Generator
from feedparser import FeedParserDict
-from podcast.factory import Factory
+from podcast.factory import Factory, BaseFactory
sys.path.append("/usr/share/podqast/python")
from podcast.singleton import Singleton
from podcast.cache import Cache
from podcast.store import Store
-from podcast.podpost import Podpost
+from podcast.podpost import Podpost, PodpostFactory
from podcast import util
from email.utils import mktime_tz, parsedate_tz
from calendar import timegm
@@ -230,9 +230,8 @@ class Podcast:
"""
Get an entry from podcast by id
"""
- from podcast.factory import Factory
- entry = Factory().get_podpost(id)
+ entry = PodpostFactory().get_podpost(id)
return entry
def get_entries(self) -> Generator[dict, None, None]:
@@ -242,7 +241,7 @@ class Podcast:
from podcast.factory import Factory
logger.debug("Podcast get_entries started.")
for id in self.entry_ids_old_to_new:
- yield Factory().get_podpost(id).get_data()
+ yield PodpostFactory().get_podpost(id).get_data()
def get_latest_entry(self) -> Optional[Podpost]:
"""
@@ -386,45 +385,16 @@ class Podcast:
}
-class PodcastFactory(metaclass=Singleton):
+class PodcastFactory(BaseFactory):
"""
Helping Factory
"""
store: Store
podcastcache: Cache
- def __init__(self, progname="harbour-podqast"):
- """
- Initialization
- """
-
- self.podcastcache = Cache(limit=50)
- home = os.path.expanduser("~")
- xdg_data_home = os.environ.get(
- "XDG_DATA_HOME", os.path.join(home, ".local", "share")
- )
- xdg_config_home = os.environ.get(
- "XDG_CONFIG_HOME", os.path.join(home, ".config")
- )
- xdg_cache_home = os.path.join(
- "XDG_CACHE_HOME", os.path.join(home, ".cache")
- )
-
- self.data_home = os.path.join(xdg_data_home, progname)
- self.config_home = os.path.join(xdg_config_home, progname)
- self.cache_home = os.path.join(xdg_cache_home, progname)
-
- if "PODQAST_HOME" in os.environ:
- home = os.environ["PODQAST_HOME"]
- self.data_home = self.config_home = self.cache_home = home
-
- self.iconpath = os.path.join(self.data_home, "icons")
- storepath = os.path.join(self.data_home, "store")
- util.make_directory(self.data_home)
- util.make_directory(storepath)
- util.make_directory(self.iconpath)
-
- self.store = Store(storepath)
+ def __init__(self):
+ super().__init__()
+ self.podcastcache = Cache(50)
def get_podcast(self, url, preview: bool = False) -> Optional[Podcast]:
"""
@@ -454,6 +424,6 @@ class PodcastFactory(metaclass=Singleton):
to_delete = self.get_podcast(url)
if to_delete != None:
for post in to_delete.entry_ids_old_to_new:
- Factory().delete_podpost(post)
+ PodpostFactory().delete_podpost(post)
self.podcastcache.delete(url)
self.store.delete(url)
diff --git a/python/podcast/podpost.py b/python/podcast/podpost.py
index 39beaa2..b012c3b 100644
--- a/python/podcast/podpost.py
+++ b/python/podcast/podpost.py
@@ -4,6 +4,8 @@ Podpost: a single podcast post
import datetime
import sys
+from podcast.cache import Cache
+
sys.path.append("../")
import hashlib
@@ -14,11 +16,10 @@ from email.utils import mktime_tz, parsedate_tz
from calendar import timegm
from typing import Optional, List
-from podcast.factory import Factory
+from podcast.factory import Factory, BaseFactory
from podcast.util import s_to_hr, tx_to_s, dl_from_url, dl_from_url_progress
from podcast.util import delete_file, format_full_date, s_to_year, make_symlink
from podcast.util import get_audio_meta, get_audio_tech, down_audio_icon
-from podcast.queue import QueueFactory
import pyotherside
import time
import re
@@ -310,9 +311,7 @@ class Podpost:
logger.info("storing podpost %s", self.id)
if not self.logo_path:
self.download_icon()
- store = Factory().get_store()
- store.store(self.id, self)
- logger.debug("...done")
+ PodpostFactory().persist(self.id, self)
def download_audio(self):
"""
@@ -497,6 +496,7 @@ class Podpost:
toggle favorite flag (and create one if it not exists)
return: bool if favorite
"""
+ from podcast.queue import QueueFactory
try:
self.favorite = not self.favorite
@@ -572,3 +572,31 @@ class Podpost:
return favorite
+class PodpostFactory(BaseFactory):
+
+ def __init__(self):
+ super().__init__()
+ self.podpostcache = Cache(limit=500)
+
+ def get_podpost(self, index):
+ """
+ Get a podpost from cache or store
+ """
+
+ podpost = self.podpostcache.get(index)
+ if not podpost:
+ podpost = self.store.get(index)
+ if podpost:
+ self.podpostcache.store(index, podpost)
+ else:
+ return None
+
+ return podpost
+
+ def delete_podpost(self, index):
+ self.podpostcache.delete(index)
+ self.store.delete(index)
+
+ def persist(self, id, self1):
+ self.store.store(id,self1)
+ self.podpostcache.store(id,self1)
diff --git a/python/podcast/queue.py b/python/podcast/queue.py
index 51272ac..7454a09 100644
--- a/python/podcast/queue.py
+++ b/python/podcast/queue.py
@@ -8,6 +8,8 @@ import os
import pyotherside
import time
+from podcast.podpost import PodpostFactory
+
sys.path.append("../")
from podcast.singleton import Singleton
@@ -57,7 +59,7 @@ class Queue:
self.top = None
else:
podpost = self.podposts[0]
- self.top = Factory().get_podpost(podpost)
+ self.top = PodpostFactory().get_podpost(podpost)
return self.top
@@ -81,7 +83,7 @@ class Queue:
self.podposts.remove(podpost)
self.podposts.insert(0, podpost)
- post = Factory().get_podpost(podpost)
+ post = PodpostFactory().get_podpost(podpost)
position = post.get_position / 1000
duration = post.duration
if duration == 0 or duration - position < 60:
@@ -110,7 +112,7 @@ class Queue:
self.podposts.remove(podpost)
self.podposts.insert(1, podpost)
- post = Factory().get_podpost(podpost)
+ post = PodpostFactory().get_podpost(podpost)
position = post.get_position / 1000
duration = post.duration
if duration == 0 or duration - position < 60:
@@ -136,7 +138,7 @@ class Queue:
self.podposts.remove(podpost)
self.podposts.append(podpost)
- post = Factory().get_podpost(podpost)
+ post = PodpostFactory().get_podpost(podpost)
position = post.get_position / 1000
duration = post.duration
if duration == 0 or duration - position < 60:
@@ -156,16 +158,16 @@ class Queue:
"""
if podpost in self.podposts:
- post = Factory().get_podpost(podpost)
+ post = PodpostFactory().get_podpost(podpost)
post.delete_file()
post.state = 0
post.save()
if podpost == self.podposts[0] and len(self.podposts) > 1:
- post1 = Factory().get_podpost(self.podposts[1])
+ post1 = PodpostFactory().get_podpost(self.podposts[1])
pyotherside.send("setpos", post1.position)
self.podposts.remove(podpost)
else:
- Factory().get_podpost(podpost).save()
+ PodpostFactory().get_podpost(podpost).save()
self.save()
@@ -175,7 +177,7 @@ class Queue:
"""
if podpost in self.podposts:
- post = Factory().get_podpost(podpost)
+ post = PodpostFactory().get_podpost(podpost)
for perc in post.download_audio():
yield perc
@@ -188,7 +190,7 @@ class Queue:
"""
for podpost in self.podposts:
- post = Factory().get_podpost(podpost)
+ post = PodpostFactory().get_podpost(podpost)
try:
if post.file_path:
if os.path.isfile(post.file_path):
@@ -204,7 +206,7 @@ class Queue:
"""
return (
- Factory()
+ PodpostFactory()
.get_podpost(self.podposts[0])
.get_hr_time(position=position)
)
diff --git a/qml/components/ArchiveHandler.py b/qml/components/ArchiveHandler.py
index bc3edf3..c9301fa 100644
--- a/qml/components/ArchiveHandler.py
+++ b/qml/components/ArchiveHandler.py
@@ -5,6 +5,8 @@ import pyotherside
import threading
import sys
+from podcast.podpost import PodpostFactory
+
sys.path.append("/usr/share/harbour-podqast/python")
from podcast.archive import ArchiveFactory
@@ -32,7 +34,7 @@ def get_archive_pod_data():
archive = ArchiveFactory().get_archive()
for post in archive.get_podposts():
- entry = Factory().get_podpost(post)
+ entry = PodpostFactory().get_podpost(post)
if entry.podurl in entries:
entries[entry.podurl]["count"] += 1
else:
diff --git a/qml/components/ExternalHandler.py b/qml/components/ExternalHandler.py
index b4be120..02406a3 100644
--- a/qml/components/ExternalHandler.py
+++ b/qml/components/ExternalHandler.py
@@ -15,7 +15,7 @@ from podcast.archive import ArchiveFactory
from podcast.queue import QueueFactory
from podcast.factory import Factory
-from podcast.podpost import Podpost
+from podcast.podpost import Podpost, PodpostFactory
import inotify.adapters
import mutagen
@@ -170,7 +170,7 @@ def get_external_posts():
for post in external.get_podposts():
pyotherside.send("podposts loop")
- entry = Factory().get_podpost(post)
+ entry = PodpostFactory().get_podpost(post)
entries.append(entry.get_data())
pyotherside.send("after py external")
# entries.sort(key = lambda r: r["edate"], reverse=True)
@@ -186,7 +186,7 @@ def get_external_pod_data():
external = ExternalFactory().get_external()
for post in external.get_podposts():
- entry = Factory().get_podpost(post)
+ entry = PodpostFactory().get_podpost(post)
if entry.podurl in entries:
entries[entry.podurl]["count"] += 1
else:
diff --git a/qml/components/FavoriteHandler.py b/qml/components/FavoriteHandler.py
index 98dfd6b..2f686e9 100644
--- a/qml/components/FavoriteHandler.py
+++ b/qml/components/FavoriteHandler.py
@@ -5,18 +5,17 @@ import pyotherside
import threading
import sys
+from podcast.podpost import PodpostFactory
+
sys.path.append("/usr/share/harbour-podqast/python")
import podcast.favorite as favorite
-from podcast.factory import Factory
-
-
def toggle_favorite(podpost, do_download=False):
"""
Return a list of all archive posts
"""
- post = Factory().get_podpost(podpost)
+ post = PodpostFactory().get_podpost(podpost)
if not post:
return
diff --git a/qml/components/InboxHandler.py b/qml/components/InboxHandler.py
index f0038ca..a315be6 100644
--- a/qml/components/InboxHandler.py
+++ b/qml/components/InboxHandler.py
@@ -5,6 +5,8 @@ import pyotherside
import threading
import sys
+from podcast.podpost import PodpostFactory
+
sys.path.append("/usr/share/harbour-podqast/python")
from podcast.inbox import InboxFactory
@@ -23,7 +25,7 @@ def get_inbox_posts(podurl=None):
pyotherside.send("len Inbox %d" % len(inbox.podposts))
for post in inbox.get_podposts():
- entry = Factory().get_podpost(post)
+ entry = PodpostFactory().get_podpost(post)
if podurl:
if entry.podurl == podurl:
entries.append(entry.get_data())
@@ -43,7 +45,7 @@ def get_inbox_pod_data():
inbox = InboxFactory().get_inbox()
for post in inbox.get_podposts():
- entry = Factory().get_podpost(post)
+ entry = PodpostFactory().get_podpost(post)
if entry.podurl in entries:
entries[entry.podurl]["count"] += 1
else:
diff --git a/qml/components/QueueHandler.py b/qml/components/QueueHandler.py
index 2c88455..59e10e7 100644
--- a/qml/components/QueueHandler.py
+++ b/qml/components/QueueHandler.py
@@ -5,6 +5,8 @@ import pyotherside
import threading
import sys
+from podcast.podpost import PodpostFactory
+
sys.path.append("/usr/share/harbour-podqast/python")
from podcast.queue import QueueFactory
@@ -21,7 +23,7 @@ def get_queue_posts(moved=""):
queue = QueueFactory().get_queue()
for post in queue.get_podposts():
- entry = Factory().get_podpost(post)
+ entry = PodpostFactory().get_podpost(post)
edata = entry.get_data()
edata["moved"] = edata["id"] == moved
entries.append(edata)
@@ -43,7 +45,7 @@ def get_first_entry():
if len(queue.podposts) < 1:
return None
pyotherside.send(
- "firstentry", Factory().get_podpost(queue.podposts[0]).get_data()
+ "firstentry", PodpostFactory().get_podpost(queue.podposts[0]).get_data()
)
@@ -214,7 +216,7 @@ def get_episode_chapters(id):
id: id of the episode
"""
- entry = Factory().get_podpost(id)
+ entry = PodpostFactory().get_podpost(id)
chapters = entry.get_chapters()
pyotherside.send("episodeChapters", chapters)
@@ -225,7 +227,7 @@ def send_first_episode_chapters(id):
(necessary when chapters of the currently
playing episode are selected/deselected)
"""
- entry = Factory().get_podpost(id)
+ entry = PodpostFactory().get_podpost(id)
edata = entry.get_data()
chapters = entry.get_chapters()
pyotherside.send("setFirst", edata, chapters)
@@ -237,7 +239,7 @@ def toggle_chapter(episodeid, chapterid):
episodeid: id of the episode
chapterid: chapter number
"""
- entry = Factory().get_podpost(episodeid)
+ entry = PodpostFactory().get_podpost(episodeid)
entry.toggle_chapter(chapterid)
diff --git a/test/__init__.py b/test/__init__.py
index 2de8407..24706ea 100644
--- a/test/__init__.py
+++ b/test/__init__.py
@@ -24,3 +24,10 @@ def cleanup_archive():
for post in archive.get_podposts():
archive.remove_podpost(post)
archive.save()
+
+def cleanup_queue():
+ from podcast.queue import QueueFactory
+ queue = QueueFactory().get_queue()
+ for post in queue.get_podposts():
+ queue.remove(post)
+ queue.save()
diff --git a/test/test_archive.py b/test/test_archive.py
index 2c8e7a8..b74fc3a 100644
--- a/test/test_archive.py
+++ b/test/test_archive.py
@@ -14,7 +14,7 @@ sys.path.append("../python")
from podcast.archive import ArchiveFactory, Archive
from podcast.factory import Factory
from podcast.podcast import Podcast
-from podcast.podpost import Podpost
+from podcast.podpost import Podpost, PodpostFactory
def test_create_archive():
@@ -78,6 +78,6 @@ def test_get_archives():
count = 0
for post in a.get_podposts():
assert type(post) == str
- assert type(Factory().get_podpost(post)) == Podpost
+ assert type(PodpostFactory().get_podpost(post)) == Podpost
count += 1
assert count == 2
diff --git a/test/test_factory.py b/test/test_factory.py
index 6d8530a..49238a5 100644
--- a/test/test_factory.py
+++ b/test/test_factory.py
@@ -3,73 +3,18 @@ Factory test
"""
import sys
+
sys.path.append("../python")
from podcast.factory import Factory
-from podcast.queue import Queue
-import feedparser
def test_singleton():
"""
Factory is a Singleton. Let's test, if it really is...
"""
- f1 = Factory() # first instance: set storedir
+ f1 = Factory() # first instance: set storedir
f2 = Factory()
assert f1 == f2
-
-def test_getfeed():
- """
- get a feed
- """
-
- f = Factory()
- feed1 = f.get_feed("https://freakshow.fm/feed/mp3")
- feed2 = f.get_feed("https://freakshow.fm/feed/mp3")
- feed3 = f.get_feed("https://cre.fm/feed/opus")
-
- assert feed1 == feed2
- assert type(feed1) == feedparser.FeedParserDict
-
-def test_getfeed2():
- """
- get a feed (should work offline)
- """
-
- f = Factory()
- feed1 = f.get_feed("https://freakshow.fm/feed/mp3")
- feed2 = f.get_feed("https://freakshow.fm/feed/mp3")
- feed3 = f.get_feed("https://cre.fm/feed/opus")
-
- assert feed1 == feed2
- assert feed1 != feed3
-
- assert type(feed1) == feedparser.FeedParserDict
- assert type(feed3) == feedparser.FeedParserDict
-
-def test_feed_persist():
- """
- Test feed persisting
- """
-
- f = Factory()
- f.safe_feed("https://freakshow.fm/feed/mp3")
- f.safe_feed("https://cre.fm/feed/opus")
-
-def test_feed_unpersist():
- """
- test feed removing
- """
-
- f = Factory()
- f.delete_feed("https://cre.fm/feed/opus")
-
-def test_feed_unpersist2():
- """
- delete other feed too
- """
-
- f = Factory()
- f.delete_feed("https://freakshow.fm/feed/mp3")
diff --git a/test/test_favorites.py b/test/test_favorites.py
index c41e8fc..9ad400d 100644
--- a/test/test_favorites.py
+++ b/test/test_favorites.py
@@ -2,7 +2,8 @@ from httpretty import HTTPretty, httprettified
from podcast.archive import ArchiveFactory
from podcast.factory import Factory
-from . import cleanup_archive
+from podcast.podpost import PodpostFactory
+from . import cleanup_archive, cleanup_queue
from test.test_podcast import read_testdata, xml_headers
@@ -17,10 +18,11 @@ def test_queue_favorites():
from podcast import favorite
from podcast.podcast import PodcastFactory
cleanup_archive()
+ cleanup_queue()
url = 'https://freakshow.fm/feed/opus/'
podcast = PodcastFactory().get_podcast(url)
- fav_posts = [Factory().get_podpost(podcast.entry_ids_old_to_new[i]) for i in range(0, 10, 2)]
+ fav_posts = [PodpostFactory().get_podpost(podcast.entry_ids_old_to_new[i]) for i in range(0, 10, 2)]
assert len(fav_posts) == 5
archive = ArchiveFactory().get_archive()
assert len(list(archive.get_podposts())) == 0
diff --git a/test/test_migration_to_v1.py b/test/test_migration_to_v1.py
index c8fc258..2c15b6c 100644
--- a/test/test_migration_to_v1.py
+++ b/test/test_migration_to_v1.py
@@ -10,6 +10,7 @@ from podcast.factory import Factory
from podcast.inbox import InboxFactory
from podcast.podcast import Podcast, PodcastFactory
from podcast.podcastlist import PodcastListFactory
+from podcast.podpost import PodpostFactory
from podcast.queue import QueueFactory
sys.path.append("../python")
@@ -27,7 +28,7 @@ def test_migration():
podcast: Podcast = PodcastFactory().get_podcast(podcasts[0])
assert podcast != None
assert len(podcast.entry_ids_old_to_new) == 22
- for post in (Factory().get_podpost(post) for post in podcast.entry_ids_old_to_new for podcast in
+ for post in (PodpostFactory().get_podpost(post) for post in podcast.entry_ids_old_to_new for podcast in
map(PodcastFactory().get_podcast, podcasts)):
assert post.insert_date is not None
assert len(list(podcast.get_entries())) == 22
diff --git a/test/test_queue.py b/test/test_queue.py
index 7043775..919aa37 100644
--- a/test/test_queue.py
+++ b/test/test_queue.py
@@ -15,7 +15,7 @@ from podcast.queue import QueueFactory
from podcast.factory import Factory
from podcast.queue import Queue
from podcast.podcast import Podcast, PodcastFactory
-from podcast.podpost import Podpost
+from podcast.podpost import Podpost, PodpostFactory
def test_create_queue():
@@ -79,7 +79,7 @@ def test_get_podposts():
assert len(postids) == 2
for post in postids:
assert type(post) == str
- assert type(Factory().get_podpost(post)) == Podpost
+ assert type(PodpostFactory().get_podpost(post)) == Podpost
assert post in [entry, entry2]
@@ -92,7 +92,7 @@ def test_queue_favorites():
queue = QueueFactory().get_queue()
url = 'https://freakshow.fm/feed/opus/'
podcast = PodcastFactory().get_podcast(url)
- for post in (Factory().get_podpost(podcast.entry_ids_old_to_new[i]) for i in range(0, 10, 2)):
+ for post in (PodpostFactory().get_podpost(podcast.entry_ids_old_to_new[i]) for i in range(0, 10, 2)):
post.favorite = True
post.save()
for id in podcast.entry_ids_old_to_new:
--
GitLab
From e4073acdf54a9b574102a9abb8e3cd9e29bb98e4 Mon Sep 17 00:00:00 2001
From: Thilo Kogge
Date: Wed, 3 Feb 2021 17:02:33 +0100
Subject: [PATCH 08/18] moved callback from qt with paths to constants
---
python/podcast/constants.py | 61 +++++++++++++++++++++++++++++++
python/podcast/factory.py | 46 +----------------------
python/podcast/podpost.py | 3 +-
qml/components/ExternalHandler.py | 10 +++--
qml/components/FeedParser.py | 4 +-
5 files changed, 74 insertions(+), 50 deletions(-)
create mode 100644 python/podcast/constants.py
diff --git a/python/podcast/constants.py b/python/podcast/constants.py
new file mode 100644
index 0000000..8a2c90b
--- /dev/null
+++ b/python/podcast/constants.py
@@ -0,0 +1,61 @@
+import os
+import pyotherside
+from typing import Optional
+
+from podcast import util
+from podcast.singleton import Singleton
+
+
+class Constants(metaclass=Singleton):
+ """
+ manages constants supplied by qml like süecific paths etc
+ """
+ favorites_home: Optional[str]
+ media_home: Optional[str]
+ external_home: Optional[str]
+
+ object: Optional[object]
+
+ def __init__(self):
+ self.object = None
+ self.media_home = None
+ self.favorites_home = None
+ self.external_home = None
+
+
+ def init_from_qml(self, object):
+ """
+ Get QML object
+ """
+ if self.object:
+ return
+ self.object = object
+ home = os.path.expanduser("~")
+ self.media_home = os.path.join(self.get_val("musicHomeVal"), "podqast")
+ self.favorites_home = os.path.join(self.media_home, "favorites")
+ self.external_home = os.path.join(self.media_home, "external")
+
+ xdg_media_home = os.path.join(
+ "XDG_DATA_DIRS", os.path.join(home, "podqast")
+ )
+ if os.path.exists(xdg_media_home):
+ os.rename(xdg_media_home, self.media_home)
+
+ if self.get_val("allowExtVal") or self.get_val("allowFavVal"):
+ util.make_directory(self.media_home)
+ util.make_directory(self.favorites_home)
+ util.make_directory(self.external_home)
+ epath = os.path.join(self.external_home, ".nomedia")
+ open(epath, "a").close()
+
+ pyotherside.send("objectLoaded")
+
+ def get_val(self, valname):
+ """
+ Return property value by valname
+ """
+
+ try:
+ return getattr(self.object, valname)
+ except:
+ return None
\ No newline at end of file
diff --git a/python/podcast/factory.py b/python/podcast/factory.py
index 450c440..c320c95 100644
--- a/python/podcast/factory.py
+++ b/python/podcast/factory.py
@@ -7,16 +7,15 @@ Factory is a Singleton
import sys
import os
+from typing import Optional
sys.path.append("../")
from podcast.singleton import Singleton
-from podcast.cache import Cache
from podcast.store import Store
from podcast import util
-import pyotherside
class BaseFactory(metaclass=Singleton):
data_home: str
@@ -68,51 +67,10 @@ class Factory(BaseFactory):
"""
Factory for
"""
+
def __init__(self):
super().__init__()
- def init_from_qml(self, object):
- """
- Get QML object
- """
-
- try:
- if self.object:
- return
- except:
- pass
-
- self.object = object
- home = os.path.expanduser("~")
- self.media_home = os.path.join(self.get_val("musicHomeVal"), "podqast")
- self.favorites_home = os.path.join(self.media_home, "favorites")
- self.external_home = os.path.join(self.media_home, "external")
-
- xdg_media_home = os.path.join(
- "XDG_DATA_DIRS", os.path.join(home, "podqast")
- )
- if os.path.exists(xdg_media_home):
- os.rename(xdg_media_home, self.media_home)
-
- if self.get_val("allowExtVal") or self.get_val("allowFavVal"):
- util.make_directory(self.media_home)
- util.make_directory(self.favorites_home)
- util.make_directory(self.external_home)
- epath = os.path.join(self.external_home, ".nomedia")
- open(epath, "a").close()
-
- pyotherside.send("objectLoaded")
-
- def get_val(self, valname):
- """
- Return property value by valname
- """
-
- try:
- return getattr(self.object, valname)
- except:
- return None
-
def get_store(self):
"""
get the store
diff --git a/python/podcast/podpost.py b/python/podcast/podpost.py
index b012c3b..2d8698b 100644
--- a/python/podcast/podpost.py
+++ b/python/podcast/podpost.py
@@ -5,6 +5,7 @@ import datetime
import sys
from podcast.cache import Cache
+from podcast.constants import Constants
sys.path.append("../")
@@ -513,7 +514,7 @@ class Podpost:
)
tnb = re.sub(r"(?u)[^-\w.]", "", tn) + "." + ext
tnb = "".join(x for x in tnb if x.isalnum() or x in "._-()")
- topath = os.path.join(Factory().favorites_home, tnb)
+ topath = os.path.join(Constants().favorites_home, tnb)
pyotherside.send("topath: " + topath)
return topath
diff --git a/qml/components/ExternalHandler.py b/qml/components/ExternalHandler.py
index 02406a3..b2be940 100644
--- a/qml/components/ExternalHandler.py
+++ b/qml/components/ExternalHandler.py
@@ -7,6 +7,8 @@ import sys
import os
import hashlib
+from podcast.constants import Constants
+
sys.path.append("/usr/share/harbour-podqast/python")
from podcast.external import ExternalFactory
@@ -42,7 +44,7 @@ def check_new():
"""
pyotherside.send("Check new/lost audio files")
- external = Factory().external_home
+ external = Constants().external_home
if not os.path.isdir(external):
pyotherside.send("Warning: external directory does not exist!")
return
@@ -66,7 +68,7 @@ def check_new():
post.save()
exlib.insert(post.id)
exlib.save()
- wheremove = Factory().get_val("extMoveToVal")
+ wheremove = Constants().get_val("extMoveToVal")
movePost(post.id, wheremove)
pyotherside.send(
"updatesNotification",
@@ -90,7 +92,7 @@ def wait_new():
check via inotify for new files in ~/podqast/external
"""
- external = Factory().external_home
+ external = Constants().external_home
if not os.path.isdir(external):
return
@@ -123,7 +125,7 @@ def wait_new():
for event in i.event_gen(timeout_s=10, yield_nones=False):
(_, type_names, path, filename) = event
- wheremove = Factory().get_val("extMoveToVal")
+ wheremove = Constants().get_val("extMoveToVal")
if "IN_CREATE" in type_names:
filepath = os.path.join(external, filename)
if os.path.islink(filepath):
diff --git a/qml/components/FeedParser.py b/qml/components/FeedParser.py
index 39984ae..87626a2 100644
--- a/qml/components/FeedParser.py
+++ b/qml/components/FeedParser.py
@@ -9,6 +9,8 @@ import os
import time
import tarfile
+from podcast.constants import Constants
+
sys.path.append("/usr/share/harbour-podqast/python")
from podcast.podcast import PodcastFactory
@@ -49,7 +51,7 @@ def get_latest_entry(url):
def init_from_qml(object):
- Factory().init_from_qml(object)
+ Constants().init_from_qml(object)
def get_entries(url):
--
GitLab
From 5ffa76afad89617d71f4eef6ee62dbb6c05b1483 Mon Sep 17 00:00:00 2001
From: Thilo Kogge
Date: Wed, 3 Feb 2021 17:34:31 +0100
Subject: [PATCH 09/18] moved podpost and podcast save methods to persist
methods on their factories.
---
python/podcast/data_migration.py | 6 ++---
python/podcast/external.py | 4 +++-
python/podcast/inbox.py | 3 ++-
python/podcast/podcast.py | 32 ++++++++++----------------
python/podcast/podcastlist.py | 2 +-
python/podcast/podpost.py | 38 ++++++++++++-------------------
python/podcast/queue.py | 10 ++++----
qml/components/ExternalHandler.py | 4 ++--
test/test_archive.py | 4 ++--
test/test_favorites.py | 2 +-
test/test_podpost.py | 5 ++--
test/test_queue.py | 6 ++---
12 files changed, 52 insertions(+), 64 deletions(-)
diff --git a/python/podcast/data_migration.py b/python/podcast/data_migration.py
index 8239696..a9fcb12 100644
--- a/python/podcast/data_migration.py
+++ b/python/podcast/data_migration.py
@@ -100,7 +100,7 @@ def migrate_podpost_v0_v1(self: Podpost):
self.length = 0
if hasattr(self, "entry") and not self.isaudio:
self.init(self.entry, self.logo_url, self.podurl)
- self.save()
+ PodpostFactory().persist(self)
def migrate_podcast_v0_v1(self: Podcast):
@@ -121,7 +121,7 @@ def migrate_podcast_v0_v1(self: Podcast):
p2 = PodpostFactory().get_podpost(post.id)
if p2:
post = p2
- post.save()
+ PodpostFactory().persist(post)
entry_ids_new_to_old.append(post.id)
self._set_alt_feeds(self.feed)
else:
@@ -133,7 +133,7 @@ def migrate_podcast_v0_v1(self: Podcast):
self.feed = None
if old_entry_count == len(entry_ids_new_to_old):
logger.info("migration done")
- self.save()
+ PodcastFactory().persist(self)
else:
logger.error("Could not complete migration. old count: %d, new: %d", old_entry_count,
len(entry_ids_new_to_old))
diff --git a/python/podcast/external.py b/python/podcast/external.py
index d2f3ccd..dd51c6b 100644
--- a/python/podcast/external.py
+++ b/python/podcast/external.py
@@ -6,6 +6,8 @@ import sys
import time
import pyotherside
+from podcast.podpost import PodpostFactory
+
sys.path.append("../")
from podcast.singleton import Singleton
@@ -44,7 +46,7 @@ class External:
post = Factory().get_podpost(podpost)
if post.insert_date == None:
post.insert_date = time.time()
- post.save()
+ PodpostFactory().persist(post)
self.save()
pyotherside.send("got %d entries" % len(self.podposts))
diff --git a/python/podcast/inbox.py b/python/podcast/inbox.py
index aad9af7..1e62457 100644
--- a/python/podcast/inbox.py
+++ b/python/podcast/inbox.py
@@ -49,7 +49,7 @@ class Inbox:
post = PodpostFactory().get_podpost(podpost)
if post.insert_date == None:
post.insert_date = time.time()
- post.save()
+ PodpostFactory().persist(post)
pyotherside.send("Inbox element saved %d" % len(self.podposts))
self.save()
@@ -142,3 +142,4 @@ class InboxFactory(metaclass=Singleton):
return self.inbox
return self.inbox
+
diff --git a/python/podcast/podcast.py b/python/podcast/podcast.py
index 1c495a1..1bdace0 100644
--- a/python/podcast/podcast.py
+++ b/python/podcast/podcast.py
@@ -138,7 +138,7 @@ class Podcast:
break
all_episode_count += 1
post = Podpost(entry, self.url, image)
- post.save()
+ PodpostFactory().persist(post)
new_posts.append(post)
# todo: limit stuff probably broken
if limit != 0 and all_episode_count >= limit:
@@ -148,7 +148,7 @@ class Podcast:
new_post_ids = [post.id for post in new_posts]
new_post_ids.reverse()
self.entry_ids_old_to_new.extend(new_post_ids)
- self.save()
+ PodcastFactory().persist(self)
return new_posts
def __set_data_from_feed(self, feed):
@@ -253,22 +253,6 @@ class Podcast:
else:
return None
- def save(self):
- """
- Save this element
- """
- self.download_icon()
- PodcastFactory().store.store(self.url, self)
- PodcastFactory().podcastcache.store(self.url, self)
-
- def delete(self):
- """
- Remove Item from store
- """
-
- PodcastFactory().store.delete(self.url)
- PodcastFactory().podcastcache.delete(self.url)
-
def download_icon(self):
"""
Download icon
@@ -317,7 +301,7 @@ class Podcast:
pyotherside.send("refreshPost", None)
return []
- self.save()
+ PodcastFactory().persist(self)
move = self.move
if move < 0:
@@ -354,7 +338,7 @@ class Podcast:
self.move = params["move"]
self.autolimit = params["autolimit"]
self.playrate = params["playrate"]
- self.save()
+ PodcastFactory().persist(self)
def get_params(self):
"""
@@ -427,3 +411,11 @@ class PodcastFactory(BaseFactory):
PodpostFactory().delete_podpost(post)
self.podcastcache.delete(url)
self.store.delete(url)
+
+ def persist(self, podcast:Podcast):
+ self.store.store(podcast.url,podcast)
+ self.podcastcache.store(podcast.url,podcast)
+
+ def delete(self, podcast:Podcast):
+ self.store.delete(podcast.url,podcast)
+ self.podcastcache.delete(podcast.url,podcast)
diff --git a/python/podcast/podcastlist.py b/python/podcast/podcastlist.py
index 5fe15d6..b98b5c6 100644
--- a/python/podcast/podcastlist.py
+++ b/python/podcast/podcastlist.py
@@ -45,7 +45,7 @@ class PodcastList:
if podcast:
if podcast.title:
podcast.subscribed = True
- podcast.save()
+ PodcastFactory().persist(podcast)
if url not in self.podcasts:
self.podcasts.append(url)
self.save()
diff --git a/python/podcast/podpost.py b/python/podcast/podpost.py
index 2d8698b..30e390c 100644
--- a/python/podcast/podpost.py
+++ b/python/podcast/podpost.py
@@ -225,7 +225,7 @@ class Podpost:
queue = QueueFactory().get_queue()
if position:
self.position = position
- self.save()
+ PodpostFactory().persist(self)
if self.duration:
if self.position > 0:
add = ""
@@ -304,16 +304,6 @@ class Podpost:
"haschapters": haschapters,
}
- def save(self):
- """
- Save this element. If self.insert_date = None: set date
- """
-
- logger.info("storing podpost %s", self.id)
- if not self.logo_path:
- self.download_icon()
- PodpostFactory().persist(self.id, self)
-
def download_audio(self):
"""
Download the audio stuff
@@ -359,7 +349,7 @@ class Podpost:
self.percentage = 0
self.file_path = file_path
- self.save()
+ PodpostFactory().persist(self)
def download_icon(self):
"""
@@ -417,7 +407,7 @@ class Podpost:
"""
self.position = position
- self.save()
+ PodpostFactory().persist(self)
@property
def get_position(self):
@@ -434,7 +424,7 @@ class Podpost:
if not self.duration:
self.duration = duration
- self.save()
+ PodpostFactory().persist(self)
def pause(self, position):
"""
@@ -444,7 +434,7 @@ class Podpost:
if position >= 0:
self.position = position
self.state = PAUSE
- self.save()
+ PodpostFactory().persist(self)
def stop(self, position):
"""
@@ -454,7 +444,7 @@ class Podpost:
if position >= 0:
self.position = position
self.state = STOP
- self.save()
+ PodpostFactory().persist(self)
@property
def get_play_state(self):
@@ -490,7 +480,7 @@ class Podpost:
delete_file(self.file_path)
self.percentage = 0
self.file_path = None
- self.save()
+ PodpostFactory().persist(self)
def toggle_fav(self, do_download=False):
"""
@@ -533,7 +523,7 @@ class Podpost:
if self.id not in queue.podposts:
self.delete_file()
- self.save()
+ PodpostFactory().persist(self)
return self.favorite
def get_chapters(self):
@@ -546,7 +536,7 @@ class Podpost:
logger.info("setting chapter selection flags")
for chapter in self.chapters:
chapter["selected"] = True
- self.save()
+ PodpostFactory().persist(self)
return self.chapters
@@ -557,7 +547,7 @@ class Podpost:
"""
self.chapters[chapterid]["selected"] = not self.chapters[chapterid]["selected"]
- self.save()
+ PodpostFactory().persist(self)
@property
def get_fav(self):
@@ -598,6 +588,8 @@ class PodpostFactory(BaseFactory):
self.podpostcache.delete(index)
self.store.delete(index)
- def persist(self, id, self1):
- self.store.store(id,self1)
- self.podpostcache.store(id,self1)
+ def persist(self, post:Podpost):
+ if type(post) != Podpost:
+ raise ValueError("Can only persist podposts")
+ self.store.store(post.id,post)
+ self.podpostcache.store(post.id,post)
diff --git a/python/podcast/queue.py b/python/podcast/queue.py
index 7454a09..9a1e580 100644
--- a/python/podcast/queue.py
+++ b/python/podcast/queue.py
@@ -93,7 +93,7 @@ class Queue:
if post.insert_date == None:
post.insert_date = time.time()
- post.save()
+ PodpostFactory().persist(post)
self.save()
pyotherside.send("needDownload", podpost)
pyotherside.send("posplay", post.get_position)
@@ -122,7 +122,7 @@ class Queue:
if post.insert_date == None:
post.insert_date = time.time()
- post.save()
+ PodpostFactory().persist(post)
self.save()
pyotherside.send("needDownload", podpost)
@@ -148,7 +148,7 @@ class Queue:
if post.insert_date == None:
post.insert_date = time.time()
- post.save()
+ PodpostFactory().persist(post)
self.save()
pyotherside.send("needDownload", podpost)
@@ -161,13 +161,13 @@ class Queue:
post = PodpostFactory().get_podpost(podpost)
post.delete_file()
post.state = 0
- post.save()
+ PodpostFactory().persist(post)
if podpost == self.podposts[0] and len(self.podposts) > 1:
post1 = PodpostFactory().get_podpost(self.podposts[1])
pyotherside.send("setpos", post1.position)
self.podposts.remove(podpost)
else:
- PodpostFactory().get_podpost(podpost).save()
+ PodpostFactory().persist(PodpostFactory().get_podpost(podpost))
self.save()
diff --git a/qml/components/ExternalHandler.py b/qml/components/ExternalHandler.py
index b2be940..b40eee0 100644
--- a/qml/components/ExternalHandler.py
+++ b/qml/components/ExternalHandler.py
@@ -65,7 +65,7 @@ def check_new():
if fnh not in exlib.podposts:
pyotherside.send("external: " + fn + " is music")
post = Podpost.from_audio_file(fn)
- post.save()
+ PodpostFactory().persist(post)
exlib.insert(post.id)
exlib.save()
wheremove = Constants().get_val("extMoveToVal")
@@ -107,7 +107,7 @@ def wait_new():
pyotherside.send(post.title)
pyotherside.send(post.logo_url)
pyotherside.send(post.id)
- post.save()
+ PodpostFactory().persist(post)
exlib = ExternalFactory().get_external()
exlib.insert(post.id)
exlib.save()
diff --git a/test/test_archive.py b/test/test_archive.py
index b74fc3a..a12fe5e 100644
--- a/test/test_archive.py
+++ b/test/test_archive.py
@@ -60,10 +60,10 @@ def setup_archive_with_2_posts(archive):
body=read_testdata('testdata/freakshow.rss'), adding_headers=xml_headers)
podcast = Podcast('https://freakshow.fm/feed/opus/')
entry1 = podcast.get_entry(podcast.entry_ids_old_to_new[0])
- entry1.save()
+ PodpostFactory().persist(entry1)
archive.insert(entry1.id)
entry2 = podcast.get_entry(podcast.entry_ids_old_to_new[1])
- entry2.save()
+ PodpostFactory().persist(entry2)
archive.insert(entry2.id)
return entry1, entry2
diff --git a/test/test_favorites.py b/test/test_favorites.py
index 9ad400d..c564923 100644
--- a/test/test_favorites.py
+++ b/test/test_favorites.py
@@ -28,7 +28,7 @@ def test_queue_favorites():
assert len(list(archive.get_podposts())) == 0
for post in fav_posts:
post.favorite = True
- post.save()
+ PodpostFactory().persist(post)
archive.insert(post.id)
archive.save()
assert len(favorite.get_queue_favorites()) == 0
diff --git a/test/test_podpost.py b/test/test_podpost.py
index b138568..791ecdb 100644
--- a/test/test_podpost.py
+++ b/test/test_podpost.py
@@ -13,7 +13,8 @@ sys.path.append("../python")
from podcast.factory import Factory
from podcast.podcast import Podcast
-from podcast.podpost import Podpost
+from podcast.podpost import Podpost, PodpostFactory
+
@httpretty.activate
def test_podpost_save():
@@ -27,7 +28,7 @@ def test_podpost_save():
p = Podcast('https://freakshow.fm/feed/opus/')
e = p.get_latest_entry()
id1 = e.id
- e.save()
+ PodpostFactory().persist(e)
n = Factory().get_store().get(e.id)
id2 = n.id
assert type(n) == Podpost
diff --git a/test/test_queue.py b/test/test_queue.py
index 919aa37..e39d5fb 100644
--- a/test/test_queue.py
+++ b/test/test_queue.py
@@ -51,11 +51,11 @@ def test_insert_top():
e = p.get_entry(p.entry_ids_old_to_new[1])
e2 = p.get_entry(p.entry_ids_old_to_new[0])
- e.save()
+ PodpostFactory().persist(e)
q.insert_top(e.id)
assert q.podposts[0] == e.id
- e2.save()
+ PodpostFactory().persist(e2)
q.insert_top(e2.id)
assert q.podposts[0] == e2.id
@@ -94,7 +94,7 @@ def test_queue_favorites():
podcast = PodcastFactory().get_podcast(url)
for post in (PodpostFactory().get_podpost(podcast.entry_ids_old_to_new[i]) for i in range(0, 10, 2)):
post.favorite = True
- post.save()
+ PodpostFactory().persist(post)
for id in podcast.entry_ids_old_to_new:
queue.insert_bottom(id)
assert len(queue.podposts) == 20
--
GitLab
From 926fbbec700579e08d47c9deaac7078cf516929f Mon Sep 17 00:00:00 2001
From: Thilo Kogge
Date: Wed, 3 Feb 2021 17:36:42 +0100
Subject: [PATCH 10/18] removed useless print statement
---
python/podcast/util.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/python/podcast/util.py b/python/podcast/util.py
index 2bcaee1..8513b41 100644
--- a/python/podcast/util.py
+++ b/python/podcast/util.py
@@ -70,7 +70,6 @@ def s_to_hr(secs):
hours = int(secs / 3600)
hr = str(hours) + "h"
secs = secs - hours * 3600
- print(secs)
if secs >= 59:
hr = hr + str(int(secs / 60)) + "m"
--
GitLab
From b646a30c282b8527c284200a60ea9576a77c650c Mon Sep 17 00:00:00 2001
From: Thilo Kogge
Date: Wed, 3 Feb 2021 17:46:07 +0100
Subject: [PATCH 11/18] fixed linter errors
---
python/podcast/data_migration.py | 4 ++--
python/podcast/factory.py | 1 -
python/podcast/podcast.py | 4 +---
test/test_podpost.py | 2 +-
4 files changed, 4 insertions(+), 7 deletions(-)
diff --git a/python/podcast/data_migration.py b/python/podcast/data_migration.py
index a9fcb12..b103050 100644
--- a/python/podcast/data_migration.py
+++ b/python/podcast/data_migration.py
@@ -48,6 +48,7 @@ def run_migrations():
set_versionnumber(1)
pyotherside.send("migrationDone")
+
def get_versionnumber() -> int:
versionfilepath = get_versionfile_path()
if os.path.isfile(versionfilepath):
@@ -82,7 +83,7 @@ def migrate_archive_v0_v1():
post = PodpostFactory().get_podpost(postid)
if not post:
continue
- if hasattr(post, "insert_date") and post.insert_date:
+ if hasattr(post, "insert_date") and post.insert_date:
archive_entry.insert_date = post.insert_date
else:
archive_entry.insert_date = datetime.datetime.now()
@@ -106,7 +107,6 @@ def migrate_podpost_v0_v1(self: Podpost):
def migrate_podcast_v0_v1(self: Podcast):
logger.info("migrating podcast '%s' to new format version 1", self.title)
try:
- from podcast.factory import Factory
if self.logo_path:
image = self.logo_path
else:
diff --git a/python/podcast/factory.py b/python/podcast/factory.py
index c320c95..0f0053f 100644
--- a/python/podcast/factory.py
+++ b/python/podcast/factory.py
@@ -7,7 +7,6 @@ Factory is a Singleton
import sys
import os
-from typing import Optional
sys.path.append("../")
diff --git a/python/podcast/podcast.py b/python/podcast/podcast.py
index 1bdace0..c2314e0 100644
--- a/python/podcast/podcast.py
+++ b/python/podcast/podcast.py
@@ -7,11 +7,10 @@ from typing import List, Dict, Optional, Generator
from feedparser import FeedParserDict
-from podcast.factory import Factory, BaseFactory
+from podcast.factory import BaseFactory
sys.path.append("/usr/share/podqast/python")
-from podcast.singleton import Singleton
from podcast.cache import Cache
from podcast.store import Store
from podcast.podpost import Podpost, PodpostFactory
@@ -238,7 +237,6 @@ class Podcast:
"""
Return a list of entries
"""
- from podcast.factory import Factory
logger.debug("Podcast get_entries started.")
for id in self.entry_ids_old_to_new:
yield PodpostFactory().get_podpost(id).get_data()
diff --git a/test/test_podpost.py b/test/test_podpost.py
index 791ecdb..97ff043 100644
--- a/test/test_podpost.py
+++ b/test/test_podpost.py
@@ -29,7 +29,7 @@ def test_podpost_save():
e = p.get_latest_entry()
id1 = e.id
PodpostFactory().persist(e)
- n = Factory().get_store().get(e.id)
+ n = PodpostFactory().get_podpost(e.id)
id2 = n.id
assert type(n) == Podpost
assert id1 == id2
--
GitLab
From a9908a994954741c097e640128efcaf67ef3bd69 Mon Sep 17 00:00:00 2001
From: Thilo Kogge
Date: Wed, 3 Feb 2021 17:49:20 +0100
Subject: [PATCH 12/18] fixed linter errors
---
qml/components/ArchiveHandler.py | 1 -
qml/components/ExternalHandler.py | 1 -
qml/components/InboxHandler.py | 1 -
qml/components/QueueHandler.py | 1 -
4 files changed, 4 deletions(-)
diff --git a/qml/components/ArchiveHandler.py b/qml/components/ArchiveHandler.py
index c9301fa..54ffbd1 100644
--- a/qml/components/ArchiveHandler.py
+++ b/qml/components/ArchiveHandler.py
@@ -10,7 +10,6 @@ from podcast.podpost import PodpostFactory
sys.path.append("/usr/share/harbour-podqast/python")
from podcast.archive import ArchiveFactory
-from podcast.factory import Factory
import logging
logger = logging.getLogger(__name__)
diff --git a/qml/components/ExternalHandler.py b/qml/components/ExternalHandler.py
index b40eee0..267e832 100644
--- a/qml/components/ExternalHandler.py
+++ b/qml/components/ExternalHandler.py
@@ -16,7 +16,6 @@ from podcast.inbox import InboxFactory
from podcast.archive import ArchiveFactory
from podcast.queue import QueueFactory
-from podcast.factory import Factory
from podcast.podpost import Podpost, PodpostFactory
import inotify.adapters
import mutagen
diff --git a/qml/components/InboxHandler.py b/qml/components/InboxHandler.py
index a315be6..26313aa 100644
--- a/qml/components/InboxHandler.py
+++ b/qml/components/InboxHandler.py
@@ -11,7 +11,6 @@ sys.path.append("/usr/share/harbour-podqast/python")
from podcast.inbox import InboxFactory
from podcast.queue import QueueFactory
-from podcast.factory import Factory
def get_inbox_posts(podurl=None):
diff --git a/qml/components/QueueHandler.py b/qml/components/QueueHandler.py
index 59e10e7..d224a6a 100644
--- a/qml/components/QueueHandler.py
+++ b/qml/components/QueueHandler.py
@@ -10,7 +10,6 @@ from podcast.podpost import PodpostFactory
sys.path.append("/usr/share/harbour-podqast/python")
from podcast.queue import QueueFactory
-from podcast.factory import Factory
from podcast.archive import ArchiveFactory
--
GitLab
From 940005900b15d0a54d6d02bfb4c2ea70c9227d83 Mon Sep 17 00:00:00 2001
From: Thilo Kogge
Date: Wed, 3 Feb 2021 20:29:07 +0100
Subject: [PATCH 13/18] moved common queue data operations into queue factory
---
python/podcast/queue.py | 12 +++++++++++-
qml/components/QueueHandler.py | 15 ++++++---------
2 files changed, 17 insertions(+), 10 deletions(-)
diff --git a/python/podcast/queue.py b/python/podcast/queue.py
index 9a1e580..fd8cd9a 100644
--- a/python/podcast/queue.py
+++ b/python/podcast/queue.py
@@ -5,10 +5,12 @@ It instanciates Podposts via Factory if needed.
import sys
import os
+from typing import Iterator
+
import pyotherside
import time
-from podcast.podpost import PodpostFactory
+from podcast.podpost import PodpostFactory, Podpost
sys.path.append("../")
@@ -323,3 +325,11 @@ class QueueFactory(metaclass=Singleton):
self.queue = Queue()
return self.queue
+
+ def get_podposts_objects(self)->Iterator[Podpost]:
+ for postid in self.get_queue().podposts:
+ yield PodpostFactory().get_podpost(postid)
+
+ def get_first_podpost_object(self):
+ return next(self.get_podposts_objects(), None)
+
diff --git a/qml/components/QueueHandler.py b/qml/components/QueueHandler.py
index d224a6a..0daf5fa 100644
--- a/qml/components/QueueHandler.py
+++ b/qml/components/QueueHandler.py
@@ -19,10 +19,8 @@ def get_queue_posts(moved=""):
"""
entries = []
- queue = QueueFactory().get_queue()
- for post in queue.get_podposts():
- entry = PodpostFactory().get_podpost(post)
+ for entry in QueueFactory().get_podposts_objects():
edata = entry.get_data()
edata["moved"] = edata["id"] == moved
entries.append(edata)
@@ -40,12 +38,11 @@ def get_first_entry():
Return the data of the first entry
"""
- queue = QueueFactory().get_queue()
- if len(queue.podposts) < 1:
- return None
- pyotherside.send(
- "firstentry", PodpostFactory().get_podpost(queue.podposts[0]).get_data()
- )
+ post = QueueFactory().get_first_podpost_object()
+ if post is not None:
+ pyotherside.send(
+ "firstentry", post.get_data()
+ )
def queue_insert_top(id, doplay=False):
--
GitLab
From 152a36f1cfcfc7452b75a6711f55c84fc11cdb38 Mon Sep 17 00:00:00 2001
From: Thilo Kogge
Date: Wed, 3 Feb 2021 21:21:29 +0100
Subject: [PATCH 14/18] moved iteration and selection logic into the respective
classes.
---
python/podcast/archive.py | 6 ++++--
python/podcast/external.py | 4 ++++
python/podcast/favorite.py | 31 ++-----------------------------
python/podcast/inbox.py | 9 ++++++++-
python/podcast/podcast.py | 22 +++++++++++-----------
python/podcast/podcastlist.py | 29 ++++++++++++++++-------------
python/podcast/podpost.py | 6 +++---
python/podcast/queue.py | 22 +++++++++++++++++++++-
qml/components/ArchiveHandler.py | 3 +--
qml/components/ExternalHandler.py | 10 ++++------
qml/components/FeedParser.py | 9 +++------
qml/components/InboxHandler.py | 14 ++++----------
qml/components/QueueHandler.py | 8 ++++----
test/test_archive.py | 17 ++++++++++++++++-
test/test_queue.py | 2 ++
15 files changed, 103 insertions(+), 89 deletions(-)
diff --git a/python/podcast/archive.py b/python/podcast/archive.py
index 6cb950c..e432a41 100644
--- a/python/podcast/archive.py
+++ b/python/podcast/archive.py
@@ -70,11 +70,13 @@ class Archive:
for archive_entry in sorted(self._archive_entries, key=lambda e: e.insert_date, reverse=True):
yield archive_entry.podpost
- def get_podpost_objects(self, url_filter=None) -> Iterator[Podpost]:
+ def get_podpost_objects(self, url_filter=None, filter_favorite=False) -> Iterator[Podpost]:
for id in self.get_podposts():
entry: Podpost = PodpostFactory().get_podpost(id)
if entry:
- if not url_filter or (url_filter and entry.podurl == url_filter):
+ if ((not url_filter or (url_filter and entry.podurl == url_filter)) and
+ (not filter_favorite or entry.favorite)
+ ):
yield entry
def remove_podpost(self, podpost):
diff --git a/python/podcast/external.py b/python/podcast/external.py
index dd51c6b..1557c75 100644
--- a/python/podcast/external.py
+++ b/python/podcast/external.py
@@ -60,6 +60,10 @@ class External:
for podpost in self.podposts:
yield podpost
+ def get_podposts_objects(self):
+ for post_id in self.get_podposts():
+ yield PodpostFactory().get_podpost(post_id)
+
def remove_podpost(self, podpost):
"""
Remove a podpost from archive
diff --git a/python/podcast/favorite.py b/python/podcast/favorite.py
index db481cd..6b66df2 100644
--- a/python/podcast/favorite.py
+++ b/python/podcast/favorite.py
@@ -1,6 +1,3 @@
-from podcast.podpost import PodpostFactory
-
-
def get_queue_favorites(podurl=None):
"""
Return a list of all favorites posts from queue
@@ -8,19 +5,8 @@ def get_queue_favorites(podurl=None):
from podcast.queue import QueueFactory
- posts = []
+ return list(QueueFactory().get_favorites(podurl))
- queue = QueueFactory().get_queue()
- for post in queue.get_podposts():
- p = PodpostFactory().get_podpost(post)
- if p.favorite:
- if podurl:
- if p.podurl == podurl:
- posts.append(p)
- else:
- posts.append(p)
-
- return posts
def append_archive_favorites(posts, podurl=None):
@@ -31,21 +17,8 @@ def append_archive_favorites(posts, podurl=None):
from podcast.archive import ArchiveFactory
archive = ArchiveFactory().get_archive()
+ return list(archive.get_podpost_objects(url_filter=podurl,filter_favorite=True))
- for post in archive.get_podposts():
- p = PodpostFactory().get_podpost(post)
- try:
- if p.favorite:
- if p not in posts:
- if podurl:
- if p.podurl == podurl:
- posts.append(p)
- else:
- posts.append(p)
- except:
- pass
-
- return posts
def get_favorites(podurl=None):
diff --git a/python/podcast/inbox.py b/python/podcast/inbox.py
index 1e62457..30f8cf0 100644
--- a/python/podcast/inbox.py
+++ b/python/podcast/inbox.py
@@ -5,7 +5,7 @@ The inbox queue. This also uses a Factory for instancing
import sys
import time
-from podcast.podpost import PodpostFactory
+from podcast.podpost import PodpostFactory, Podpost
sys.path.append("../")
@@ -61,6 +61,13 @@ class Inbox:
for podpost in self.podposts:
yield podpost
+ def get_podposts_objects(self, podurl = None):
+ for post_id in self.get_podposts():
+ post:Podpost = PodpostFactory().get_podpost(post_id)
+ if not podurl or (podurl and post.podurl == podurl):
+ yield post
+
+
def remove(self, podpost):
"""
Remove a podpost from archive
diff --git a/python/podcast/podcast.py b/python/podcast/podcast.py
index c2314e0..0d1a832 100644
--- a/python/podcast/podcast.py
+++ b/python/podcast/podcast.py
@@ -3,7 +3,7 @@ Podcast
"""
import sys
-from typing import List, Dict, Optional, Generator
+from typing import List, Dict, Optional, Generator, Iterator
from feedparser import FeedParserDict
@@ -111,10 +111,7 @@ class Podcast:
logger.debug("fetching episodes for %s", self.title)
- if self.logo_path:
- image = self.logo_path
- else:
- image = self.logo_url
+ image = self.logo()
old_first_id = self.entry_ids_old_to_new[-1] if len(self.entry_ids_old_to_new) > 0 else ""
@@ -150,6 +147,13 @@ class Podcast:
PodcastFactory().persist(self)
return new_posts
+ def logo(self):
+ if self.logo_path:
+ image = self.logo_path
+ else:
+ image = self.logo_url
+ return image
+
def __set_data_from_feed(self, feed):
logger.debug("setting instance values from feed")
self.__set_times_from_feeds(feed)
@@ -196,17 +200,13 @@ class Podcast:
description = description[:160] + "..."
self.download_icon()
- if self.logo_path:
- image = self.logo_path
- else:
- image = self.logo_url
return {
"url": self.url,
"title": title,
"description": description,
"descriptionfull": descriptionfull,
- "logo_url": image,
+ "logo_url": self.logo(),
}
def _set_alt_feeds(self, feed):
@@ -233,7 +233,7 @@ class Podcast:
entry = PodpostFactory().get_podpost(id)
return entry
- def get_entries(self) -> Generator[dict, None, None]:
+ def get_entries(self) -> Iterator[Podpost]:
"""
Return a list of entries
"""
diff --git a/python/podcast/podcastlist.py b/python/podcast/podcastlist.py
index b98b5c6..3083752 100644
--- a/python/podcast/podcastlist.py
+++ b/python/podcast/podcastlist.py
@@ -3,13 +3,13 @@ List of subscribed podcasts
"""
import sys
-from typing import List
+from typing import List, Iterator
sys.path.append("../")
from podcast.singleton import Singleton
from podcast.factory import Factory
-from podcast.podcast import PodcastFactory
+from podcast.podcast import PodcastFactory, Podcast
from podcast import util
from podcast import gpodder_import
import pyotherside
@@ -63,15 +63,19 @@ class PodcastList:
pc.delete()
self.save()
- def get_podcasts(self) -> str:
+ def get_podcasts(self) -> Iterator[str]:
"""
return the list of subscribed podcasts
"""
- for podcast in self.podcasts:
- pc = PodcastFactory().get_podcast(podcast)
+ for podcast in self.get_podcasts_objects():
+ yield podcast.url
+
+ def get_podcasts_objects(self, subscribed_only=True) -> Iterator[Podcast]:
+ for podcast_url in self.podcasts:
+ pc = PodcastFactory().get_podcast(podcast_url)
if pc:
- if hasattr(pc, "subscribed") and pc.subscribed:
- yield podcast
+ if not subscribed_only or hasattr(pc, "subscribed") and pc.subscribed:
+ yield pc
def refresh(self, moveto, limit=0):
"""
@@ -80,16 +84,15 @@ class PodcastList:
pllen = len(self.podcasts)
count = 0
- for podcast in self.podcasts:
- pc = PodcastFactory().get_podcast(podcast)
- if pc:
+ for podcast in self.get_podcasts_objects(subscribed_only=False):
+ if podcast:
try:
- if pc.subscribed:
- for post in pc.refresh(moveto, limit):
+ if podcast.subscribed:
+ for post in podcast.refresh(moveto, limit):
yield post
except:
logger.exception(
- "podcast refresh failed for %s." % pc.title
+ "podcast refresh failed for %s." % podcast.title
)
count += 1
diff --git a/python/podcast/podpost.py b/python/podcast/podpost.py
index 30e390c..42be1cb 100644
--- a/python/podcast/podpost.py
+++ b/python/podcast/podpost.py
@@ -229,7 +229,7 @@ class Podpost:
if self.duration:
if self.position > 0:
add = ""
- if self.state == PLAY and self.id == queue.podposts[0]:
+ if self.state == PLAY and self.id == queue.get_top_id():
add = " playing"
else:
add = " remaining"
@@ -250,7 +250,7 @@ class Podpost:
from podcast.queue import QueueFactory
queue = QueueFactory().get_queue()
- inqueue = self.id in queue.podposts
+ inqueue = self.id in queue.get_podposts()
timestring = self.get_hr_time()
@@ -520,7 +520,7 @@ class Podpost:
if self.file_path:
queue = QueueFactory().get_queue()
delete_file(get_topath())
- if self.id not in queue.podposts:
+ if self.id not in queue.get_podposts_ids():
self.delete_file()
PodpostFactory().persist(self)
diff --git a/python/podcast/queue.py b/python/podcast/queue.py
index fd8cd9a..3a35beb 100644
--- a/python/podcast/queue.py
+++ b/python/podcast/queue.py
@@ -258,7 +258,17 @@ class Queue:
"""
for podpost in self.podposts:
- yield (podpost)
+ yield podpost
+
+ def get_top_id(self):
+ return self._get_top().id
+
+ def get_podposts_ids(self):
+ for p in self.get_podposts():
+ yield p.id
+
+ def count(self):
+ return len(self.podposts)
def play(self):
"""
@@ -333,3 +343,13 @@ class QueueFactory(metaclass=Singleton):
def get_first_podpost_object(self):
return next(self.get_podposts_objects(), None)
+ def get_favorites(self, podurl)->Iterator[Podpost]:
+ for post in self.get_podposts_objects():
+ if post.favorite:
+ if podurl:
+ if post.podurl == podurl:
+ yield post
+ else:
+ yield post
+
+
diff --git a/qml/components/ArchiveHandler.py b/qml/components/ArchiveHandler.py
index 54ffbd1..fba7763 100644
--- a/qml/components/ArchiveHandler.py
+++ b/qml/components/ArchiveHandler.py
@@ -32,8 +32,7 @@ def get_archive_pod_data():
archive = ArchiveFactory().get_archive()
- for post in archive.get_podposts():
- entry = PodpostFactory().get_podpost(post)
+ for entry in archive.get_podpost_objects():
if entry.podurl in entries:
entries[entry.podurl]["count"] += 1
else:
diff --git a/qml/components/ExternalHandler.py b/qml/components/ExternalHandler.py
index 267e832..ade7117 100644
--- a/qml/components/ExternalHandler.py
+++ b/qml/components/ExternalHandler.py
@@ -61,7 +61,7 @@ def check_new():
os.path.join(external, f).encode()
).hexdigest()
mfiles.append(fnh)
- if fnh not in exlib.podposts:
+ if fnh not in exlib.get_podposts():
pyotherside.send("external: " + fn + " is music")
post = Podpost.from_audio_file(fn)
PodpostFactory().persist(post)
@@ -79,7 +79,7 @@ def check_new():
except:
pyotherside.send("File does not exist")
- for f in exlib.podposts:
+ for f in exlib.get_podposts():
pyotherside.send("we are on file %s" % f)
if f not in mfiles:
exlib.remove_podpost(f)
@@ -169,9 +169,8 @@ def get_external_posts():
entries = []
external = ExternalFactory().get_external()
- for post in external.get_podposts():
+ for entry in external.get_podposts_objects():
pyotherside.send("podposts loop")
- entry = PodpostFactory().get_podpost(post)
entries.append(entry.get_data())
pyotherside.send("after py external")
# entries.sort(key = lambda r: r["edate"], reverse=True)
@@ -186,8 +185,7 @@ def get_external_pod_data():
external = ExternalFactory().get_external()
- for post in external.get_podposts():
- entry = PodpostFactory().get_podpost(post)
+ for entry in external.get_podposts_objects():
if entry.podurl in entries:
entries[entry.podurl]["count"] += 1
else:
diff --git a/qml/components/FeedParser.py b/qml/components/FeedParser.py
index 87626a2..21ac64a 100644
--- a/qml/components/FeedParser.py
+++ b/qml/components/FeedParser.py
@@ -87,8 +87,7 @@ def get_podcasts():
podcasts = []
pclist = PodcastListFactory().get_podcast_list()
- for podcast in pclist.get_podcasts():
- pc = PodcastFactory().get_podcast(podcast)
+ for pc in pclist.get_podcasts_objects():
podcasts.append(pc.feedinfo())
pyotherside.send("podcastslist", podcasts)
@@ -101,8 +100,7 @@ def get_podcastscache():
pclist = PodcastListFactory().get_podcast_list()
- for podcast in pclist.get_podcasts():
- PodcastFactory().get_podcast(podcast)
+ list(pclist.get_podcasts_objects())
pyotherside.send("podcast cache ready")
@@ -284,8 +282,7 @@ def write_opml():
podcasts = []
pclist = PodcastListFactory().get_podcast_list()
- for podcast in pclist.get_podcasts():
- pc = PodcastFactory().get_podcast(podcast)
+ for pc in pclist.get_podcasts_objects():
podcasts.append(
{"name": pc.title, "xml_url": pc.url, "html_url": pc.link}
)
diff --git a/qml/components/InboxHandler.py b/qml/components/InboxHandler.py
index 26313aa..aa527b5 100644
--- a/qml/components/InboxHandler.py
+++ b/qml/components/InboxHandler.py
@@ -21,15 +21,10 @@ def get_inbox_posts(podurl=None):
entries = []
inbox = InboxFactory().get_inbox()
- pyotherside.send("len Inbox %d" % len(inbox.podposts))
+ pyotherside.send("len Inbox %d" % len(inbox.get_podposts()))
- for post in inbox.get_podposts():
- entry = PodpostFactory().get_podpost(post)
- if podurl:
- if entry.podurl == podurl:
- entries.append(entry.get_data())
- else:
- entries.append(entry.get_data())
+ for entry in inbox.get_podposts_objects(podurl=podurl):
+ entries.append(entry.get_data())
entries.sort(key=lambda r: r["date"], reverse=True)
pyotherside.send("createInboxList", entries)
@@ -43,8 +38,7 @@ def get_inbox_pod_data():
inbox = InboxFactory().get_inbox()
- for post in inbox.get_podposts():
- entry = PodpostFactory().get_podpost(post)
+ for entry in inbox.get_podposts_objects():
if entry.podurl in entries:
entries[entry.podurl]["count"] += 1
else:
diff --git a/qml/components/QueueHandler.py b/qml/components/QueueHandler.py
index 0daf5fa..4297745 100644
--- a/qml/components/QueueHandler.py
+++ b/qml/components/QueueHandler.py
@@ -148,7 +148,7 @@ def queue_to_archive(id):
queue = QueueFactory().get_queue()
archive = ArchiveFactory().get_archive()
- if queue.podposts[0] == id:
+ if queue.get_top_id() == id:
pyotherside.send("stopping")
queue.remove(id)
archive.insert(id)
@@ -162,7 +162,7 @@ def queue_top_to_archive():
"""
queue = QueueFactory().get_queue()
- queue_to_archive(queue.podposts[0])
+ queue_to_archive(queue.get_top_id())
queue_play()
@@ -191,9 +191,9 @@ def queue_hr_time(position):
"""
queue = QueueFactory().get_queue()
- if len(queue.podposts) > 0:
+ if queue.count() > 0:
pyotherside.send(
- "hrtime", queue.podposts[0], queue.get_hr_time(position)
+ "hrtime", queue.get_top_id(), queue.get_hr_time(position)
)
diff --git a/test/test_archive.py b/test/test_archive.py
index a12fe5e..0586057 100644
--- a/test/test_archive.py
+++ b/test/test_archive.py
@@ -12,7 +12,6 @@ from test.test_podcast import read_testdata, xml_headers
sys.path.append("../python")
from podcast.archive import ArchiveFactory, Archive
-from podcast.factory import Factory
from podcast.podcast import Podcast
from podcast.podpost import Podpost, PodpostFactory
@@ -80,4 +79,20 @@ def test_get_archives():
assert type(post) == str
assert type(PodpostFactory().get_podpost(post)) == Podpost
count += 1
+ posts = list(a.get_podpost_objects())
+ assert len(posts) == 2
+ for post in posts:
+ assert type(post) == Podpost
+ assert len(list(a.get_podpost_objects(filter_favorite=True))) == 0
+ assert len(list(a.get_podpost_objects(url_filter="http://i.am.wrong"))) == 0
+ assert len(list(a.get_podpost_objects(url_filter="http://i.am.wrong",filter_favorite=True))) == 0
+ assert len(list(a.get_podpost_objects(url_filter="https://freakshow.fm/feed/opus/"))) == 2
+ assert len(list(a.get_podpost_objects(url_filter="https://freakshow.fm/feed/opus/",filter_favorite=True))) == 0
+ for post in a.get_podpost_objects():
+ post.favorite = True
+ PodpostFactory().persist(post)
+ assert len(list(a.get_podpost_objects(url_filter="https://freakshow.fm/feed/opus/",filter_favorite=True))) == 2
+ assert len(list(a.get_podpost_objects(filter_favorite=True))) == 2
+ assert len(list(a.get_podpost_objects(url_filter="http://i.am.wrong",filter_favorite=True))) == 0
+
assert count == 2
diff --git a/test/test_queue.py b/test/test_queue.py
index e39d5fb..8cc3a87 100644
--- a/test/test_queue.py
+++ b/test/test_queue.py
@@ -7,6 +7,7 @@ import sys
import httpretty
from httpretty import HTTPretty
+from test import cleanup_queue
from test.test_podcast import read_testdata, xml_headers
sys.path.append("../python")
@@ -68,6 +69,7 @@ def test_get_podposts():
"""
Test listing of podposts
"""
+ cleanup_queue()
queue = QueueFactory().get_queue()
podcast = PodcastFactory().get_podcast('https://freakshow.fm/feed/opus/')
--
GitLab
From 9167a449e22d8a316867b6a6c4f3ef7f51f28fde Mon Sep 17 00:00:00 2001
From: Thilo Kogge
Date: Thu, 4 Feb 2021 12:24:08 +0100
Subject: [PATCH 15/18] fixed linter errors
---
python/podcast/podcast.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/python/podcast/podcast.py b/python/podcast/podcast.py
index 0d1a832..ad5f437 100644
--- a/python/podcast/podcast.py
+++ b/python/podcast/podcast.py
@@ -3,7 +3,7 @@ Podcast
"""
import sys
-from typing import List, Dict, Optional, Generator, Iterator
+from typing import List, Dict, Optional, Iterator
from feedparser import FeedParserDict
--
GitLab
From e8426259d9725fef5eb3d9c4f6d72bc289698805 Mon Sep 17 00:00:00 2001
From: Thilo Kogge
Date: Thu, 4 Feb 2021 12:28:27 +0100
Subject: [PATCH 16/18] fixed linter errors
---
qml/components/ArchiveHandler.py | 2 --
qml/components/ExternalHandler.py | 2 +-
qml/components/FavoriteHandler.py | 2 +-
qml/components/FeedParser.py | 2 +-
qml/components/InboxHandler.py | 2 --
qml/components/QueueHandler.py | 2 +-
6 files changed, 4 insertions(+), 8 deletions(-)
diff --git a/qml/components/ArchiveHandler.py b/qml/components/ArchiveHandler.py
index fba7763..7d0673d 100644
--- a/qml/components/ArchiveHandler.py
+++ b/qml/components/ArchiveHandler.py
@@ -5,8 +5,6 @@ import pyotherside
import threading
import sys
-from podcast.podpost import PodpostFactory
-
sys.path.append("/usr/share/harbour-podqast/python")
from podcast.archive import ArchiveFactory
diff --git a/qml/components/ExternalHandler.py b/qml/components/ExternalHandler.py
index ade7117..72e0075 100644
--- a/qml/components/ExternalHandler.py
+++ b/qml/components/ExternalHandler.py
@@ -7,10 +7,10 @@ import sys
import os
import hashlib
-from podcast.constants import Constants
sys.path.append("/usr/share/harbour-podqast/python")
+from podcast.constants import Constants
from podcast.external import ExternalFactory
from podcast.inbox import InboxFactory
from podcast.archive import ArchiveFactory
diff --git a/qml/components/FavoriteHandler.py b/qml/components/FavoriteHandler.py
index 2f686e9..84eb2da 100644
--- a/qml/components/FavoriteHandler.py
+++ b/qml/components/FavoriteHandler.py
@@ -5,9 +5,9 @@ import pyotherside
import threading
import sys
-from podcast.podpost import PodpostFactory
sys.path.append("/usr/share/harbour-podqast/python")
+from podcast.podpost import PodpostFactory
import podcast.favorite as favorite
def toggle_favorite(podpost, do_download=False):
diff --git a/qml/components/FeedParser.py b/qml/components/FeedParser.py
index 21ac64a..b732145 100644
--- a/qml/components/FeedParser.py
+++ b/qml/components/FeedParser.py
@@ -9,10 +9,10 @@ import os
import time
import tarfile
-from podcast.constants import Constants
sys.path.append("/usr/share/harbour-podqast/python")
+from podcast.constants import Constants
from podcast.podcast import PodcastFactory
from podcast.podcastlist import PodcastListFactory
from podcast.queue import QueueFactory
diff --git a/qml/components/InboxHandler.py b/qml/components/InboxHandler.py
index aa527b5..b5abb2a 100644
--- a/qml/components/InboxHandler.py
+++ b/qml/components/InboxHandler.py
@@ -5,8 +5,6 @@ import pyotherside
import threading
import sys
-from podcast.podpost import PodpostFactory
-
sys.path.append("/usr/share/harbour-podqast/python")
from podcast.inbox import InboxFactory
diff --git a/qml/components/QueueHandler.py b/qml/components/QueueHandler.py
index 4297745..0783249 100644
--- a/qml/components/QueueHandler.py
+++ b/qml/components/QueueHandler.py
@@ -5,10 +5,10 @@ import pyotherside
import threading
import sys
-from podcast.podpost import PodpostFactory
sys.path.append("/usr/share/harbour-podqast/python")
+from podcast.podpost import PodpostFactory
from podcast.queue import QueueFactory
from podcast.archive import ArchiveFactory
--
GitLab
From bcbf178a5a5a5c4bab6875018797656a3952c7da Mon Sep 17 00:00:00 2001
From: Thilo Kogge
Date: Fri, 5 Feb 2021 18:07:58 +0100
Subject: [PATCH 17/18] extracted more data access logic into factories
---
python/podcast/podcast.py | 14 +++++++-------
python/podcast/podpost.py | 40 +++++++++++++++++++++++++++++++--------
2 files changed, 39 insertions(+), 15 deletions(-)
diff --git a/python/podcast/podcast.py b/python/podcast/podcast.py
index ad5f437..575d13a 100644
--- a/python/podcast/podcast.py
+++ b/python/podcast/podcast.py
@@ -134,13 +134,13 @@ class Podcast:
break
all_episode_count += 1
post = Podpost(entry, self.url, image)
- PodpostFactory().persist(post)
new_posts.append(post)
# todo: limit stuff probably broken
if limit != 0 and all_episode_count >= limit:
if not supress_limit_notification:
pyotherside.send("apperror", "Auto post limit reached for %s!" % self.title)
break
+ PodpostFactory().persist_bulk(new_posts)
new_post_ids = [post.id for post in new_posts]
new_post_ids.reverse()
self.entry_ids_old_to_new.extend(new_post_ids)
@@ -230,16 +230,16 @@ class Podcast:
Get an entry from podcast by id
"""
- entry = PodpostFactory().get_podpost(id)
- return entry
+ return PodpostFactory().get_podpost(id)
+
def get_entries(self) -> Iterator[Podpost]:
"""
Return a list of entries
"""
logger.debug("Podcast get_entries started.")
- for id in self.entry_ids_old_to_new:
- yield PodpostFactory().get_podpost(id).get_data()
+ for post in PodpostFactory().get_podcast_posts(self):
+ yield post.get_data()
def get_latest_entry(self) -> Optional[Podpost]:
"""
@@ -251,6 +251,7 @@ class Podcast:
else:
return None
+ # todo handle download icon during init
def download_icon(self):
"""
Download icon
@@ -405,8 +406,7 @@ class PodcastFactory(BaseFactory):
logger.info("deleting podcast and entries %s", url)
to_delete = self.get_podcast(url)
if to_delete != None:
- for post in to_delete.entry_ids_old_to_new:
- PodpostFactory().delete_podpost(post)
+ PodpostFactory().delete_all_from_podcast(self)
self.podcastcache.delete(url)
self.store.delete(url)
diff --git a/python/podcast/podpost.py b/python/podcast/podpost.py
index 42be1cb..d01ad60 100644
--- a/python/podcast/podpost.py
+++ b/python/podcast/podpost.py
@@ -15,7 +15,7 @@ from urllib.parse import urlparse
import html2text
from email.utils import mktime_tz, parsedate_tz
from calendar import timegm
-from typing import Optional, List
+from typing import Optional, List, Iterator
from podcast.factory import Factory, BaseFactory
from podcast.util import s_to_hr, tx_to_s, dl_from_url, dl_from_url_progress
@@ -43,7 +43,7 @@ class Podpost:
title: str
percentage: float
position: int
- isaudio: bool # if the post comes from the external folder
+ isaudio: bool # if the post comes from the external folder
id: str
state: int
favorite: bool
@@ -53,11 +53,11 @@ class Podpost:
href: str
duration: Optional[int]
length: int
- published: Optional[float] # when the post was published according to feed
- insert_date: float # when we entered this post into our db
+ published: Optional[float] # when the post was published according to feed
+ insert_date: float # when we entered this post into our db
link: Optional[str]
type: str
- podurl: str # the feed url
+ podurl: str # the feed url
chapters: List
def __init__(self, entry, podurl, logo_url, data=None, isaudio=False):
@@ -588,8 +588,32 @@ class PodpostFactory(BaseFactory):
self.podpostcache.delete(index)
self.store.delete(index)
- def persist(self, post:Podpost):
+ def persist(self, post: Podpost):
if type(post) != Podpost:
raise ValueError("Can only persist podposts")
- self.store.store(post.id,post)
- self.podpostcache.store(post.id,post)
+ self.store.store(post.id, post)
+ self.podpostcache.store(post.id, post)
+
+ def get_podcast_posts(self, podcast) -> Iterator[Podpost]:
+ """
+ @type podcast: Podcast
+ """
+ from podcast.podcast import Podcast
+ if (type(podcast) != Podcast):
+ raise ValueError("supplied argument must be a podcast")
+ for id in podcast.entry_ids_old_to_new:
+ yield self.get_podpost(id)
+
+ def persist_bulk(self, new_posts:List[Podpost]):
+ for post in new_posts:
+ self.persist(post)
+
+ def delete_all_from_podcast(self, podcast):
+ """
+ @type podcast: Podcast
+ """
+ from podcast.podcast import Podcast
+ if (type(podcast) != Podcast):
+ raise ValueError("supplied argument must be a podcast")
+ for post_id in podcast.entry_ids_old_to_new:
+ self.delete_podpost(post_id)
\ No newline at end of file
--
GitLab
From 54f537e79be18a1eb1dfb954e4a5b2bd70656d16 Mon Sep 17 00:00:00 2001
From: Thilo Kogge
Date: Sat, 6 Feb 2021 20:20:53 +0100
Subject: [PATCH 18/18] fixed error in podcast remove, added tests
---
python/podcast/podcast.py | 10 +++++-----
test/test_podcast.py | 11 ++++++++---
2 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/python/podcast/podcast.py b/python/podcast/podcast.py
index 575d13a..1889da8 100644
--- a/python/podcast/podcast.py
+++ b/python/podcast/podcast.py
@@ -233,7 +233,7 @@ class Podcast:
return PodpostFactory().get_podpost(id)
- def get_entries(self) -> Iterator[Podpost]:
+ def get_entries(self) -> Iterator[Dict]:
"""
Return a list of entries
"""
@@ -402,11 +402,11 @@ class PodcastFactory(BaseFactory):
logger.debug("PodcastFactory: from cache %s", url)
return podcast
- def remove_podcast(self, url):
+ def remove_podcast(self, url: str):
logger.info("deleting podcast and entries %s", url)
to_delete = self.get_podcast(url)
if to_delete != None:
- PodpostFactory().delete_all_from_podcast(self)
+ PodpostFactory().delete_all_from_podcast(to_delete)
self.podcastcache.delete(url)
self.store.delete(url)
@@ -415,5 +415,5 @@ class PodcastFactory(BaseFactory):
self.podcastcache.store(podcast.url,podcast)
def delete(self, podcast:Podcast):
- self.store.delete(podcast.url,podcast)
- self.podcastcache.delete(podcast.url,podcast)
+ self.store.delete(podcast.url)
+ self.podcastcache.delete(podcast.url)
diff --git a/test/test_podcast.py b/test/test_podcast.py
index 3d71891..f2f1afa 100644
--- a/test/test_podcast.py
+++ b/test/test_podcast.py
@@ -7,9 +7,11 @@ import os
import httpretty
from httpretty import HTTPretty
+from podcast.podpost import PodpostFactory
+
sys.path.append("../python")
-from podcast.podcast import Podcast
+from podcast.podcast import Podcast, PodcastFactory
xml_headers = {"content-type": "application/rss+xml; charset=UTF-8"}
def read_testdata(filename):
@@ -28,10 +30,10 @@ def test_feed_entry():
HTTPretty.register_uri(HTTPretty.GET, 'https://freakshow.fm/feed/opus/',
body=read_testdata('testdata/freakshow.rss'), adding_headers=xml_headers)
- for data in [ 'https://freakshow.fm/feed/opus/',
+ for url in [ 'https://freakshow.fm/feed/opus/',
'http://feeds.twit.tv/sn.xml',
]:
- podcast = Podcast(data)
+ podcast = Podcast(url)
assert podcast.alt_feeds != None
for feed in podcast.alt_feeds:
assert type(feed['url']) == str
@@ -58,6 +60,9 @@ def test_feed_entry():
assert type(data['logo_url']) == str
assert podcast.get_entry(data['id']) != None
assert data == podcast.get_entry(data['id']).get_data()
+ PodcastFactory().remove_podcast(url)
+ for entry in entries:
+ assert PodpostFactory().get_podpost(entry['id']) is None
invoked = 0
@httpretty.activate
--
GitLab