add/remove blank-line (extra-edit)

ruff 'E302,E303,E304,E305,W391'
This commit is contained in:
un-pogaz 2025-01-24 11:14:21 +01:00
parent 5540126765
commit 8d28380515
307 changed files with 314 additions and 512 deletions

View File

@ -76,5 +76,3 @@ class InterfacePluginDemo(InterfaceActionBase):
ac = self.actual_plugin_
if ac is not None:
ac.apply_settings()

View File

@ -89,5 +89,6 @@ def generate_template_language_help(language, log):
a(POSTAMBLE)
return ''.join(output)
if __name__ == '__main__':
generate_template_language_help()

View File

@ -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:

View File

@ -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'

View File

@ -28,4 +28,3 @@ class WwwAltomdata_dk(BasicNewsRecipe):
('Kommentarer til Alt om DATA, Datatid TechLife', 'http://www.altomdata.dk/comments/feed'),
]

View File

@ -18,6 +18,7 @@ today = today.replace('/', '%2F')
index = 'https://epaper.andhrajyothy.com'
class andhra(BasicNewsRecipe):
title = 'ఆంధ్రజ్యోతి - ఆంధ్రప్రదేశ్'
language = 'te'

View File

@ -18,6 +18,7 @@ today = today.replace('/', '%2F')
index = 'https://epaper.andhrajyothy.com'
class andhra(BasicNewsRecipe):
title = 'ఆంధ్రజ్యోతి - తెలంగాణ'
language = 'te'

View File

@ -24,4 +24,3 @@ class WwwAvisen_dk(BasicNewsRecipe):
feeds = [
('Nyheder fra Avisen.dk', 'http://www.avisen.dk/rss.aspx'),
]

View File

@ -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

View File

@ -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:

View File

@ -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']

View File

@ -51,4 +51,3 @@ class WwwComputerworld_dk(BasicNewsRecipe):
('IDG Kurser', 'http://job.idgkurser.dk/rss/'),
]

View File

@ -5,6 +5,7 @@ def absurl(url):
if url.startswith('/'):
return 'https://www.deccanherald.com' + url
class herald(BasicNewsRecipe):
title = 'Deccan Herald'
__author__ = 'unkn0wn'

View File

@ -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]

View File

@ -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')
]

View File

@ -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'),

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -33,7 +33,6 @@ class Esensja(BasicNewsRecipe):
dict(attrs={'class': ['tekst_koniec', 'ref', 'wykop']}),
dict(attrs={'itemprop': ['copyrightHolder', 'publisher']}),
dict(id='komentarze')
]
extra_css = '''

View File

@ -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 = [

View File

@ -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'

View File

@ -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

View File

@ -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'

View File

@ -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'}):

View File

@ -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 = ''

View File

@ -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')
]

View File

@ -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 = [

View File

@ -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']

View File

@ -20,4 +20,3 @@ class IndiaSpeaksReddit(BasicNewsRecipe):
feeds = [
('India Speaks Reddit main feed', 'https://www.reddit.com/r/IndiaSpeaks.rss'),
]

View File

@ -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')]

View File

@ -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)

View File

@ -6,6 +6,7 @@ def absurl(url):
if url.startswith('/'):
return 'https://www.livelaw.in' + url
class livelaw(BasicNewsRecipe):
title = 'Live Law'
__author__ = 'unkn0wn'

View File

@ -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):

View File

@ -36,4 +36,3 @@ class ReutersJa(BasicNewsRecipe):
for img in soup.findAll('img', attrs={'data-src':True}):
img['src'] = img['data-src']
return soup

View File

@ -38,4 +38,3 @@ class Nordjyske_dk(BasicNewsRecipe):
('Aalborg', 'http://nordjyske.dk/rss/aalborg'),
]

View File

@ -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)

View File

@ -18,4 +18,3 @@ class PajamasMedia(BasicNewsRecipe):
'http://feeds.feedburner.com/PajamasMedia'),
]

View File

@ -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'

View File

@ -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)

View File

@ -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)

View File

@ -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'

View File

@ -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']

View File

@ -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')]

View File

@ -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')
]

View File

@ -27,7 +27,6 @@ class Tehelka(BasicNewsRecipe):
use_embedded_content = False
ignore_duplicate_articles = {'title', 'url'}
feeds = [
('Tehelka', 'http://tehelka.com/rss'),
]

View File

@ -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'})

View File

@ -196,7 +196,6 @@ class PrivateEyeRecipe(BasicNewsRecipe):
return soup
# Remove features not wanted and tweak HTML
preprocess_regexps = [
# Remove big blank spaces

View File

@ -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'

View File

@ -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)

View File

@ -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'

View File

@ -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'

View File

@ -28,6 +28,7 @@ except ImportError:
needs_subscription = False
class WSJ(BasicNewsRecipe):
if needs_subscription:

View File

@ -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]

View File

@ -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)

View File

@ -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

View File

@ -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()

View File

@ -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')
#
# }}}

View File

@ -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')

View File

@ -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
# }}}

View File

@ -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:

View File

@ -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)
# }}}

View File

@ -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())
# }}}

View File

@ -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]

View File

@ -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)

View File

@ -450,6 +450,7 @@ def my_unichr(num):
except (ValueError, OverflowError):
return '?'
XML_ENTITIES = {
'"' : '&quot;',
"'" : '&apos;',
@ -458,6 +459,7 @@ XML_ENTITIES = {
'&' : '&amp;'
}
def entity_to_unicode(match, exceptions=(), encoding=None, result_exceptions={}):
'''
:param match: A match object such that '&'+match.group(1)';' is the entity.

