mirror of
https://github.com/lrnselfreliance/wrolpi.git
synced 2026-10-26 19:01:39 -04:00
* Squashed commit of the following:
commit c527475fcb4d4906457be5c10f0e9c6dee7fedc1
Author: Roland <roland@learningselfreliance.com>
Date: Tue Dec 14 22:16:36 2021 -0700
Only saving a favorite video to the config if it has a source_id.
commit ae8b712ebeaef467b8d5a5b87ca0f4f276373a0d
Author: Roland <roland@learningselfreliance.com>
Date: Tue Dec 14 22:14:26 2021 -0700
Ading description and changing Save button to Download.
commit 03a72be6dfdfa383915950a80e3f1ee9febf6705
Author: Roland <roland@learningselfreliance.com>
Date: Tue Dec 14 22:09:44 2021 -0700
Removing uploader for now.
commit 5d0231284bf84e459687f6ab903b06bf4e3762bd
Author: Roland <roland@learningselfreliance.com>
Date: Tue Dec 14 22:07:17 2021 -0700
Removing unique data from example info.
commit 9cc721a32d4715d9d6433e51db3b35e039c78d68
Author: Roland <roland@learningselfreliance.com>
Date: Tue Dec 14 22:02:33 2021 -0700
Updating downloader tests.
commit 8e193b03349ae4613f105418cd3e8176c7101304
Author: Roland <roland@learningselfreliance.com>
Date: Tue Dec 14 21:53:31 2021 -0700
Toasting error when WROL Mode is enabled. Disabling new downloads during WROL Mode.
commit 48c4311c31db8f2d2c8dd0a65f979a5f0a49a911
Author: Roland <roland@learningselfreliance.com>
Date: Tue Dec 14 21:45:06 2021 -0700
Raising error if download exits without a 0. Clearing kill event when starting a new download.
commit 54ba3a890d59facc837410d34bf7afb40db3b685
Author: Roland <roland@learningselfreliance.com>
Date: Tue Dec 14 21:16:46 2021 -0700
Downloads can be restarted and killed.
commit bd60751262247259c3e9ceb5116e017d6314c219
Author: Roland <roland@learningselfreliance.com>
Date: Mon Dec 13 16:28:18 2021 -0700
Downloads can be started again. Downloads are sorted on Downloads page.
commit ea7f39231b92982ae0b263b76c5bd1902cc8169d
Author: Roland <roland@learningselfreliance.com>
Date: Sat Dec 11 21:24:16 2021 -0700
Building Downloads tab.
commit d3321872ac3743ff6df781b07ef0fb537f1d4c98
Author: Roland <roland@learningselfreliance.com>
Date: Sat Dec 11 20:41:46 2021 -0700
Not scheduling channels withtout a URL/frequency.
commit 84f268a0d4f58c85f86b6377900492e0766f6619
Author: Roland <roland@learningselfreliance.com>
Date: Sat Dec 11 19:56:08 2021 -0700
Channel downloads will be spread out when each channel is created.
commit 26fa6beea38ef3f8d6b7bf218f18222a51a87a60
Author: Roland <roland@learningselfreliance.com>
Date: Sat Dec 11 13:08:11 2021 -0700
Recurring downloads are renewed on startup.
commit fc2ab850533f1c3ad073f4692c7dea2be43e85d6
Author: Roland <roland@learningselfreliance.com>
Date: Fri Dec 10 17:03:57 2021 -0700
Fetching download again after do_download.
commit fdadad327fc09c17a49eb63b11e632fb72cc3195
Author: Roland <roland@learningselfreliance.com>
Date: Fri Dec 10 16:20:51 2021 -0700
Fixing error with test. Mock was not being reset.
commit 070dee238e53377acd22097c63cf3794e68ed423
Author: Roland <roland@learningselfreliance.com>
Date: Fri Dec 10 15:36:39 2021 -0700
Fixed bug in date handling (big surprise).
commit e53a8992268d68620c679455adaec3a590f20602
Author: Roland <roland@learningselfreliance.com>
Date: Wed Dec 1 16:48:36 2021 -0700
Using chunks for regular channel refresh.
commit 3bd60c58d1bef0226325f321978c0434b36b3be5
Author: Roland <roland@learningselfreliance.com>
Date: Wed Dec 1 15:22:02 2021 -0700
Reformatting.
commit 4fdc325f25a32c311ca6543fe321624b2bd564b2
Author: Roland <roland@learningselfreliance.com>
Date: Wed Dec 1 15:13:34 2021 -0700
Creating function that refreshes NO CHANNEL videos.
commit d67feafb6c2994f5a4a1295920a70db369cc6816
Author: Roland <roland@learningselfreliance.com>
Date: Wed Dec 1 14:35:54 2021 -0700
Removing unused functions.
commit 6b3918e4e78fbac64920f85c4de0df873ec366a1
Author: Roland <roland@learningselfreliance.com>
Date: Wed Dec 1 14:31:48 2021 -0700
Removing reporter and events. This will be replaced in the future with some sort of SSE.
commit 54fa1b0f5e93ca25c80b780dcdc3876b700273b1
Author: Roland <roland@learningselfreliance.com>
Date: Sun Nov 28 17:55:43 2021 -0700
Better error handling for archive button.
commit c31d124e511b27f626ed2df71486d47302b396f3
Author: Roland <roland@learningselfreliance.com>
Date: Sun Nov 28 17:29:43 2021 -0700
Displaying View Count in a human readable format.
commit 0ee2bd65588fd93b475cad6144e76f1b45191b39
Author: Roland <roland@learningselfreliance.com>
Date: Sat Nov 27 09:29:41 2021 -0700
Fixing tests.
commit e64aff32bab95c311ea3747e1a21b58b99750d5e
Author: Roland <roland@learningselfreliance.com>
Date: Sat Nov 27 08:59:51 2021 -0700
Handling when a Video has no Channel in UI.
commit b9549ecd5aac03c002adca7b7667f0a7189b662a
Author: Roland <roland@learningselfreliance.com>
Date: Fri Nov 26 08:35:36 2021 -0700
Downloaders can raise UnrecoverableDownloadError to signal a downlaod should not be retried.
commit da88798e2584d3e84900a70e34166c8c208c64fb
Author: Roland <roland@learningselfreliance.com>
Date: Wed Nov 24 20:40:29 2021 -0700
Downloaders can refuse a download, which will then be deleted.
commit b865d856121db5ec8a3660c5d3c13b9846fde688
Author: Roland <roland@learningselfreliance.com>
Date: Wed Nov 24 19:35:43 2021 -0700
Removing relative path handling.
commit 6d7757870b02ba030d78b3ef7e43f28b906eea61
Author: Roland <roland@learningselfreliance.com>
Date: Wed Nov 24 19:28:27 2021 -0700
Using __json__ for Video and Channel models.
commit 649e4d6a61608272759d1e7ee02b490bb5c20b3e
Author: Roland <roland@learningselfreliance.com>
Date: Wed Nov 24 18:23:38 2021 -0700
Fixing video links in UI.
commit 9d081af12742070b8519bd752812130cb5dbe393
Author: Roland <roland@learningselfreliance.com>
Date: Wed Nov 24 14:42:38 2021 -0700
Fixing docs.
commit 1202cbe0f9ae744d7801b53a5071cded8ea39924
Author: Roland <roland@learningselfreliance.com>
Date: Wed Nov 24 14:40:36 2021 -0700
Fixing wrolpi tests.
commit 3f6af8cc1123f2f63a3fc0f21ec4d994c642cf13
Author: Roland <roland@learningselfreliance.com>
Date: Wed Nov 24 14:13:35 2021 -0700
Fixing tests to use MediaPath.
commit faec04f2a5e4c267a502c03884940a9c5bcfe387
Author: Roland <roland@learningselfreliance.com>
Date: Fri Nov 19 10:21:20 2021 -0700
Testing when a video has no channel.
commit cbf22aad7a0b72e61685e0236e843554b57c4af1
Author: Roland <roland@learningselfreliance.com>
Date: Thu Nov 18 16:24:03 2021 -0700
Using MediaPath for Video and Channel models. Testing VideoDownloader.do_download.
commit 7916ed61e43439e6cd60f23ce3fdf6c1a75bf02d
Author: Roland <roland@learningselfreliance.com>
Date: Thu Nov 18 12:43:44 2021 -0700
Channels/Videos downloaders can get gotten.
commit 808ef796cec01db6e7009065f9e26d25d9500ce2
Author: Roland <roland@learningselfreliance.com>
Date: Wed Nov 17 21:45:19 2021 -0700
Upgrading to Sanic 21.9.1.
commit ea32813be28e78393ac456ee782a7245c098188f
Author: Roland <roland@learningselfreliance.com>
Date: Wed Nov 17 20:29:01 2021 -0700
Creating Downloader and DownloaderManager classes which handle downloading URLs.
commit e859a77a77277ddf8b6e221ec9c9383c8ab91d66
Author: Roland <roland@learningselfreliance.com>
Date: Wed Nov 17 12:41:39 2021 -0700
Creating UI segement which allows the download/upload of media.
* Displaying all recurring downloads.
* Not downloading channels with empty url.
* Showing positive row for recurring downloads.
* Removing default last_successful_download.
* Only displaying Last Successful Download when there is one.
* Refreshing videos before finding missing videos.
* Using short video path name for log.
* Removing download history feature in favor of new Downloads page.
* Only showing info date if it exists.
* Making get_or_create_channel more reliable.
* Allowing null for channel download frequency.
* Logging when searching for channel.
* Storing channel's source_id in config.
* Importing using link instead of name.
* Getting channel id when importing channels.
* Removing redunant parentheses from repr.
* Preserving database channel values if there are not values in the config.
* Only highlighting pending downloads.
* Deleting old downloads periodically.
* Sorting recurring by next_download/frequency.
* Creating fixtures for channels, media directory and db session.
* Removing unused function. Wrapping config for tests.
* Deleting channel download when deleting a channel.
* Testing that a channel's download is deleted when the channel is deleted.
* Updating youtube-dl
* Switching from youtube-dl in favor of yt-dlp.
* Sorting once-downlaods by last_successful_download then id.
* Adding special handling to video_url_resolver for full urls.
* Consolidating downloader methods and functions. Reversing once-download sort order so the most recently downloaded are at the top.
* Getting session if one is not provided.
* Adding test for create_downloads.
* Not passing format option when getting filename.
* Linting
Signed-off-by: Roland <roland@learningselfreliance.com>
348 lines
15 KiB
Python
348 lines
15 KiB
Python
import json
|
|
import pathlib
|
|
from datetime import datetime
|
|
|
|
import mock
|
|
|
|
from modules.archive.lib import new_archive, get_or_create_domain_and_url, get_urls, get_url_count, delete_url, \
|
|
_refresh_archives, get_domains, get_new_archive_files
|
|
from modules.archive.models import Archive, URL, Domain
|
|
from wrolpi.common import get_media_directory
|
|
from wrolpi.db import get_db_session
|
|
from wrolpi.errors import InvalidDomain, UnknownURL
|
|
from wrolpi.media_path import MediaPath
|
|
from wrolpi.root_api import CustomJSONEncoder
|
|
from wrolpi.test.common import TestAPI, wrap_test_db, wrap_media_directory
|
|
|
|
|
|
def make_fake_request_archive(readability=True, screenshot=True, title=True):
|
|
def fake_request_archive(_):
|
|
singlefile = '<html>\ntest single-file\nジにてこちら\n<title>some title</title></html>'
|
|
r = dict(
|
|
content=f'<html>test readability content</html>',
|
|
textContent='<html>test readability textContent</html>',
|
|
title='ジにてこちら' if title else None,
|
|
) if readability else None
|
|
s = b'screenshot data' if screenshot else None
|
|
return singlefile, r, s
|
|
|
|
return fake_request_archive
|
|
|
|
|
|
class TestArchive(TestAPI):
|
|
|
|
def setUp(self) -> None:
|
|
super().setUp()
|
|
(pathlib.Path(self.tmp_dir.name) / 'archive').mkdir(exist_ok=True)
|
|
|
|
@mock.patch('modules.archive.lib.now', lambda: datetime(2001, 1, 1))
|
|
def test_get_new_archive_files(self):
|
|
s, r, t, j, c = map(str, get_new_archive_files('https://example.com/two'))
|
|
assert str(s).endswith('archive/example.com/2001-01-01 00:00:00.000000.html')
|
|
assert str(r).endswith('archive/example.com/2001-01-01 00:00:00.000000-readability.html')
|
|
assert str(t).endswith('archive/example.com/2001-01-01 00:00:00.000000-readability.txt')
|
|
assert str(j).endswith('archive/example.com/2001-01-01 00:00:00.000000-readability.json')
|
|
assert str(c).endswith('archive/example.com/2001-01-01 00:00:00.000000.png')
|
|
|
|
s, r, t, j, c = get_new_archive_files('https://www.example.com/one')
|
|
# Leading www. is removed.
|
|
assert str(s).endswith('archive/example.com/2001-01-01 00:00:00.000000.html')
|
|
assert str(r).endswith('archive/example.com/2001-01-01 00:00:00.000000-readability.html')
|
|
assert str(t).endswith('archive/example.com/2001-01-01 00:00:00.000000-readability.txt')
|
|
assert str(j).endswith('archive/example.com/2001-01-01 00:00:00.000000-readability.json')
|
|
assert str(c).endswith('archive/example.com/2001-01-01 00:00:00.000000.png')
|
|
|
|
@wrap_test_db
|
|
def test_new_archive(self):
|
|
with mock.patch('modules.archive.lib.request_archive', make_fake_request_archive()):
|
|
archive1 = new_archive('https://example.com', sync=True)
|
|
# Everything is filled out.
|
|
self.assertIsInstance(archive1, Archive)
|
|
self.assertIsNotNone(archive1.archive_datetime)
|
|
self.assertIsInstance(archive1.singlefile_path, MediaPath)
|
|
self.assertIsInstance(archive1.readability_path, MediaPath)
|
|
self.assertIsInstance(archive1.readability_txt_path, MediaPath)
|
|
self.assertIsInstance(archive1.screenshot_path, MediaPath)
|
|
self.assertEqual(archive1.title, 'ジにてこちら')
|
|
self.assertIsNotNone(archive1.url)
|
|
self.assertIsNotNone(archive1.domain)
|
|
|
|
# The actual files were dumped and read correctly.
|
|
with open(archive1.singlefile_path.path) as fh:
|
|
self.assertEqual(fh.read(), '<html>\ntest single-file\nジにてこちら\n<title>some title</title></html>')
|
|
with open(archive1.readability_path.path) as fh:
|
|
self.assertEqual(fh.read(), '<html>test readability content</html>')
|
|
with open(archive1.readability_txt_path.path) as fh:
|
|
self.assertEqual(fh.read(), '<html>test readability textContent</html>')
|
|
with open(archive1.readability_json_path.path) as fh:
|
|
self.assertEqual(json.load(fh), {'title': 'ジにてこちら', 'url': 'https://example.com'})
|
|
|
|
archive2 = new_archive('https://example.com')
|
|
# URL and Domain are reused.
|
|
self.assertEqual(archive1.url, archive2.url)
|
|
self.assertEqual(archive1.domain, archive2.domain)
|
|
|
|
@wrap_test_db
|
|
def test_no_screenshot(self):
|
|
with mock.patch('modules.archive.lib.request_archive', make_fake_request_archive(screenshot=False)):
|
|
archive = new_archive('https://example.com', sync=True)
|
|
self.assertIsInstance(archive.singlefile_path, MediaPath)
|
|
self.assertIsInstance(archive.readability_path, MediaPath)
|
|
# Screenshot was empty
|
|
self.assertIsNone(archive.screenshot_path)
|
|
|
|
@wrap_test_db
|
|
def test_no_readability(self):
|
|
with mock.patch('modules.archive.lib.request_archive', make_fake_request_archive(readability=False)):
|
|
archive = new_archive('https://example.com', sync=True)
|
|
self.assertIsInstance(archive.singlefile_path, MediaPath)
|
|
self.assertIsInstance(archive.screenshot_path, MediaPath)
|
|
# Readability empty
|
|
self.assertIsNone(archive.readability_path)
|
|
self.assertIsNone(archive.readability_txt_path)
|
|
|
|
@wrap_test_db
|
|
def test_dict(self):
|
|
with mock.patch('modules.archive.lib.request_archive', make_fake_request_archive()):
|
|
d = new_archive('https://example.com', sync=True).dict()
|
|
self.assertIsInstance(d, dict)
|
|
json.dumps(d, cls=CustomJSONEncoder)
|
|
|
|
@wrap_test_db
|
|
def test_relationships(self):
|
|
with get_db_session(commit=True) as session:
|
|
domain, url = get_or_create_domain_and_url(session, 'https://wrolpi.org:443')
|
|
archive = Archive(
|
|
singlefile_path=f'{self.tmp_dir.name}/wrolpi.org:443/foo',
|
|
title='bar',
|
|
url_id=url.id,
|
|
domain_id=domain.id,
|
|
)
|
|
session.add(archive)
|
|
session.flush()
|
|
|
|
url.latest_id = archive.id
|
|
|
|
self.assertEqual(archive.domain, domain)
|
|
self.assertEqual(archive.url, url)
|
|
|
|
# Relationships are added in the dict() method.
|
|
self.assertDictContains(
|
|
url.dict(),
|
|
dict(
|
|
id=1,
|
|
url='https://wrolpi.org:443',
|
|
latest_id=1,
|
|
latest=dict(singlefile_path=self.tmp_path / 'wrolpi.org:443/foo'),
|
|
domain_id=1,
|
|
domain=dict(directory=self.tmp_path / 'archive/wrolpi.org:443', domain='wrolpi.org:443'),
|
|
)
|
|
)
|
|
|
|
@wrap_test_db
|
|
def test_get_urls(self):
|
|
# No URLs yet.
|
|
urls = get_urls()
|
|
self.assertEqual([], urls)
|
|
|
|
with mock.patch('modules.archive.lib.request_archive', make_fake_request_archive(readability=False)):
|
|
# One set of duplicate URLs
|
|
new_archive('https://wrolpi.org/one', sync=True)
|
|
new_archive('https://wrolpi.org/one', sync=True)
|
|
|
|
# Unique URLs
|
|
new_archive('https://wrolpi.org/two', sync=True)
|
|
new_archive('https://wrolpi.org/three', sync=True)
|
|
new_archive('https://example.com/one', sync=True)
|
|
|
|
urls = get_urls()
|
|
# There are only 4 because one set is duplicate.
|
|
self.assertEqual(len(urls), 4)
|
|
self.assertEqual(
|
|
['https://example.com/one', 'https://wrolpi.org/three',
|
|
'https://wrolpi.org/two', 'https://wrolpi.org/one'],
|
|
[i['url'] for i in urls],
|
|
)
|
|
|
|
# Only one URL for this domain.
|
|
urls = get_urls(domain='example.com')
|
|
self.assertEqual(len(urls), 1)
|
|
self.assertEqual(urls[0]['url'], 'https://example.com/one')
|
|
|
|
# Bad domain requested.
|
|
self.assertRaises(InvalidDomain, get_urls, domain='bad_domain.com')
|
|
|
|
# Limit to 3, but with an offset of 2 there are only 2.
|
|
urls = get_urls(3, 2)
|
|
self.assertEqual(['https://wrolpi.org/two', 'https://wrolpi.org/one'], [i['url'] for i in urls])
|
|
|
|
# First two of this domain.
|
|
urls = get_urls(2, 0, 'wrolpi.org')
|
|
self.assertEqual(['https://wrolpi.org/two', 'https://wrolpi.org/one'], [i['url'] for i in urls])
|
|
# Last two of this domain, but there is only 1.
|
|
urls = get_urls(2, 2, 'wrolpi.org')
|
|
self.assertEqual(['https://wrolpi.org/three'], [i['url'] for i in urls])
|
|
|
|
@wrap_test_db
|
|
def test_validate_paths(self):
|
|
with mock.patch('modules.archive.lib.request_archive', make_fake_request_archive()):
|
|
archive = new_archive('https://example.com')
|
|
try:
|
|
with get_db_session(commit=True):
|
|
archive.singlefile_path = 'asdf'
|
|
except ValueError as e:
|
|
self.assertIn('relative', str(e), f'Relative path error was not raised')
|
|
|
|
@wrap_test_db
|
|
def test_get_url_count(self):
|
|
with mock.patch('modules.archive.lib.request_archive', make_fake_request_archive()):
|
|
self.assertRaises(InvalidDomain, get_url_count, 'bad domain')
|
|
|
|
self.assertEqual(get_url_count(), 0)
|
|
new_archive('https://example.com', sync=True)
|
|
self.assertEqual(get_url_count(), 1)
|
|
new_archive('https://example.com', sync=True)
|
|
self.assertEqual(get_url_count(), 1)
|
|
new_archive('https://example.org', sync=True)
|
|
self.assertEqual(get_url_count(), 2)
|
|
new_archive('https://example.org', sync=True)
|
|
self.assertEqual(get_url_count('example.org'), 1)
|
|
|
|
@wrap_test_db
|
|
def test_delete_url(self):
|
|
with mock.patch('modules.archive.lib.request_archive', make_fake_request_archive()):
|
|
archive = new_archive('https://example.com', sync=True)
|
|
|
|
with get_db_session() as session:
|
|
urls = session.query(URL).all()
|
|
self.assertEqual(len(urls), 1)
|
|
archives = session.query(Archive).all()
|
|
self.assertEqual(len(archives), 1)
|
|
|
|
self.assertIsNotNone(archive.singlefile_path)
|
|
singlefile_path = archive.singlefile_path.path
|
|
self.assertTrue(singlefile_path.is_file())
|
|
|
|
url_id = archive.url.id
|
|
|
|
# Delete the URL, all archives and all files.
|
|
delete_url(url_id)
|
|
self.assertFalse(singlefile_path.exists())
|
|
|
|
# Can't delete the same URL twice.
|
|
self.assertRaises(UnknownURL, delete_url, url_id)
|
|
|
|
with get_db_session() as session:
|
|
urls = session.query(URL).all()
|
|
self.assertEqual(len(urls), 0)
|
|
|
|
# Bad ID
|
|
self.assertRaises(UnknownURL, delete_url, 123)
|
|
|
|
@wrap_test_db
|
|
def test_get_title_from_html(self):
|
|
with wrap_media_directory():
|
|
with mock.patch('modules.archive.lib.request_archive', make_fake_request_archive()):
|
|
archive = new_archive('example.com', sync=True)
|
|
self.assertEqual(archive.title, 'ジにてこちら')
|
|
|
|
def fake_request_archive(_):
|
|
singlefile = '<html>\ntest single-file\nジにてこちら\n<title>some title</title></html>'
|
|
r = dict(
|
|
content=f'<html>test readability content</html>',
|
|
textContent='<html>test readability textContent</html>',
|
|
)
|
|
s = b'screenshot data'
|
|
return singlefile, r, s
|
|
|
|
with mock.patch('modules.archive.lib.request_archive', fake_request_archive):
|
|
archive = new_archive('example.com', sync=True)
|
|
self.assertEqual(archive.title, 'some title')
|
|
|
|
def fake_request_archive(_):
|
|
singlefile = '<html></html>'
|
|
r = dict(
|
|
content=f'<html>missing a title</html>',
|
|
textContent='',
|
|
)
|
|
s = b'screenshot data'
|
|
return singlefile, r, s
|
|
|
|
with mock.patch('modules.archive.lib.request_archive', fake_request_archive):
|
|
archive = new_archive('example.com', sync=True)
|
|
self.assertIsNone(archive.title)
|
|
|
|
@wrap_test_db
|
|
def test_refresh_archives(self):
|
|
with wrap_media_directory():
|
|
with get_db_session() as session:
|
|
urls = session.query(URL).count()
|
|
self.assertEqual(urls, 0)
|
|
|
|
archive_directory = get_media_directory() / 'archive'
|
|
archive_directory.mkdir()
|
|
|
|
# Make some test files to refresh.
|
|
example = archive_directory / 'example.com'
|
|
example.mkdir()
|
|
(example / '2021-10-05 16:20:10.346823.html').touch()
|
|
(example / '2021-10-05 16:20:10.346823.png').touch()
|
|
(example / '2021-10-05 16:20:10.346823-readability.txt').touch()
|
|
(example / '2021-10-05 16:20:10.346823-readability.json').touch()
|
|
(example / '2021-10-05 16:20:10.346823-readability.html').touch()
|
|
with (example / '2021-10-05 16:20:10.346823-readability.json').open('wt') as fh:
|
|
json.dump({'url': 'foo'}, fh)
|
|
|
|
# These should log an error because they are missing the singlefile path.
|
|
(example / '2021-10-05 16:20:10.346824-readability.html').touch()
|
|
(example / '2021-10-05 16:20:10.346825-readability.json').touch()
|
|
# These are not archives and should be ignored.
|
|
(example / '2021-10-05 16:20:10.346826-something.html').touch()
|
|
(example / 'random file').touch()
|
|
(example / '2021-10-05 16:20:10.346827-something.html').mkdir()
|
|
(example / '2021-10-05 16:20:10 invalid date').touch()
|
|
|
|
# This single archive is found.
|
|
_refresh_archives()
|
|
with get_db_session() as session:
|
|
self.assertEqual(session.query(URL).count(), 1)
|
|
self.assertEqual(session.query(Archive).count(), 1)
|
|
|
|
url: URL = session.query(URL).one()
|
|
archive: Archive = session.query(Archive).one()
|
|
self.assertEqual(url.latest, archive)
|
|
# latest_datetime is set, the timestamp in the file name is assumed to be UTC.
|
|
self.assertEqual(str(url.latest_datetime), '2021-10-05 16:20:10.346823-06:00')
|
|
|
|
# Running the refresh does not result in a new archive.
|
|
_refresh_archives()
|
|
with get_db_session() as session:
|
|
self.assertEqual(session.query(URL).count(), 1)
|
|
self.assertEqual(session.query(Archive).count(), 1)
|
|
|
|
@wrap_test_db
|
|
def test_refresh_archives_delete_empty(self):
|
|
"""
|
|
Domains or URLs with no archives should be deleted during refresh.
|
|
"""
|
|
with wrap_media_directory():
|
|
(get_media_directory() / 'archive').mkdir()
|
|
with get_db_session(commit=True) as session:
|
|
# These should not be deleted.
|
|
domain, url = get_or_create_domain_and_url(session, 'https://example.com')
|
|
archive = Archive(singlefile_path='foo', url_id=url.id)
|
|
session.add(archive)
|
|
|
|
# These should be deleted.
|
|
domain = Domain(domain='bar')
|
|
session.add(domain)
|
|
session.flush()
|
|
session.add(URL(url='bar', domain_id=domain.id))
|
|
|
|
self.assertEqual(len(get_urls()), 2)
|
|
self.assertEqual(len(get_domains()), 2)
|
|
|
|
_refresh_archives()
|
|
|
|
self.assertEqual(len(get_urls()), 1)
|
|
self.assertEqual(len(get_domains()), 1)
|