mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-05-24 02:02:32 -04:00
add/remove blank-line (extra-edit)
ruff 'E302,E303,E304,E305,W391'
This commit is contained in:
parent
5540126765
commit
8d28380515
@ -76,5 +76,3 @@ class InterfacePluginDemo(InterfaceActionBase):
|
||||
ac = self.actual_plugin_
|
||||
if ac is not None:
|
||||
ac.apply_settings()
|
||||
|
||||
|
||||
|
@ -89,5 +89,6 @@ def generate_template_language_help(language, log):
|
||||
a(POSTAMBLE)
|
||||
return ''.join(output)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
generate_template_language_help()
|
||||
|
@ -17,6 +17,7 @@ from calibre.web.feeds.news import BasicNewsRecipe
|
||||
|
||||
use_archive = True
|
||||
|
||||
|
||||
def E(parent, name, text='', **attrs):
|
||||
ans = parent.makeelement(name, **attrs)
|
||||
ans.text = text
|
||||
@ -341,7 +342,6 @@ class Economist(BasicNewsRecipe):
|
||||
|
||||
# }}}
|
||||
|
||||
|
||||
def preprocess_raw_html(self, raw, url):
|
||||
# open('/t/raw.html', 'wb').write(raw.encode('utf-8'))
|
||||
if use_archive:
|
||||
|
@ -8,6 +8,7 @@ def absurl(url):
|
||||
if url.startswith('/'):
|
||||
return 'https://www.afr.com' + url
|
||||
|
||||
|
||||
class afr(BasicNewsRecipe):
|
||||
title = 'Australian Financial Review'
|
||||
__author__ = 'unkn0wn'
|
||||
|
@ -28,4 +28,3 @@ class WwwAltomdata_dk(BasicNewsRecipe):
|
||||
('Kommentarer til Alt om DATA, Datatid TechLife', 'http://www.altomdata.dk/comments/feed'),
|
||||
|
||||
]
|
||||
|
||||
|
@ -18,6 +18,7 @@ today = today.replace('/', '%2F')
|
||||
|
||||
index = 'https://epaper.andhrajyothy.com'
|
||||
|
||||
|
||||
class andhra(BasicNewsRecipe):
|
||||
title = 'ఆంధ్రజ్యోతి - ఆంధ్రప్రదేశ్'
|
||||
language = 'te'
|
||||
|
@ -18,6 +18,7 @@ today = today.replace('/', '%2F')
|
||||
|
||||
index = 'https://epaper.andhrajyothy.com'
|
||||
|
||||
|
||||
class andhra(BasicNewsRecipe):
|
||||
title = 'ఆంధ్రజ్యోతి - తెలంగాణ'
|
||||
language = 'te'
|
||||
|
@ -24,4 +24,3 @@ class WwwAvisen_dk(BasicNewsRecipe):
|
||||
feeds = [
|
||||
('Nyheder fra Avisen.dk', 'http://www.avisen.dk/rss.aspx'),
|
||||
]
|
||||
|
||||
|
@ -12,6 +12,7 @@ def class_as_string(x):
|
||||
x = ' '.join(x)
|
||||
return x
|
||||
|
||||
|
||||
def class_startswith(*prefixes):
|
||||
|
||||
def q(x):
|
||||
@ -24,6 +25,7 @@ def class_startswith(*prefixes):
|
||||
|
||||
return dict(attrs={'class': q})
|
||||
|
||||
|
||||
def absolutize_url(url):
|
||||
if url.startswith('//'):
|
||||
return 'https:' + url
|
||||
|
@ -15,6 +15,7 @@ def absurl(x):
|
||||
x = 'https://caravanmagazine.in' + x
|
||||
return x
|
||||
|
||||
|
||||
def safe_dict(data, *names):
|
||||
ans = data
|
||||
for x in names:
|
||||
@ -49,6 +50,7 @@ def parse_body(x):
|
||||
yield from parse_body(p)
|
||||
yield '</p>'
|
||||
|
||||
|
||||
def parse_p(p):
|
||||
if p.get('type', '') == 'text':
|
||||
if 'marks' in p:
|
||||
|
@ -67,7 +67,6 @@ class ChicagoTribune(BasicNewsRecipe):
|
||||
feeds.append({'title': title, 'url': url})
|
||||
return [('Articles', feeds)]
|
||||
|
||||
|
||||
def preprocess_html(self, soup):
|
||||
for img in soup.findAll('img', attrs={'data-src': True}):
|
||||
img['src'] = img['data-src']
|
||||
|
@ -51,4 +51,3 @@ class WwwComputerworld_dk(BasicNewsRecipe):
|
||||
('IDG Kurser', 'http://job.idgkurser.dk/rss/'),
|
||||
|
||||
]
|
||||
|
||||
|
@ -5,6 +5,7 @@ def absurl(url):
|
||||
if url.startswith('/'):
|
||||
return 'https://www.deccanherald.com' + url
|
||||
|
||||
|
||||
class herald(BasicNewsRecipe):
|
||||
title = 'Deccan Herald'
|
||||
__author__ = 'unkn0wn'
|
||||
|
@ -54,7 +54,6 @@ class DeutscheWelle_es(BasicNewsRecipe):
|
||||
('Conozca Alemania', 'http://rss.dw-world.de/rdf/rss-sp-con')
|
||||
]
|
||||
|
||||
|
||||
def preprocess_html(self, soup):
|
||||
for img in soup.findAll('img', srcset=True):
|
||||
img['src'] = img['srcset'].split()[6]
|
||||
|
@ -59,4 +59,3 @@ class DeutscheWelle_sr(BasicNewsRecipe):
|
||||
(u'Nauka Tehnika Medicina', u'http://rss.dw-world.de/rdf/rss-ser-science'),
|
||||
(u'Kultura', u'feed:http://rss.dw-world.de/rdf/rss-ser-cul')
|
||||
]
|
||||
|
||||
|
@ -14,6 +14,7 @@ Fetch Deutschlandfunk & Deutschlandfunk Kultur
|
||||
## Version:1.6
|
||||
## New RSS source: https://www.deutschlandfunk.de/rss-angebot-102.html
|
||||
|
||||
|
||||
class AdvancedUserRecipe1432200863(BasicNewsRecipe):
|
||||
|
||||
title = 'Deutschlandfunk & Deutschlandfunk Kultur'
|
||||
@ -34,8 +35,6 @@ class AdvancedUserRecipe1432200863(BasicNewsRecipe):
|
||||
.b-image-figure, .caption-figure.is-left, .b-image-credits {font-size: .75em; font-weight: normal;margin-bottom: .75em}
|
||||
'''
|
||||
|
||||
|
||||
|
||||
feeds = [
|
||||
('DLF Nachrichten', 'https://www.deutschlandfunk.de/nachrichten-100.rss'),
|
||||
('DLF Politikportal', 'https://www.deutschlandfunk.de/politikportal-100.rss'),
|
||||
|
@ -104,7 +104,6 @@ class DRNyheder(BasicNewsRecipe):
|
||||
cover_url = cover_item['src']
|
||||
return cover_url
|
||||
|
||||
|
||||
keep_only_tags = [
|
||||
|
||||
dict(name='h1', attrs={'class': 'dre-article-title__heading'}), # Title
|
||||
|
@ -242,7 +242,6 @@ class Espresso(BasicNewsRecipe):
|
||||
raw = etree.tostring(root, encoding='unicode')
|
||||
return raw
|
||||
|
||||
|
||||
def eco_find_image_tables(self, soup):
|
||||
for x in soup.findAll('table', align=['right', 'center']):
|
||||
if len(x.findAll('font')) in (1, 2) and len(x.findAll('img')) == 1:
|
||||
|
@ -78,6 +78,7 @@ def load_article_from_json(raw):
|
||||
body += process_node(node)
|
||||
return '<html><body><article>' + body + '</article></body></html>'
|
||||
|
||||
|
||||
def cleanup_html_article(root):
|
||||
main = root.xpath('//main')[0]
|
||||
body = root.xpath('//body')[0]
|
||||
@ -91,17 +92,20 @@ def cleanup_html_article(root):
|
||||
for x in root.xpath('//button'):
|
||||
x.getparent().remove(x)
|
||||
|
||||
|
||||
def classes(classes):
|
||||
q = frozenset(classes.split(' '))
|
||||
return dict(attrs={
|
||||
'class': lambda x: x and frozenset(x.split()).intersection(q)})
|
||||
|
||||
|
||||
def new_tag(soup, name, attrs=()):
|
||||
impl = getattr(soup, 'new_tag', None)
|
||||
if impl is not None:
|
||||
return impl(name, attrs=dict(attrs))
|
||||
return Tag(soup, name, attrs=attrs or None)
|
||||
|
||||
|
||||
def process_url(url):
|
||||
if url.startswith('/'):
|
||||
url = 'https://www.economist.com' + url
|
||||
|
@ -33,7 +33,6 @@ class Esensja(BasicNewsRecipe):
|
||||
dict(attrs={'class': ['tekst_koniec', 'ref', 'wykop']}),
|
||||
dict(attrs={'itemprop': ['copyrightHolder', 'publisher']}),
|
||||
dict(id='komentarze')
|
||||
|
||||
]
|
||||
|
||||
extra_css = '''
|
||||
|
@ -18,7 +18,6 @@ def format_tickaroo_liveblog(soup):
|
||||
for div in soup.findAll('div', attrs={'class':'tik4-content-block tik4-content-block--rich-text tik4-content-block--position-2'}):
|
||||
div.insert_before(soup.new_tag('br'))
|
||||
|
||||
|
||||
#format liveblogs
|
||||
for tag in soup.findAll('time'):
|
||||
ntag = soup.new_tag('br')
|
||||
@ -33,6 +32,7 @@ def format_tickaroo_liveblog(soup):
|
||||
if ntag and temp:
|
||||
ntag.insert_after(temp)
|
||||
|
||||
|
||||
# process run of images
|
||||
def bilderstrecke(soup,tag):
|
||||
flag = False
|
||||
@ -76,10 +76,10 @@ def bilderstrecke(soup,tag):
|
||||
collect.append(fig)
|
||||
soup.find(class_='header-teaser').insert_after(collect)
|
||||
|
||||
|
||||
for tag in soup.findAll(class_='header-teaser__image--default'):
|
||||
tag.extract()
|
||||
|
||||
|
||||
def story(soup,tag):
|
||||
first_image = soup.find('img',attrs={'loading':'lazy'})
|
||||
first_caption = soup.find('figcaption',attrs={'class':'caption'})
|
||||
@ -136,7 +136,6 @@ class FazNet(BasicNewsRecipe):
|
||||
dict(name = 'script', attrs = {'id':'__NUXT_DATA__'}),
|
||||
]
|
||||
|
||||
|
||||
remove_tags = [
|
||||
dict(name='div', attrs={'class':[
|
||||
'related-articles','consent-placeholder',
|
||||
@ -153,7 +152,6 @@ class FazNet(BasicNewsRecipe):
|
||||
|
||||
remove_attributes = ['onclick']
|
||||
|
||||
|
||||
test_article = False
|
||||
if not test_article:
|
||||
feeds = [
|
||||
|
@ -7,6 +7,7 @@ from calibre.web.feeds.news import BasicNewsRecipe, classes
|
||||
|
||||
index = 'https://www.globaltimes.cn/'
|
||||
|
||||
|
||||
class GlobalTimes(BasicNewsRecipe):
|
||||
title = 'Global Times'
|
||||
__author__ = 'unkn0wn'
|
||||
|
@ -5,10 +5,12 @@ from calibre.web.feeds.news import BasicNewsRecipe, classes
|
||||
Hamilton Spectator Calibre Recipe
|
||||
'''
|
||||
|
||||
|
||||
def absurl(url):
|
||||
if url.startswith('/'):
|
||||
return 'https://www.thespec.com' + url
|
||||
|
||||
|
||||
class HamiltonSpectator(BasicNewsRecipe):
|
||||
title = u'Hamilton Spectator'
|
||||
max_articles_per_feed = 50
|
||||
|
@ -17,6 +17,7 @@ def get_story(story):
|
||||
for x in story['story-elements']:
|
||||
yield from get_story(x)
|
||||
|
||||
|
||||
def img(img):
|
||||
yield '<p>'
|
||||
if 'image-s3-key' in img:
|
||||
@ -25,6 +26,7 @@ def img(img):
|
||||
yield '<div class="cap">' + img['title'] + '</div>'
|
||||
yield '</p>'
|
||||
|
||||
|
||||
class himal(BasicNewsRecipe):
|
||||
title = 'Himal Southasian'
|
||||
__author__ = 'unkn0wn'
|
||||
|
@ -74,7 +74,6 @@ class TheHindufeeds(BasicNewsRecipe):
|
||||
src.extract()
|
||||
return soup
|
||||
|
||||
|
||||
def get_cover_url(self):
|
||||
soup = self.index_to_soup('https://www.thehindu.com/todays-paper/')
|
||||
if cover := soup.find(attrs={'class':'hindu-ad'}):
|
||||
|
@ -8,6 +8,7 @@ from calibre.web.feeds.news import BasicNewsRecipe
|
||||
|
||||
index = 'https://epaper.hindustantimes.com'
|
||||
|
||||
|
||||
class ht(BasicNewsRecipe):
|
||||
title = 'Hindustan Times Print Edition'
|
||||
language = 'en_IN'
|
||||
@ -100,7 +101,6 @@ class ht(BasicNewsRecipe):
|
||||
feeds_dict[section].append({'title': title, 'description': desc, 'url': url})
|
||||
return list(feeds_dict.items())
|
||||
|
||||
|
||||
def preprocess_raw_html(self, raw, *a):
|
||||
data = json.loads(raw)
|
||||
body = ''
|
||||
|
@ -64,4 +64,3 @@ class Hurriyet(BasicNewsRecipe):
|
||||
(u'Ankara', 'https://www.hurriyet.com.tr/rss/ankara'),
|
||||
(u'Ege', 'https://www.hurriyet.com.tr/rss/ege')
|
||||
]
|
||||
|
||||
|
@ -8,6 +8,7 @@ def absurl(url):
|
||||
if url.startswith('/'):
|
||||
return 'https://www.infzm.com' + url
|
||||
|
||||
|
||||
def json_to_html(raw, link):
|
||||
data = json.loads(raw)
|
||||
data = data['data']['content']
|
||||
@ -51,7 +52,6 @@ class infzm(BasicNewsRecipe):
|
||||
.cm_pic_caption, .cm_pic_author { font-size:small; text-align:center; }
|
||||
'''
|
||||
|
||||
|
||||
def parse_index(self):
|
||||
index = 'https://www.infzm.com/'
|
||||
sections = [
|
||||
|
@ -47,7 +47,6 @@ class inc42(BasicNewsRecipe):
|
||||
feeds.append((section, articles))
|
||||
return feeds
|
||||
|
||||
|
||||
def preprocess_html(self, soup):
|
||||
for img in soup.findAll('img', attrs={'data-src':True}):
|
||||
img['src'] = img['data-src']
|
||||
|
@ -20,4 +20,3 @@ class IndiaSpeaksReddit(BasicNewsRecipe):
|
||||
feeds = [
|
||||
('India Speaks Reddit main feed', 'https://www.reddit.com/r/IndiaSpeaks.rss'),
|
||||
]
|
||||
|
||||
|
@ -17,4 +17,3 @@ class Kosmonauta(BasicNewsRecipe):
|
||||
remove_attributes = ['style']
|
||||
max_articles_per_feed = 100
|
||||
feeds = [(u'Kosmonauta.net', u'http://www.kosmonauta.net/feed')]
|
||||
|
||||
|
@ -21,12 +21,14 @@ def resize(x):
|
||||
if '_750' in k:
|
||||
return v
|
||||
|
||||
|
||||
m_fr = {
|
||||
1: 'Janvier', 2: 'Février', 3: 'Mars', 4: 'Avril',
|
||||
5: 'Mai', 6: 'Juin', 7: 'Juillet', 8: 'Août',
|
||||
9: 'Septembre', 10: 'Octobre', 11: 'Novembre', 12: 'Décembre'
|
||||
}
|
||||
|
||||
|
||||
def json_to_html(raw):
|
||||
data = json.loads(raw)
|
||||
|
||||
|
@ -6,6 +6,7 @@ def absurl(url):
|
||||
if url.startswith('/'):
|
||||
return 'https://www.livelaw.in' + url
|
||||
|
||||
|
||||
class livelaw(BasicNewsRecipe):
|
||||
title = 'Live Law'
|
||||
__author__ = 'unkn0wn'
|
||||
|
@ -14,6 +14,7 @@ def absurl(x):
|
||||
x = 'https://www.newyorker.com' + x
|
||||
return x
|
||||
|
||||
|
||||
class NewYorker(BasicNewsRecipe):
|
||||
|
||||
title = 'The New Yorker Magazine'
|
||||
@ -129,7 +130,6 @@ class NewYorker(BasicNewsRecipe):
|
||||
feeds_dict[section].append({'title': title, 'url': url, 'description': desc})
|
||||
return feeds_dict.items()
|
||||
|
||||
|
||||
# The New Yorker changes the content it delivers based on cookies, so the
|
||||
# following ensures that we send no cookies
|
||||
def get_browser(self, *args, **kwargs):
|
||||
|
@ -36,4 +36,3 @@ class ReutersJa(BasicNewsRecipe):
|
||||
for img in soup.findAll('img', attrs={'data-src':True}):
|
||||
img['src'] = img['data-src']
|
||||
return soup
|
||||
|
||||
|
@ -38,4 +38,3 @@ class Nordjyske_dk(BasicNewsRecipe):
|
||||
('Aalborg', 'http://nordjyske.dk/rss/aalborg'),
|
||||
|
||||
]
|
||||
|
||||
|
@ -97,7 +97,6 @@ class Nzz(BasicNewsRecipe):
|
||||
|
||||
return url
|
||||
|
||||
|
||||
def get_browser(self, *args, **kwargs):
|
||||
kwargs['user_agent'] = 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)'
|
||||
br = BasicNewsRecipe.get_browser(self, *args, **kwargs)
|
||||
|
@ -18,4 +18,3 @@ class PajamasMedia(BasicNewsRecipe):
|
||||
'http://feeds.feedburner.com/PajamasMedia'),
|
||||
|
||||
]
|
||||
|
||||
|
@ -24,6 +24,7 @@ def classes(classes):
|
||||
return dict(attrs={
|
||||
'class': lambda x: x and frozenset(x.split()).intersection(q)})
|
||||
|
||||
|
||||
class RadioCanada(BasicNewsRecipe):
|
||||
title = 'Radio Canada'
|
||||
__author__ = 'quatorze, pticrix'
|
||||
|
@ -79,7 +79,6 @@ class RND(BasicNewsRecipe):
|
||||
#('E-Mobility', 'https://www.rnd.de/arc/outboundfeeds/rss/category/e-mobility/')
|
||||
]
|
||||
|
||||
|
||||
def parse_feeds(self):
|
||||
# Call parent's method.
|
||||
feeds = BasicNewsRecipe.parse_feeds(self)
|
||||
|
@ -193,7 +193,6 @@ class Saechsische(BasicNewsRecipe):
|
||||
#('Beruf & Bildung', 'https://www.saechsische.de/arc/outboundfeeds/rss/category/beruf-und-bildung')
|
||||
]
|
||||
|
||||
|
||||
def parse_feeds(self):
|
||||
# Call parent's method.
|
||||
feeds = BasicNewsRecipe.parse_feeds(self)
|
||||
|
@ -10,6 +10,7 @@ def classes(classes):
|
||||
return dict(attrs={
|
||||
'class': lambda x: x and frozenset(x.split()).intersection(q)})
|
||||
|
||||
|
||||
class Salon_com(BasicNewsRecipe):
|
||||
|
||||
title = 'Salon.com'
|
||||
|
@ -20,6 +20,7 @@ def E(parent, name, text='', **attrs):
|
||||
parent.append(ans)
|
||||
return ans
|
||||
|
||||
|
||||
def process_node(node, html_parent):
|
||||
ntype = node.get('type')
|
||||
|
||||
@ -45,6 +46,7 @@ def ts_date(x):
|
||||
dt = datetime.fromtimestamp(x/1000 + time.timezone)
|
||||
return dt.strftime('%b %d, %Y at %I:%M %p')
|
||||
|
||||
|
||||
def load_article_from_json(raw, root):
|
||||
# open('/t/raw.json', 'w').write(raw)
|
||||
data = json.loads(raw)['props']['pageProps']['payload']['data']['article']
|
||||
|
@ -25,5 +25,4 @@ class Ria_eng(BasicNewsRecipe):
|
||||
'comment': description, 'tags': category, 'language': language
|
||||
}
|
||||
|
||||
|
||||
feeds = [(u'News', u'https://sputnikglobe.com/export/rss2/archive/index.xml')]
|
||||
|
@ -70,4 +70,3 @@ class TagesspiegelRss(BasicNewsRecipe):
|
||||
(u'Medien', u'http://www.tagesspiegel.de/contentexport/feed/medien'),
|
||||
(u'Wissen', u'http://www.tagesspiegel.de/contentexport/feed/wissen')
|
||||
]
|
||||
|
||||
|
@ -27,7 +27,6 @@ class Tehelka(BasicNewsRecipe):
|
||||
use_embedded_content = False
|
||||
ignore_duplicate_articles = {'title', 'url'}
|
||||
|
||||
|
||||
feeds = [
|
||||
('Tehelka', 'http://tehelka.com/rss'),
|
||||
]
|
||||
|
@ -35,7 +35,6 @@ class SaturdayPaper(BasicNewsRecipe):
|
||||
{'name': 'div', 'class': 'end-matter'},
|
||||
]
|
||||
|
||||
|
||||
def get_cover_url(self):
|
||||
soup = self.index_to_soup('https://www.thesaturdaypaper.com.au/editions/')
|
||||
div = soup.find('div', attrs={'class':'article__image'})
|
||||
|
@ -196,7 +196,6 @@ class PrivateEyeRecipe(BasicNewsRecipe):
|
||||
|
||||
return soup
|
||||
|
||||
|
||||
# Remove features not wanted and tweak HTML
|
||||
preprocess_regexps = [
|
||||
# Remove big blank spaces
|
||||
|
@ -11,11 +11,13 @@ def resize(x):
|
||||
elif '?crop=' in x:
|
||||
return x + '&resize=600'
|
||||
|
||||
|
||||
def absurl(url):
|
||||
if url.startswith('/'):
|
||||
url = 'https://www.thetimes.com' + url
|
||||
return url
|
||||
|
||||
|
||||
class times(BasicNewsRecipe):
|
||||
title = 'The Times and Sunday Times'
|
||||
__author__ = 'unkn0wn'
|
||||
|
@ -14,6 +14,7 @@ def re_html(y):
|
||||
return soup.text
|
||||
return ''
|
||||
|
||||
|
||||
def get_id(url):
|
||||
rq = browser().open(url)
|
||||
return re.search(r'\?p=(\S+)>', str(rq.info())).group(1)
|
||||
|
@ -23,6 +23,7 @@ date_ = dt.strftime('%d_%m_%Y')
|
||||
index = 'https://asset.harnscloud.com/PublicationData/TOI/' + le + '/' + date0
|
||||
img_index = 'https://cmsimages.timesgroup.com/image-resizer?epaper_s3_path=PublicationData/TOI/' + le + '/' + date0
|
||||
|
||||
|
||||
def handle_images(x, soup):
|
||||
img = soup.find('img')
|
||||
if img:
|
||||
@ -36,6 +37,7 @@ def handle_images(x, soup):
|
||||
for lead in reversed(soup.findAll('div', attrs={'class':'lead'})):
|
||||
x.insert_after(lead)
|
||||
|
||||
|
||||
class toiprint(BasicNewsRecipe):
|
||||
title = 'TOI Print Edition'
|
||||
language = 'en_IN'
|
||||
|
@ -14,10 +14,12 @@ def classes(classes):
|
||||
return dict(attrs={
|
||||
'class': lambda x: x and frozenset(x.split()).intersection(q)})
|
||||
|
||||
|
||||
def absurl(url):
|
||||
if url.startswith('/'):
|
||||
return 'https://www.usatoday.com' + url
|
||||
|
||||
|
||||
class USAToday(BasicNewsRecipe):
|
||||
|
||||
title = 'USA Today'
|
||||
|
@ -28,6 +28,7 @@ except ImportError:
|
||||
|
||||
needs_subscription = False
|
||||
|
||||
|
||||
class WSJ(BasicNewsRecipe):
|
||||
|
||||
if needs_subscription:
|
||||
|
@ -36,6 +36,7 @@ select = [
|
||||
'RUF055', # unnecessary regex
|
||||
'RUF039', # always use raw-string for regex
|
||||
'RUF047', # needless else
|
||||
'E302', 'E303', 'E304', 'E305', 'W391', # blank-line standard
|
||||
]
|
||||
|
||||
[lint.per-file-ignores]
|
||||
@ -49,7 +50,7 @@ select = [
|
||||
"src/calibre/gui2/tts/manager.py" = ['UP037']
|
||||
"src/calibre/utils/copy_files.py" = ['UP037']
|
||||
"src/calibre/utils/smartypants.py" = ['RUF039', 'RUF055']
|
||||
"src/qt/*.py" = ['I']
|
||||
"src/qt/*.py" = ['I', 'E302']
|
||||
"src/qt/*.pyi" = ['I']
|
||||
|
||||
[lint.isort]
|
||||
|
1
setup.py
1
setup.py
@ -29,7 +29,6 @@ def check_version_info():
|
||||
exit(f'calibre requires Python {minver}. Current Python version: {".".join(map(str, sys.version_info[:3]))}')
|
||||
|
||||
|
||||
|
||||
check_version_info()
|
||||
|
||||
sys.path.insert(0, src_base)
|
||||
|
@ -23,6 +23,7 @@ isunix = islinux or ismacos or isbsd or ishaiku
|
||||
|
||||
py_lib = os.path.join(sys.prefix, 'libs', 'python{}{}.lib'.format(*sys.version_info[:2]))
|
||||
|
||||
|
||||
class CompileCommand(NamedTuple):
|
||||
cmd: list[str]
|
||||
src: str
|
||||
@ -145,7 +146,6 @@ def parse_extension(ext, compiling_for='native'):
|
||||
if compiling_for == 'windows':
|
||||
get_key = 'windows_'
|
||||
|
||||
|
||||
def get(k, default=''):
|
||||
ans = ext.pop(k, default)
|
||||
ans = ext.pop(get_key + k, ans)
|
||||
@ -242,7 +242,6 @@ class Environment(NamedTuple):
|
||||
return list(map(map_name, libs))
|
||||
|
||||
|
||||
|
||||
def init_env(debug=False, sanitize=False, compiling_for='native'):
|
||||
from setup.build_environment import NMAKE, win_cc, win_inc, win_ld, win_lib
|
||||
linker = None
|
||||
|
@ -10,6 +10,7 @@ import subprocess
|
||||
|
||||
BASE = '/srv/download/bw'
|
||||
|
||||
|
||||
def main():
|
||||
if not os.path.exists(BASE):
|
||||
os.makedirs(BASE)
|
||||
@ -52,5 +53,6 @@ def main():
|
||||
with open('index.html', 'wb') as f:
|
||||
f.write(html.encode('utf-8'))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
@ -69,7 +69,6 @@ class ReadFileWithProgressReporting: # {{{
|
||||
)
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
# }}}
|
||||
|
||||
|
||||
@ -93,7 +92,6 @@ class Base: # {{{
|
||||
print('_' * 50)
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
# }}}
|
||||
|
||||
|
||||
@ -127,7 +125,6 @@ class SourceForge(Base): # {{{
|
||||
break
|
||||
print('Uploaded in', int(time.time() - start), 'seconds\n\n')
|
||||
|
||||
|
||||
# }}}
|
||||
|
||||
|
||||
@ -259,7 +256,6 @@ class GitHub(Base): # {{{
|
||||
self.fail(r, f'Failed to create release for version: {self.version}')
|
||||
return r.json()
|
||||
|
||||
|
||||
# }}}
|
||||
|
||||
|
||||
@ -388,10 +384,9 @@ def generate_index(): # {{{
|
||||
f.write(index.encode('utf-8'))
|
||||
finally:
|
||||
os.chdir('..')
|
||||
|
||||
|
||||
# }}}
|
||||
|
||||
|
||||
SERVER_BASE = '/srv/download/'
|
||||
|
||||
|
||||
@ -432,9 +427,6 @@ def upload_to_servers(files, version): # {{{
|
||||
# else:
|
||||
# break
|
||||
# print('Uploaded in', int(time.time() - start), 'seconds\n\n')
|
||||
#
|
||||
|
||||
|
||||
# }}}
|
||||
|
||||
|
||||
|
@ -25,6 +25,7 @@ def generate_data():
|
||||
ans.append((x, nl(getattr(locale, x.upper()))))
|
||||
return ans
|
||||
|
||||
|
||||
def main():
|
||||
if sys.version_info[0] < 3: # noqa: UP036
|
||||
raise RuntimeError('Must be run using python 3.x')
|
||||
|
@ -1,7 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
# License: GPLv3 Copyright: 2013, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
|
||||
|
||||
# Imports {{{
|
||||
import argparse
|
||||
import ast
|
||||
@ -151,8 +150,8 @@ def load_plugins_index():
|
||||
raise
|
||||
return json.loads(bz2.decompress(raw))
|
||||
|
||||
# Get metadata from plugin zip file {{{
|
||||
|
||||
# Get metadata from plugin zip file {{{
|
||||
|
||||
def convert_node(fields, x, names={}, import_data=None):
|
||||
name = x.__class__.__name__
|
||||
@ -357,9 +356,9 @@ def get_plugin_info(raw_zip):
|
||||
return json.loads(res.stdout)
|
||||
raise
|
||||
|
||||
|
||||
# }}}
|
||||
|
||||
|
||||
def update_plugin_from_entry(plugin, entry):
|
||||
plugin['index_name'] = entry.name
|
||||
plugin['thread_url'] = entry.url
|
||||
@ -706,7 +705,6 @@ def test_parse(): # {{{
|
||||
if new_url != full_url:
|
||||
print(f'new url ({aname}): {new_url} != {full_url} for plugin at: {url}')
|
||||
raise SystemExit(1)
|
||||
|
||||
# }}}
|
||||
|
||||
|
||||
@ -740,7 +738,6 @@ class HelloWorld(FileTypePlugin):
|
||||
zf.writestr('very/ver.py', b'MV = (0, 7, 53)')
|
||||
zf.writestr('__init__.py', b'from xxx import yyy\nfrom very.lovely import HelloWorld')
|
||||
assert get_plugin_info(buf.getvalue()) == vals
|
||||
|
||||
# }}}
|
||||
|
||||
|
||||
|
@ -65,7 +65,6 @@ class Test(BaseTest):
|
||||
ffmpeg_dll_dir = os.path.join(SW, 'ffmpeg', 'bin')
|
||||
os.add_dll_directory(ffmpeg_dll_dir)
|
||||
|
||||
|
||||
from calibre.utils.run_tests import filter_tests_by_name, find_tests, remove_tests_by_name, run_cli
|
||||
tests = find_tests(which_tests=frozenset(opts.test_module), exclude_tests=frozenset(opts.exclude_test_module))
|
||||
if opts.test_name:
|
||||
|
@ -607,7 +607,6 @@ class Translations(POT): # {{{
|
||||
if os.path.exists(destbase):
|
||||
shutil.rmtree(destbase)
|
||||
shutil.rmtree(self.cache_dir)
|
||||
|
||||
# }}}
|
||||
|
||||
|
||||
@ -756,7 +755,6 @@ class GetTranslations(Translations): # {{{
|
||||
cc('git add */*.po'.split())
|
||||
cc('git commit -am'.split() + [msg or 'Updated translations'])
|
||||
cc('git push'.split())
|
||||
|
||||
# }}}
|
||||
|
||||
|
||||
@ -817,7 +815,6 @@ class ISO639(Command): # {{{
|
||||
def clean(self):
|
||||
if os.path.exists(self.DEST):
|
||||
os.remove(self.DEST)
|
||||
|
||||
# }}}
|
||||
|
||||
|
||||
|
@ -98,7 +98,6 @@ class ReUpload(Command): # {{{
|
||||
if os.path.exists(x):
|
||||
os.remove(x)
|
||||
|
||||
|
||||
# }}}
|
||||
|
||||
|
||||
@ -159,7 +158,6 @@ def run_remote_upload(args):
|
||||
'python', 'hosting.py'
|
||||
] + args)
|
||||
|
||||
|
||||
# }}}
|
||||
|
||||
|
||||
@ -313,7 +311,6 @@ class UploadInstallers(Command): # {{{
|
||||
def upload_to_calibre(self):
|
||||
run_remote_upload(calibre_cmdline(__version__))
|
||||
|
||||
|
||||
# }}}
|
||||
|
||||
|
||||
@ -355,7 +352,6 @@ class UploadUserManual(Command): # {{{
|
||||
)
|
||||
check_call('ssh main chown -R http:http /srv/manual'.split())
|
||||
|
||||
|
||||
# }}}
|
||||
|
||||
|
||||
@ -382,7 +378,6 @@ class UploadDemo(Command): # {{{
|
||||
|
||||
check_call(f'scp /tmp/html-demo.zip main:{DOWNLOADS}/', shell=True)
|
||||
|
||||
|
||||
# }}}
|
||||
|
||||
|
||||
@ -410,5 +405,4 @@ class UploadToServer(Command): # {{{
|
||||
f'ssh main /usr/local/bin/update-calibre-version.py {__version__} && /usr/local/bin/update-calibre-code.py && /apps/static/generate.py'
|
||||
).split())
|
||||
|
||||
|
||||
# }}}
|
||||
|
@ -128,7 +128,6 @@ def query_vcvarsall(is64bit=True):
|
||||
comn_tools[k] = int(m.group(1))
|
||||
comntools = sorted(comn_tools, key=comn_tools.__getitem__)[-1]
|
||||
|
||||
|
||||
def g(k):
|
||||
try:
|
||||
return env[k]
|
||||
|
@ -176,6 +176,7 @@ def download_item(dest_dir: str, file: File):
|
||||
raise SystemExit(f'The hash for {file.filename} does not match.'
|
||||
f' {m.hexdigest()} != {file.sha256}')
|
||||
|
||||
|
||||
def cabinets_in_msi(path):
|
||||
raw = subprocess.check_output(['msiinfo', 'export', path, 'Media']).decode('utf-8')
|
||||
return re.findall(r'\S+\.cab', raw)
|
||||
|
@ -450,6 +450,7 @@ def my_unichr(num):
|
||||
except (ValueError, OverflowError):
|
||||
return '?'
|
||||
|
||||
|
||||
XML_ENTITIES = {
|
||||
'"' : '"',
|
||||
"'" : ''',
|
||||
@ -458,6 +459,7 @@ XML_ENTITIES = {
|
||||
'&' : '&'
|
||||
}
|
||||
|
||||
|
||||
def entity_to_unicode(match, exceptions=(), encoding=None, result_exceptions={}):
|
||||
'''
|
||||
:param match: A match object such that '&'+match.group(1)';' is the entity.
|
||||
|
@ -410,7 +410,6 @@ else:
|
||||
atexit.register(cleanup_cdir)
|
||||
# }}}
|
||||
|
||||
|
||||
is_running_from_develop = False
|
||||
if getattr(sys, 'frozen', False):
|
||||
try:
|
||||
|
@ -475,6 +475,7 @@ class MetadataReaderPlugin(Plugin): # {{{
|
||||
:return: A :class:`calibre.ebooks.metadata.book.Metadata` object
|
||||
'''
|
||||
return None
|
||||
|
||||
# }}}
|
||||
|
||||
|
||||
|
@ -11,8 +11,8 @@ from calibre.ebooks.metadata.archive import ArchiveExtract, KPFExtract, get_comi
|
||||
|
||||
plugins = []
|
||||
|
||||
# To archive plugins {{{
|
||||
|
||||
# To archive plugins {{{
|
||||
|
||||
class PML2PMLZ(FileTypePlugin):
|
||||
name = 'PML to PMLZ'
|
||||
@ -96,8 +96,8 @@ class TXT2TXTZ(FileTypePlugin):
|
||||
plugins += [HTML2ZIP, PML2PMLZ, TXT2TXTZ, ArchiveExtract, KPFExtract]
|
||||
# }}}
|
||||
|
||||
# Metadata reader plugins {{{
|
||||
|
||||
# Metadata reader plugins {{{
|
||||
|
||||
class ComicMetadataReader(MetadataReaderPlugin):
|
||||
|
||||
@ -434,8 +434,8 @@ plugins += [x for x in list(locals().values()) if isinstance(x, type) and
|
||||
|
||||
# }}}
|
||||
|
||||
# Metadata writer plugins {{{
|
||||
|
||||
# Metadata writer plugins {{{
|
||||
|
||||
class EPUBMetadataWriter(MetadataWriterPlugin):
|
||||
|
||||
@ -835,7 +835,6 @@ plugins += [
|
||||
USER_DEFINED,
|
||||
]
|
||||
|
||||
|
||||
# }}}
|
||||
|
||||
# New metadata download plugins {{{
|
||||
@ -850,8 +849,8 @@ plugins += [GoogleBooks, GoogleImages, Amazon, Edelweiss, OpenLibrary, BigBookSe
|
||||
|
||||
# }}}
|
||||
|
||||
# Interface Actions {{{
|
||||
|
||||
# Interface Actions {{{
|
||||
|
||||
class ActionAdd(InterfaceActionBase):
|
||||
name = 'Add Books'
|
||||
@ -1137,6 +1136,7 @@ class ActionAllActions(InterfaceActionBase):
|
||||
actual_plugin = 'calibre.gui2.actions.all_actions:AllGUIActions'
|
||||
description = _('Open a menu showing all installed GUI actions')
|
||||
|
||||
|
||||
class ActionVirtualLibrary(InterfaceActionBase):
|
||||
name = 'Virtual Library'
|
||||
actual_plugin = 'calibre.gui2.actions.virtual_library:VirtualLibraryAction'
|
||||
@ -1183,8 +1183,8 @@ plugins += [ActionAdd, ActionAllActions, ActionFetchAnnotations, ActionGenerateC
|
||||
|
||||
# }}}
|
||||
|
||||
# Preferences Plugins {{{
|
||||
|
||||
# Preferences Plugins {{{
|
||||
|
||||
class LookAndFeel(PreferencesPlugin):
|
||||
name = 'Look & Feel'
|
||||
@ -1460,8 +1460,8 @@ plugins += [LookAndFeel, Behavior, Columns, Toolbar, Search, InputOptions,
|
||||
|
||||
# }}}
|
||||
|
||||
# Store plugins {{{
|
||||
|
||||
# Store plugins {{{
|
||||
|
||||
class StoreAmazonKindleStore(StoreBase):
|
||||
name = 'Amazon Kindle'
|
||||
|
@ -11,7 +11,6 @@ from calibre.customize import Plugin
|
||||
|
||||
|
||||
class ConversionOption:
|
||||
|
||||
'''
|
||||
Class representing conversion options
|
||||
'''
|
||||
@ -127,7 +126,6 @@ def gui_configuration_widget(name, parent, get_option_by_name,
|
||||
|
||||
|
||||
class InputFormatPlugin(Plugin):
|
||||
|
||||
'''
|
||||
InputFormatPlugins are responsible for converting a document into
|
||||
HTML+OPF+CSS+etc.
|
||||
@ -275,7 +273,6 @@ class InputFormatPlugin(Plugin):
|
||||
|
||||
|
||||
class OutputFormatPlugin(Plugin):
|
||||
|
||||
'''
|
||||
OutputFormatPlugins are responsible for converting an OEB document
|
||||
(OPF+HTML) into an output e-book.
|
||||
|
@ -34,8 +34,8 @@ class Plugin(_Plugin):
|
||||
self.width_pts = self.width * 72./self.dpi
|
||||
self.height_pts = self.height * 72./self.dpi
|
||||
|
||||
# Input profiles {{{
|
||||
|
||||
# Input profiles {{{
|
||||
|
||||
class InputProfile(Plugin):
|
||||
|
||||
|
@ -74,11 +74,10 @@ def load_plugin(path_to_zip_file): # {{{
|
||||
:return: A :class:`Plugin` instance.
|
||||
'''
|
||||
return loader.load(path_to_zip_file)
|
||||
|
||||
# }}}
|
||||
|
||||
# Enable/disable plugins {{{
|
||||
|
||||
# Enable/disable plugins {{{
|
||||
|
||||
def disable_plugin(plugin_or_name):
|
||||
x = getattr(plugin_or_name, 'name', plugin_or_name)
|
||||
@ -131,8 +130,8 @@ def is_disabled(plugin):
|
||||
plugin.name in default_disabled_plugins
|
||||
# }}}
|
||||
|
||||
# File type plugins {{{
|
||||
|
||||
# File type plugins {{{
|
||||
|
||||
_on_import = {}
|
||||
_on_postimport = {}
|
||||
@ -270,8 +269,8 @@ def run_plugins_on_postadd(db, book_id, fmt_map):
|
||||
|
||||
# }}}
|
||||
|
||||
# Plugin customization {{{
|
||||
|
||||
# Plugin customization {{{
|
||||
|
||||
def customize_plugin(plugin, custom):
|
||||
d = config['plugin_customization']
|
||||
@ -284,8 +283,8 @@ def plugin_customization(plugin):
|
||||
|
||||
# }}}
|
||||
|
||||
# Input/Output profiles {{{
|
||||
|
||||
# Input/Output profiles {{{
|
||||
|
||||
def input_profiles():
|
||||
for plugin in _initialized_plugins:
|
||||
@ -299,8 +298,8 @@ def output_profiles():
|
||||
yield plugin
|
||||
# }}}
|
||||
|
||||
# Interface Actions # {{{
|
||||
|
||||
# Interface Actions # {{{
|
||||
|
||||
def interface_actions():
|
||||
customization = config['plugin_customization']
|
||||
@ -311,8 +310,8 @@ def interface_actions():
|
||||
yield plugin
|
||||
# }}}
|
||||
|
||||
# Preferences Plugins # {{{
|
||||
|
||||
# Preferences Plugins # {{{
|
||||
|
||||
def preferences_plugins():
|
||||
customization = config['plugin_customization']
|
||||
@ -323,8 +322,8 @@ def preferences_plugins():
|
||||
yield plugin
|
||||
# }}}
|
||||
|
||||
# Library Closed Plugins # {{{
|
||||
|
||||
# Library Closed Plugins # {{{
|
||||
|
||||
def available_library_closed_plugins():
|
||||
customization = config['plugin_customization']
|
||||
@ -343,8 +342,8 @@ def has_library_closed_plugins():
|
||||
return False
|
||||
# }}}
|
||||
|
||||
# Store Plugins # {{{
|
||||
|
||||
# Store Plugins # {{{
|
||||
|
||||
def store_plugins():
|
||||
customization = config['plugin_customization']
|
||||
@ -375,8 +374,8 @@ def available_stores():
|
||||
|
||||
# }}}
|
||||
|
||||
# Metadata read/write {{{
|
||||
|
||||
# Metadata read/write {{{
|
||||
|
||||
_metadata_readers = {}
|
||||
_metadata_writers = {}
|
||||
@ -519,8 +518,8 @@ def can_set_metadata(ftype):
|
||||
|
||||
# }}}
|
||||
|
||||
# Add/remove plugins {{{
|
||||
|
||||
# Add/remove plugins {{{
|
||||
|
||||
def add_plugin(path_to_zip_file):
|
||||
make_config_dir()
|
||||
@ -565,8 +564,8 @@ def remove_plugin(plugin_or_name):
|
||||
|
||||
# }}}
|
||||
|
||||
# Input/Output format plugins {{{
|
||||
|
||||
# Input/Output format plugins {{{
|
||||
|
||||
def input_format_plugins():
|
||||
for plugin in _initialized_plugins:
|
||||
@ -623,8 +622,8 @@ def available_output_formats():
|
||||
|
||||
# }}}
|
||||
|
||||
# Catalog plugins {{{
|
||||
|
||||
# Catalog plugins {{{
|
||||
|
||||
def catalog_plugins():
|
||||
for plugin in _initialized_plugins:
|
||||
@ -648,8 +647,8 @@ def plugin_for_catalog_format(fmt):
|
||||
|
||||
# }}}
|
||||
|
||||
# Device plugins {{{
|
||||
|
||||
# Device plugins {{{
|
||||
|
||||
def device_plugins(include_disabled=False):
|
||||
for plugin in _initialized_plugins:
|
||||
@ -670,8 +669,8 @@ def disabled_device_plugins():
|
||||
yield plugin
|
||||
# }}}
|
||||
|
||||
# Metadata sources2 {{{
|
||||
|
||||
# Metadata sources2 {{{
|
||||
|
||||
def metadata_plugins(capabilities):
|
||||
capabilities = frozenset(capabilities)
|
||||
@ -702,8 +701,8 @@ def patch_metadata_plugins(possibly_updated_plugins):
|
||||
_initialized_plugins[i] = pup
|
||||
# }}}
|
||||
|
||||
# Editor plugins {{{
|
||||
|
||||
# Editor plugins {{{
|
||||
|
||||
def all_edit_book_tool_plugins():
|
||||
for plugin in _initialized_plugins:
|
||||
@ -711,8 +710,8 @@ def all_edit_book_tool_plugins():
|
||||
yield plugin
|
||||
# }}}
|
||||
|
||||
# Initialize plugins {{{
|
||||
|
||||
# Initialize plugins {{{
|
||||
|
||||
_initialized_plugins = []
|
||||
|
||||
@ -823,8 +822,8 @@ def initialized_plugins():
|
||||
|
||||
# }}}
|
||||
|
||||
# CLI {{{
|
||||
|
||||
# CLI {{{
|
||||
|
||||
def build_plugin(path):
|
||||
from calibre import prints
|
||||
|
@ -197,8 +197,8 @@ class DBPrefs(dict): # {{{
|
||||
return json.load(f, object_hook=from_json)
|
||||
# }}}
|
||||
|
||||
# Extra collators {{{
|
||||
|
||||
# Extra collators {{{
|
||||
|
||||
def pynocase(one, two, encoding='utf-8'):
|
||||
if isbytestring(one):
|
||||
@ -226,8 +226,8 @@ def icu_collator(s1, s2):
|
||||
|
||||
# }}}
|
||||
|
||||
# Unused aggregators {{{
|
||||
|
||||
# Unused aggregators {{{
|
||||
|
||||
def Concatenate(sep=','):
|
||||
'''String concatenation aggregator for sqlite'''
|
||||
|
@ -135,7 +135,6 @@ dynamic_category_preferences = frozenset({'grouped_search_make_user_categories',
|
||||
|
||||
|
||||
class Cache:
|
||||
|
||||
'''
|
||||
An in-memory cache of the metadata.db file from a calibre library.
|
||||
This class also serves as a threadsafe API for accessing the database.
|
||||
|
@ -189,6 +189,7 @@ def sort_key_for_name_and_first_letter(x, hierarchical_categories=()):
|
||||
return (c if numeric_collation and c.isdigit() else '9999999999',
|
||||
collation_order(v2), sort_key(v1))
|
||||
|
||||
|
||||
def sort_key_for_name(x, hierarchical_categories=()):
|
||||
v = x.sort or x.name
|
||||
if x.category not in hierarchical_categories:
|
||||
|
@ -96,8 +96,6 @@ see the different options, specify the name of the output file and then the
|
||||
add_plugin_parser_options(fmt, parser)
|
||||
|
||||
return parser
|
||||
|
||||
|
||||
# }}}
|
||||
|
||||
|
||||
|
@ -16,6 +16,7 @@ BOOK_ID_PATH_TEMPLATE = ' ({})'
|
||||
RESOURCE_URL_SCHEME = 'calres'
|
||||
TEMPLATE_ICON_INDICATOR = ' template ' # Item values cannot start or end with space
|
||||
|
||||
|
||||
@dataclass
|
||||
class TrashEntry:
|
||||
book_id: int
|
||||
|
@ -164,7 +164,6 @@ class ThreadSafePrefs(MutableMapping):
|
||||
|
||||
|
||||
class LibraryDatabase:
|
||||
|
||||
''' Emulate the old LibraryDatabase2 interface '''
|
||||
|
||||
PATH_LIMIT = DB.PATH_LIMIT
|
||||
|
@ -25,6 +25,7 @@ from calibre.utils.icu import lower as icu_lower
|
||||
if iswindows:
|
||||
from calibre_extensions import winutil
|
||||
|
||||
|
||||
class cmt(str):
|
||||
pass
|
||||
|
||||
|
@ -28,8 +28,8 @@ EQUALS_MATCH = 1
|
||||
REGEXP_MATCH = 2
|
||||
ACCENT_MATCH = 3
|
||||
|
||||
# Utils {{{
|
||||
|
||||
# Utils {{{
|
||||
|
||||
def _matchkind(query, case_sensitive=False):
|
||||
matchkind = CONTAINS_MATCH
|
||||
|
@ -20,6 +20,7 @@ from polyglot.builtins import iteritems, itervalues
|
||||
def identity(x):
|
||||
return x
|
||||
|
||||
|
||||
def c_parse(val):
|
||||
try:
|
||||
year, month, day, hour, minutes, seconds, tzsecs = _c_speedup(val)
|
||||
@ -90,7 +91,6 @@ class Table:
|
||||
|
||||
|
||||
class VirtualTable(Table):
|
||||
|
||||
'''
|
||||
A dummy table used for fields that only exist in memory like ondevice
|
||||
'''
|
||||
@ -102,7 +102,6 @@ class VirtualTable(Table):
|
||||
|
||||
|
||||
class OneToOneTable(Table):
|
||||
|
||||
'''
|
||||
Represents data that is unique per book (it may not actually be unique) but
|
||||
each item is assigned to a book in a one-to-one mapping. For example: uuid,
|
||||
@ -197,7 +196,6 @@ class CompositeTable(OneToOneTable):
|
||||
|
||||
|
||||
class ManyToOneTable(Table):
|
||||
|
||||
'''
|
||||
Represents data where one data item can map to many books, for example:
|
||||
series or publisher.
|
||||
@ -409,7 +407,6 @@ class RatingTable(ManyToOneTable):
|
||||
|
||||
|
||||
class ManyToManyTable(ManyToOneTable):
|
||||
|
||||
'''
|
||||
Represents data that has a many-to-many mapping with books. i.e. each book
|
||||
can have more than one value and each value can be mapped to more than one
|
||||
|
@ -4,6 +4,3 @@
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2011, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
|
||||
|
||||
|
@ -160,7 +160,6 @@ class FilesystemTest(BaseTest):
|
||||
self.assertEqual(cache.rename_extra_files(1, {'B': 'data/c'}), set())
|
||||
self.assertEqual(cache.rename_extra_files(1, {'B': 'data/c'}, replace=True), {'B'})
|
||||
|
||||
|
||||
@unittest.skipUnless(iswindows, 'Windows only')
|
||||
def test_windows_atomic_move(self):
|
||||
'Test book file open in another process when changing metadata'
|
||||
|
@ -78,7 +78,6 @@ def run_funcs(self, db, ndb, funcs):
|
||||
|
||||
|
||||
class LegacyTest(BaseTest):
|
||||
|
||||
''' Test the emulation of the legacy interface. '''
|
||||
|
||||
def test_library_wide_properties(self): # {{{
|
||||
|
@ -22,6 +22,7 @@ def test_notes_restore(self: 'NotesTest'):
|
||||
doc2 = 'simple notes for an author2'
|
||||
cache.set_notes_for('authors', authors[1], doc2, resource_hashes=(h2,))
|
||||
|
||||
|
||||
def test_notes_api(self: 'NotesTest'):
|
||||
cache, notes = self.create_notes_db()
|
||||
authors = sorted(cache.all_field_ids('authors'))
|
||||
@ -81,6 +82,7 @@ def test_notes_api(self: 'NotesTest'):
|
||||
cache.set_notes_for('authors', authors[0], '', resource_hashes=())
|
||||
self.ae(len(os.listdir(notes.retired_dir)), 1)
|
||||
|
||||
|
||||
def test_cache_api(self: 'NotesTest'):
|
||||
cache, notes = self.create_notes_db()
|
||||
authors = cache.field_for('authors', 1)
|
||||
|
@ -712,7 +712,6 @@ class ReadingTest(BaseTest):
|
||||
self.assertRaises(NotImplementedError, pmi.template_to_attribute, {}, {})
|
||||
self.assertRaises(NotImplementedError, pmi.smart_update, {})
|
||||
|
||||
|
||||
# }}}
|
||||
|
||||
def test_marked_field(self): # {{{
|
||||
|
@ -920,7 +920,6 @@ class WritingTest(BaseTest):
|
||||
cache.restore_annotations(1, list(opf.read_annotations()))
|
||||
amap = cache.annotations_map_for_book(1, 'moo')
|
||||
self.assertEqual([x[0] for x in annot_list], map_as_list(amap))
|
||||
|
||||
# }}}
|
||||
|
||||
def test_changed_events(self): # {{{
|
||||
@ -1043,7 +1042,6 @@ class WritingTest(BaseTest):
|
||||
self.assertDictEqual({'publisher': {'random': 'url2'}, 'tags': {'foobar': 'url'}},
|
||||
mi.link_maps, "ProxyMetadata didn't return the right link map")
|
||||
|
||||
|
||||
# Now test deleting the links.
|
||||
links = cache.get_link_map('tags')
|
||||
to_del = {l:'' for l in links.keys()}
|
||||
@ -1054,6 +1052,4 @@ class WritingTest(BaseTest):
|
||||
cache.set_link_map('publisher', to_del)
|
||||
self.assertEqual({}, cache.get_link_map('publisher'), 'links on publisher were not deleted')
|
||||
self.assertEqual({}, cache.get_all_link_maps_for_book(1), 'Not all links for book were deleted')
|
||||
|
||||
|
||||
# }}}
|
||||
|
@ -107,7 +107,6 @@ class CacheError(Exception):
|
||||
|
||||
|
||||
class ThumbnailCache:
|
||||
|
||||
' This is a persistent disk cache to speed up loading and resizing of covers '
|
||||
|
||||
def __init__(self,
|
||||
|
@ -99,7 +99,6 @@ def format_identifiers(x):
|
||||
|
||||
|
||||
class View:
|
||||
|
||||
''' A table view of the database, with rows and columns. Also supports
|
||||
filtering and sorting. '''
|
||||
|
||||
|
@ -19,8 +19,8 @@ from polyglot.builtins import iteritems, itervalues
|
||||
|
||||
missing = object()
|
||||
|
||||
# Convert data into values suitable for the db {{{
|
||||
|
||||
# Convert data into values suitable for the db {{{
|
||||
|
||||
def sqlite_datetime(x):
|
||||
return isoformat(x, sep=' ') if isinstance(x, datetime) else x
|
||||
@ -190,8 +190,8 @@ def get_adapter(name, metadata):
|
||||
return ans
|
||||
# }}}
|
||||
|
||||
# One-One fields {{{
|
||||
|
||||
# One-One fields {{{
|
||||
|
||||
def one_one_in_books(book_id_val_map, db, field, *args):
|
||||
'Set a one-one field in the books table'
|
||||
@ -265,8 +265,8 @@ def custom_series_index(book_id_val_map, db, field, *args):
|
||||
return {s[1] for s in sequence}
|
||||
# }}}
|
||||
|
||||
# Many-One fields {{{
|
||||
|
||||
# Many-One fields {{{
|
||||
|
||||
def safe_lower(x):
|
||||
try:
|
||||
@ -392,8 +392,8 @@ def many_one(book_id_val_map, db, field, allow_case_change, *args):
|
||||
return dirtied
|
||||
# }}}
|
||||
|
||||
# Many-Many fields {{{
|
||||
|
||||
# Many-Many fields {{{
|
||||
|
||||
def uniq(vals, kmap=lambda x:x):
|
||||
''' Remove all duplicates from vals, while preserving order. kmap must be a
|
||||
|
@ -99,7 +99,6 @@ class MIBUK(USBMS):
|
||||
|
||||
|
||||
class JETBOOK_MINI(USBMS):
|
||||
|
||||
'''
|
||||
['0x4b8',
|
||||
'0x507',
|
||||
@ -126,7 +125,6 @@ class JETBOOK_MINI(USBMS):
|
||||
|
||||
|
||||
class JETBOOK_COLOR(USBMS):
|
||||
|
||||
'''
|
||||
set([('0x951',
|
||||
'0x160b',
|
||||
|
@ -39,5 +39,3 @@ class Pages:
|
||||
@property
|
||||
def number_of_pages(self) -> int:
|
||||
return sum(len(pg.page_locations) for pg in self.__pages_groups)
|
||||
|
||||
|
||||
|
@ -185,5 +185,4 @@ class Bookmark: # {{{
|
||||
|
||||
return ans
|
||||
|
||||
|
||||
# }}}
|
||||
|
@ -4,6 +4,3 @@
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2012, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
|
||||
|
||||
|
@ -22,6 +22,7 @@ from calibre.utils.icu import lower, sort_key
|
||||
|
||||
bexts = frozenset(BOOK_EXTENSIONS) - {'mbp', 'tan', 'rar', 'zip', 'xml'}
|
||||
|
||||
|
||||
def convert_timestamp(md):
|
||||
try:
|
||||
if isinstance(md, tuple):
|
||||
|
@ -9,4 +9,3 @@ __docformat__ = 'restructuredtext en'
|
||||
'''
|
||||
libmtp based drivers for MTP devices on Unix like platforms.
|
||||
'''
|
||||
|
||||
|
@ -4,6 +4,3 @@
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2012, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
|
||||
|
||||
|
@ -73,7 +73,6 @@ class USBDevice:
|
||||
|
||||
|
||||
class Device(DeviceConfig, DevicePlugin):
|
||||
|
||||
'''
|
||||
This class provides logic common to all drivers for devices that export themselves
|
||||
as USB Mass Storage devices. Provides implementations for mounting/ejecting
|
||||
|
@ -67,7 +67,6 @@ def safe_walk(top, topdown=True, onerror=None, followlinks=False, maxdepth=128):
|
||||
# CLI must come before Device as it implements the CLI functions that
|
||||
# are inherited from the device interface in Device.
|
||||
class USBMS(CLI, Device):
|
||||
|
||||
'''
|
||||
The base class for all USBMS devices. Implements the logic for
|
||||
sending/getting/updating metadata/caching metadata/etc.
|
||||
|
@ -44,7 +44,6 @@ except ImportError:
|
||||
|
||||
# Data and function type definitions {{{
|
||||
|
||||
|
||||
class GUID(Structure):
|
||||
_fields_ = [
|
||||
('data1', DWORD),
|
||||
@ -701,8 +700,8 @@ def get_volume_pathnames(volume_id, buf=None):
|
||||
|
||||
# }}}
|
||||
|
||||
# def scan_usb_devices(): {{{
|
||||
|
||||
# def scan_usb_devices(): {{{
|
||||
|
||||
_USBDevice = namedtuple('USBDevice', 'vendor_id product_id bcd devid devinst')
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user