View File

@ -410,7 +410,6 @@ else:
atexit.register(cleanup_cdir)
# }}}
is_running_from_develop = False
if getattr(sys, 'frozen', False):
try:

View File

@ -475,6 +475,7 @@ class MetadataReaderPlugin(Plugin): # {{{
:return: A :class:`calibre.ebooks.metadata.book.Metadata` object
'''
return None
# }}}

View File

@ -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'

View File

@ -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.

View File

@ -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):

View File

@ -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

View File

@ -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'''

View File

@ -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.

View File

@ -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:

View File

@ -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
# }}}

View File

@ -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

View File

@ -164,7 +164,6 @@ class ThreadSafePrefs(MutableMapping):
class LibraryDatabase:
''' Emulate the old LibraryDatabase2 interface '''
PATH_LIMIT = DB.PATH_LIMIT

View File

@ -25,6 +25,7 @@ from calibre.utils.icu import lower as icu_lower
if iswindows:
from calibre_extensions import winutil
class cmt(str):
pass

View File

@ -28,8 +28,8 @@ EQUALS_MATCH = 1
REGEXP_MATCH = 2
ACCENT_MATCH = 3
# Utils {{{
# Utils {{{
def _matchkind(query, case_sensitive=False):
matchkind = CONTAINS_MATCH

View File

@ -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

View File

@ -4,6 +4,3 @@
__license__ = 'GPL v3'
__copyright__ = '2011, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'

View File

@ -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'

View File

@ -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): # {{{

View File

@ -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)

View File

@ -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): # {{{

View File

@ -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')
# }}}

View File

@ -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,

View File

@ -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. '''

View File

@ -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

View File

@ -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',

View File

@ -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)

View File

@ -185,5 +185,4 @@ class Bookmark: # {{{
return ans
# }}}

View File

@ -4,6 +4,3 @@
__license__ = 'GPL v3'
__copyright__ = '2012, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'

View File

@ -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):

View File

@ -9,4 +9,3 @@ __docformat__ = 'restructuredtext en'
'''
libmtp based drivers for MTP devices on Unix like platforms.
'''

View File

@ -4,6 +4,3 @@
__license__ = 'GPL v3'
__copyright__ = '2012, Kovid Goyal <kovid at kovidgoyal.net>'
__docformat__ = 'restructuredtext en'

View File

@ -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

View File

@ -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.

View File

@ -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