]>
git.scottworley.com Git - paperdoorknob/blob - fetch.py
b99938c055fe8a2fc31f951404ed497849e5dcff
1 # paperdoorknob: Print glowfic
3 # This program is free software: you can redistribute it and/or modify it
4 # under the terms of the GNU General Public License as published by the
5 # Free Software Foundation, version 3.
8 from abc
import ABC
, abstractmethod
9 from contextlib
import contextmanager
10 from sys
import stderr
11 from typing
import IO
, Iterator
19 def fetch(self
, url
: str) -> bytes:
20 raise NotImplementedError()
23 class _SessionFetcher(Fetcher
):
25 def __init__(self
, session
: requests
.Session
, timeout
: int) -> None:
26 self
._session
= session
27 self
._timeout
= timeout
29 def fetch(self
, url
: str) -> bytes:
30 with self
._session
.get(url
, timeout
=self
._timeout
) as r
:
35 class _CachingFetcher(Fetcher
):
39 session
: requests_cache
.CachedSession
,
40 timeout
: int) -> None:
41 self
._session
= session
42 self
._timeout
= timeout
43 self
._request
_count
= 0
44 self
._cache
_hit
_count
= 0
46 def fetch(self
, url
: str) -> bytes:
47 with self
._session
.get(url
, timeout
=self
._timeout
) as r
:
49 self
._request
_count
+= 1
50 self
._cache
_hit
_count
+= int(r
.from_cache
)
54 def request_count(self
) -> int:
55 return self
._request
_count
58 def cache_hit_count(self
) -> int:
59 return self
._cache
_hit
_count
63 def DirectFetcher(timeout
: int) -> Iterator
[_SessionFetcher
]:
64 with requests
.session() as session
:
65 yield _SessionFetcher(session
, timeout
)
72 report_stream
: IO
[str] = stderr
) -> Iterator
[_CachingFetcher
]:
73 with requests_cache
.CachedSession(cache_path
, cache_control
=True) as session
:
74 fetcher
= _CachingFetcher(session
, timeout
)
76 if fetcher
.request_count
> 0:
77 percent
= 100.0 * fetcher
.cache_hit_count
/ fetcher
.request_count
79 f
"Fetch cache hits: {fetcher.cache_hit_count} ({percent:.1f}%)",
83 class FakeFetcher(Fetcher
):
85 def __init__(self
, resources
: dict[str, bytes]) -> None:
86 self
._resources
= resources
89 def fetch(self
, url
: str) -> bytes:
90 self
._fetch
_count
+= 1
91 if url
not in self
._resources
:
92 raise requests
.HTTPError("URL not found", url
)
93 return self
._resources
[url
]
95 def request_count(self
) -> int:
96 return self
._fetch
_count