Compare commits

...

420 commits

Author SHA1 Message Date
Kovid Goyal
5fe9010e74
... 2022-03-14 20:11:35 +05:30
Kovid Goyal
f8f971d208
Content server: Fix reading of books with thousands of internal files not working in the Chrome browser. Fixes #1964742 [Error when opening EPUB file which contains many chapters via Web Interface](https://bugs.launchpad.net/calibre/+bug/1964742)
Apparently chrome's network stack is too dumb to queue multiple ajax
requests so do it in our code.
2022-03-14 20:09:05 +05:30
Kovid Goyal
b2950eaeee
Swarajya Magazine by unkn0wn 2022-03-14 10:34:05 +05:30
Kovid Goyal
4a5e505ccf
Edit book: Insert hyperlinks: When sorting anchors on elements without any text content, use the anchor itself 2022-03-13 20:18:52 +05:30
Kovid Goyal
7b64f8a396
Update India Legal Magazine 2022-03-13 20:07:00 +05:30
Kovid Goyal
91697b777a
Edit book: Make the saved search panel freely resizable 2022-03-13 07:21:33 +05:30
Kovid Goyal
8d8ee82288
Edit book: When dragging to select a region or adjust the selection fix mouse moving outside the image causing the region to no longer be adjusted 2022-03-13 06:57:50 +05:30
Kovid Goyal
f1002b15ef
Update The Smithsonian 2022-03-12 09:52:01 +05:30
Kovid Goyal
78333c8683
Update The Federalist 2022-03-12 08:43:53 +05:30
Kovid Goyal
5989f3cef7
... 2022-03-12 08:37:37 +05:30
Kovid Goyal
0d775490b0
Ignore corrupted reading rates json file 2022-03-11 12:25:18 +05:30
Kovid Goyal
15d40ce3c1
use default umask as temp value 2022-03-09 11:11:11 +05:30
Kovid Goyal
7acaee07d0
Create config files with permissions based on umask rather than the hardcoded ones created by python's tempfile module 2022-03-09 11:10:05 +05:30
Kovid Goyal
65219abb3d
Use a prefix for the atomic write tempfile 2022-03-09 10:42:46 +05:30
Kovid Goyal
3e97ae74d6
Only retry for specific error codes 2022-03-09 08:40:36 +05:30
Kovid Goyal
29482963b7
config_base cant depend on utils.filenames 2022-03-09 08:20:30 +05:30
Kovid Goyal
c1a06e9c37
oops 2022-03-09 08:08:21 +05:30
Kovid Goyal
0012b7cd64
Delete temp file used for atomic writes even if renaming fails 2022-03-09 07:54:44 +05:30
Kovid Goyal
007099dd60
Use atomic writes for the config files
Avoids the need for file locking and also ensures no partial data is
written in case of crash/powerloss. Fixes #1964123 [Settings reset in main calibre program when pc turns off due to power failure](https://bugs.launchpad.net/calibre/+bug/1964123)
2022-03-09 07:51:54 +05:30
Kovid Goyal
15ded1182f
Merge branch 'master' of https://github.com/cbhaley/calibre 2022-03-08 17:48:50 +05:30
Charles Haley
9270e9b948 Fix a performance problem exposed when using the view manager plugin. The method apply_state() indirectly does a save_state() whenever a column is repositioned. The view manager can reposition a lot of columns in one go, potentially resulting in *many* calls to save_state(). The fix is to call save_state() once after all the columns have been repositions.
A second piece of the fix is to add a save_state=True parameter to apply_state(). The caller would set save_state=False if it will call save_state() directly.

See https://www.mobileread.com/forums/showthread.php?t=345554. The thread is rather long.
2022-03-08 12:09:34 +00:00
Kovid Goyal
240aee0ee5
Use the gesture manager for touch support in the viewer panels
Harmonizes with the book list and is superior to plain QScroller
2022-03-08 15:22:46 +05:30
Kovid Goyal
5277bad302
Use Qt to detect touchscreen support 2022-03-08 15:02:38 +05:30
Kovid Goyal
3aed3daaa2
... 2022-03-08 11:35:50 +05:30
Kovid Goyal
cbbac1be62
Update The Federalist 2022-03-08 07:41:14 +05:30
Kovid Goyal
7080d8914b
Open Magazine by unkn0wn 2022-03-08 07:21:14 +05:30
Kovid Goyal
9a73323fa3
E-book viewer: Allow scrolling of the ToC, highlights, bookmarks, etc. with touch gestures. Fixes #1963875 [Make the Viewer TOC touch friendly](https://bugs.launchpad.net/calibre/+bug/1963875) 2022-03-07 21:15:11 +05:30
Kovid Goyal
894f7d547a
Add books dialog: Exclude zip and rar files from the default list of books types. These are rarely single books these days. And they can still be selected using the archives option. Fixes #1602 (Allows you to default to exclude some file types when adding books) 2022-03-07 21:01:38 +05:30
Kovid Goyal
528efd3d88
Amazon metadata download: Fix getting series info from amazon.jp. Fixes #1963856 [[PATCH] AmzonJP FIX to get series and black curtain tag](https://bugs.launchpad.net/calibre/+bug/1963856) 2022-03-07 11:09:19 +05:30
Kovid Goyal
dd8a8af383
Edit/Polish book: Fix hardcoded Unicode ligatures not being preserved in AZW3 format books 2022-03-07 07:12:49 +05:30
Kovid Goyal
e467468783
Workaround for bug in Qt causing a crash on unhandled exception in current_changed 2022-03-06 15:21:35 +05:30
Kovid Goyal
7e645a0e30
... 2022-03-04 07:26:44 +05:30
Kovid Goyal
e21623b8c1
version 5.38.0 2022-03-04 06:31:24 +05:30
Kovid Goyal
8fa9a5bd8f
pep8 2022-03-03 20:38:56 +05:30
Kovid Goyal
6e054fd1b0
Also implement remembering reading rate for in browser viewer 2022-03-03 20:25:49 +05:30
Kovid Goyal
f043ceff0c
calculate time left immediately on load if historical rates are available 2022-03-03 20:12:21 +05:30
Kovid Goyal
439da2712a
E-book viewer: When displaying estimated time to completion for reading a book, remember the reading rate the next time the book is opened so that the period spent calculating the time remaining is reduced. Fixes #1852929 [Time to read book is not saved](https://bugs.launchpad.net/calibre/+bug/1852929) 2022-03-03 20:09:51 +05:30
Kovid Goyal
b2c8f6f8ee
PDF Output: Fix conversion failing if there are ToC entries pointing to removed content. Fixes #1960554 [Private bug](https://bugs.launchpad.net/calibre/+bug/1960554) 2022-03-03 15:33:33 +05:30
Kovid Goyal
a772d45227
Copy to library: Fix annotations not being copied. Fixes #1962365 [Highlights missing when copying to another library](https://bugs.launchpad.net/calibre/+bug/1962365) 2022-03-03 14:26:16 +05:30
Kovid Goyal
aec6b7c174
Use the new transifex client, which is dog-slow and not API compatible with the old one
Le Sigh.
https://github.com/transifex/cli/issues/5
2022-03-03 12:23:03 +05:30
Kovid Goyal
66f427eef4
Fix #1961465 [[Enhancement - Content server] ESC to close the Search for books page](https://bugs.launchpad.net/calibre/+bug/1961465) 2022-03-02 19:08:16 +05:30
Kovid Goyal
4ebed6bbc1
E-book viewer: Fix an error when opening books with MathML for the second time if the last read position was at a MathML element. Fixes #1961775 [Private bug](https://bugs.launchpad.net/calibre/+bug/1961775) 2022-03-02 16:40:08 +05:30
Kovid Goyal
7431c7fe85
Edit book: Fix double clicking to select a word also selecting smart quotes surrounding the word 2022-03-02 12:38:48 +05:30
Kovid Goyal
b7db7cf446
Update New York Times Book Review 2022-02-28 10:59:26 +05:30
Kovid Goyal
833ba43207
Hindustan Times by unkn0wn 2022-02-25 20:55:42 +05:30
Kovid Goyal
df66924f1b
Edit book: Spell check: Fix words after a comment not being checked. Fixes #1962213 [Spell checker ignores text after HTML comment](https://bugs.launchpad.net/calibre/+bug/1962213) 2022-02-25 05:28:30 +05:30
Kovid Goyal
dd0e805838
Bump bundled feedparser 2022-02-24 13:56:37 +05:30
Kovid Goyal
a7f5ddfe8b
Update Lenta.ru and aif.ru 2022-02-24 13:40:45 +05:30
Kovid Goyal
f08b87900f
Update Indian Express 2022-02-23 20:10:57 +05:30
Kovid Goyal
4f5d90a5c3
Merge branch 'master' of https://github.com/Vuizur/calibre 2022-02-23 19:53:08 +05:30
Hannes Krumbiegel
bff3db73dc
Create rt.recipe 2022-02-23 14:40:11 +01:00
Kovid Goyal
af7f37453a
Get books: Remove xinxii plugin
It doesnt work and I cant even find a working search on the xinxii
website, so...
2022-02-22 22:07:02 +05:30
Kovid Goyal
dd61adc992
Merge branch 'master' of https://github.com/cbhaley/calibre
Fixes #1961639 [Enhancement] When editing Metadata in the Book List](https://bugs.launchpad.net/calibre/+bug/1961639)
2022-02-22 22:00:58 +05:30
Charles Haley
ab1d49d3f1 Enhancement 1961639: Option to disable editing composite templates if edited with the Tab key 2022-02-22 15:32:41 +00:00
Kovid Goyal
e3fb3ce015
DRYer 2022-02-22 18:37:49 +05:30
Kovid Goyal
2c3e605441
We need Visual Studio 2019 on CI to build 2022-02-22 08:28:57 +05:30
Kovid Goyal
63cb92bb35
Dump envvars when failing to find one 2022-02-22 08:15:23 +05:30
Kovid Goyal
a02ca85c20
Use a lighter background for current cell and change text color to black
The current cell should "stand out" more
2022-02-22 08:00:53 +05:30
Kovid Goyal
bb8aff53d5
... 2022-02-22 07:56:27 +05:30
Kovid Goyal
8597c509ed
Fix #1961514 [[Enhancement] Remove unnecessary lines in the Manage items window](https://bugs.launchpad.net/calibre/+bug/1961514) 2022-02-20 15:26:51 +05:30
Kovid Goyal
3eb4274e88
Think I prefer plain white over yellow for current item 2022-02-20 15:24:31 +05:30
Kovid Goyal
7c20b8212a
Dark theme: Highlight the current cell in the book list with a darker background and different foreground to make it more obvious. Fixes #1961500 [[Enhancement} Use a different color for current cell in Win10 Dark mode](https://bugs.launchpad.net/calibre/+bug/1961500) 2022-02-20 14:59:36 +05:30
Kovid Goyal
f9acb16314
... 2022-02-20 14:14:32 +05:30
Kovid Goyal
664a820feb
... 2022-02-20 13:45:15 +05:30
Kovid Goyal
a4e55ce1e6
Live Mint: Add support for Saturday special edition 2022-02-20 13:19:31 +05:30
Kovid Goyal
03cac41da7
India Legal Magazine by unkn0wn 2022-02-20 11:43:00 +05:30
Kovid Goyal
3367c3f022
Char select dialog: Truncate character description on hover instead of resizing dialog to fit it 2022-02-20 10:42:15 +05:30
Kovid Goyal
b57a5d0168
Merge branch 'master' of https://github.com/cbhaley/calibre 2022-02-20 10:26:14 +05:30
Charles Haley
b2898e4f14 Enhancement #1961464: add ability to import and export the edit metadata custom column field list. 2022-02-19 11:44:53 +00:00
Kovid Goyal
82a9db1aa6
EPUB 3 metadata: Fix non-integer series index being sometimes represented using exponential notation 2022-02-19 09:07:40 +05:30
Kovid Goyal
b7eb5bd5ac
Avoid trailing zeroes when formatting decimal series indices 2022-02-19 09:04:37 +05:30
Kovid Goyal
41045fc367
Tag editor: Fix regression in previous release that caused double clicking on tags to not work on non Linux platforms 2022-02-18 21:13:24 +05:30
Kovid Goyal
07b4239634
workaround for nyt todays paper page using undefinedinstead of null in its json 2022-02-18 19:59:22 +05:30
Kovid Goyal
803da449ba
Cleanup previous PR
recipes have to run on old python 2 based calibre as well, so no type
annotations
2022-02-18 17:29:35 +05:30
Kovid Goyal
ac8a115eed
Merge branch 'fix-mainichi-en-recipe' of https://github.com/albertaparicio/calibre 2022-02-18 17:29:31 +05:30
Kovid Goyal
c5339c117e
Merge branch 'fix-japan-times-recipe' of https://github.com/albertaparicio/calibre 2022-02-18 17:27:00 +05:30
Albert Aparicio
14ce0c41f1 Recipes - Redo Mainichi (English version) from scratch
The present version of the Mainichi (en) version was not working. I
remade it from scratch, taking into account the current layout of the
Mainichi website
2022-02-18 11:35:20 +01:00
Albert Aparicio
4a01a799f1 Recipes - Fix and improve Japan Times recipe 2022-02-18 11:32:45 +01:00
Kovid Goyal
484d5ee5d6
mozilla seems to be back up 2022-02-18 08:43:26 +05:30
Kovid Goyal
8294f53402
Temporarily disable recent_uas because there is some network issue connecting to Mozilla's servers from my machine 2022-02-18 07:39:25 +05:30
Kovid Goyal
9615e5ebbc
... 2022-02-18 07:25:19 +05:30
Kovid Goyal
7ceeae768f
version 5.37.0 2022-02-18 07:24:50 +05:30
Kovid Goyal
1c0796be45
Update Publico.PT
Fixes #1961348 [Fix username/password on Publico recipe](https://bugs.launchpad.net/calibre/+bug/1961348)
2022-02-18 07:16:39 +05:30
Kovid Goyal
87b527d33e
pep8 2022-02-17 22:49:11 +05:30
Kovid Goyal
bbfa51852c
Update Live Mint 2022-02-17 22:41:31 +05:30
Kovid Goyal
d2baa161c7
Fix sizing of images in The Hindu 2022-02-17 20:49:44 +05:30
Kovid Goyal
c0e7520954
Book details: Add actions to trim the cover to the right-click menu. Fixes #1961129 [[Enhancement] Action to trim cover borders in context menu of Book details panel](https://bugs.launchpad.net/calibre/+bug/1961129) 2022-02-17 11:02:29 +05:30
Kovid Goyal
4f92e975bf
Update Reuters 2022-02-17 10:20:46 +05:30
Kovid Goyal
9287e70784
E-book viewer: Fix setting to use roman numerals for series not being respected 2022-02-17 08:20:34 +05:30
Kovid Goyal
433e07fda7
Fix pyexpat not being linked against bundled libexpat 2022-02-16 15:37:56 +05:30
Kovid Goyal
91532c8ea9
string changes 2022-02-16 11:04:09 +05:30
Kovid Goyal
0acb86eccf
Fix #1961002 [[Enhancement] Section is squeezed in with the Swedish language](https://bugs.launchpad.net/calibre/+bug/1961002) 2022-02-16 10:59:56 +05:30
Kovid Goyal
8464187b7a
Preserve sort order when removing rows 2022-02-16 08:32:18 +05:30
Kovid Goyal
cad142847a
Fix #1960586 [[Enhancement] Remove multiple email address at once](https://bugs.launchpad.net/calibre/+bug/1960586) 2022-02-16 08:23:56 +05:30
Kovid Goyal
ff2bc6ecf7
Merge branch 'master' of https://github.com/cbhaley/calibre
Fixes #1960688 [Enhancement Request: Alternate way to access 'edit permissible values' dialog](https://bugs.launchpad.net/calibre/+bug/1960688)
2022-02-16 07:54:09 +05:30
Charles Haley
a3be0a6106 Enhancement 1960688]: add editing enumeration permissible values to the column context menu. 2022-02-15 19:04:42 +00:00
Kovid Goyal
731ccd92a9
... 2022-02-13 12:28:24 +05:30
Kovid Goyal
46f9b1ebd7
Update The Hindu 2022-02-13 12:07:58 +05:30
Kovid Goyal
a968848316
Merge branch 'patch-1' of https://github.com/tadejsinko/calibre
Update MMC RTV Slovenija
2022-02-13 10:29:03 +05:30
Tadej
ba06dedeb4
Remove another type of gallery from output 2022-02-13 01:17:53 +01:00
Tadej
a04033e2e7
Update all feed URLs to use HTTPS 2022-02-13 00:41:28 +01:00
Tadej
dffb2775f2
Fixed news recipe for www.rtvslo.si
The old recipe wasn't generating any content at all due to significant changes to the website. I fixed the recipe and added a few feeds that were missing.
2022-02-13 00:08:29 +01:00
Kovid Goyal
3d71e15a65
Textile output: Dont fail if input document has invalid padding or margin specifications. Fixes #1960686 [Private bug](https://bugs.launchpad.net/calibre/+bug/1960686) 2022-02-12 13:19:29 +05:30
Kovid Goyal
2fadaf5b19
Make Jonatan feel better :) 2022-02-12 12:20:57 +05:30
Kovid Goyal
b967d20420
E-book viewer: Fix image display window not remembering its size and settings when run from within calibre. Fixes #1960446 [Remembering position and size of the Image windows in E-book Viewer](https://bugs.launchpad.net/calibre/+bug/1960446) 2022-02-10 20:24:00 +05:30
Kovid Goyal
d9c6bc0af8
... 2022-02-10 20:07:02 +05:30
Kovid Goyal
4cb8b0625a
Merge branch 'master' of https://github.com/cbhaley/calibre 2022-02-10 20:06:34 +05:30
Charles Haley
dd21a4ccf9 Template functions preferences changes:
1) Make the stored templates dialog show all the selected books instead of only the first.
2) Remember the last state help showing or not for both stored templates and template functions.
2022-02-10 13:50:32 +00:00
Kovid Goyal
1e117b61a0
Merge branch 'master' of https://github.com/cbhaley/calibre
Fixes #1960442 [[Enhancement] Remove line in Template functions window](https://bugs.launchpad.net/calibre/+bug/1960442)
2022-02-10 17:02:45 +05:30
Charles Haley
576cb4142c Enhancement #1960442: Remove line in Template functions window 2022-02-10 09:28:41 +00:00
Kovid Goyal
14919c9531
... 2022-02-10 11:05:58 +05:30
Kovid Goyal
6cfb2e9ab1
Fix #1960438 [[Enhancement] Windows have more top padding than others](https://bugs.launchpad.net/calibre/+bug/1960438) 2022-02-10 08:31:24 +05:30
Kovid Goyal
d552304ba0
More context menu icons 2022-02-09 11:22:07 +05:30
Kovid Goyal
e13889baed
Edit book: When saving a copy dont fail if the original file has no write permissions. 2022-02-09 09:06:38 +05:30
Kovid Goyal
2709a3eb88
OpenOffice -> LibreOffice 2022-02-09 08:48:12 +05:30
Kovid Goyal
ce04d47398
Fix #1960378 [[Enhancement] Add icons to buttons](https://bugs.launchpad.net/calibre/+bug/1960378) 2022-02-09 08:45:23 +05:30
Kovid Goyal
758eb98cd1
More context menu icons 2022-02-09 08:24:01 +05:30
Kovid Goyal
1f38dd88b4
... 2022-02-08 11:49:17 +05:30
Kovid Goyal
ff71a384db
String changes 2022-02-08 11:30:25 +05:30
Kovid Goyal
fd9cc8ce30
Show an error when toc editor fails to start 2022-02-08 11:14:00 +05:30
Kovid Goyal
2c9e9831e7
More context menu icons 2022-02-08 05:54:00 +05:30
Kovid Goyal
d5201ff24d
Fix #1960227 [[Enhancement - Content server] Don't display arrows on the cover on the Book details page if there are no previous/next book](https://bugs.launchpad.net/calibre/+bug/1960227) 2022-02-07 18:28:15 +05:30
Kovid Goyal
22aaea6073
More context menu icons 2022-02-07 14:51:30 +05:30
Kovid Goyal
f4a1cdc98c
Sort menu: Show the current sort at the top of the menu 2022-02-07 14:41:16 +05:30
Kovid Goyal
78af40cf17
Use a better monospace font on windows for book details 2022-02-07 13:54:24 +05:30
Kovid Goyal
a03b4ac614
Fix #1960203 [Add clear button to the fields in the Create Virtual library window](https://bugs.launchpad.net/calibre/+bug/1960203) 2022-02-07 13:37:17 +05:30
Kovid Goyal
a467d5ef07
Merge branch 'master' of https://github.com/cbhaley/calibre 2022-02-07 13:16:53 +05:30
Kovid Goyal
e52c124224
Embed fonts: Create <head> when missing. Fixes #1960180 [Error embedding fonts](https://bugs.launchpad.net/calibre/+bug/1960180) 2022-02-07 08:19:46 +05:30
Charles Haley
288a5f8593 Add a tweak to change the behavior of the tab character in completing combo boxes 2022-02-06 22:10:35 +00:00
Kovid Goyal
2adc821a67
... 2022-02-06 12:00:16 +05:30
Kovid Goyal
6fae77e7f4
Tag editor: Use a proxy model for better filter performance
Also simplifies the code
2022-02-06 11:58:36 +05:30
Kovid Goyal
cab955630c
User manual: Fix mart quotes and dashes not rendered in PDF version
Move to lualatex instead of pdflatex as the latex engine. Hopefully it
doesnt break something else.
2022-02-06 08:26:15 +05:30
Kovid Goyal
726adf2a8c
... 2022-02-06 06:20:44 +05:30
Kovid Goyal
b4ab128f8d
Dont change the type of opts.trusted_ips 2022-02-06 06:02:52 +05:30
Kovid Goyal
d36c916e67
... 2022-02-05 11:37:07 +05:30
Kovid Goyal
5858575750
Fix incorrect serialization of ip_addresses in the preferences dialog after the content server has been started 2022-02-05 10:50:12 +05:30
Kovid Goyal
affd7be313
Content server: Ignore failure to strftime log entries 2022-02-05 10:36:22 +05:30
Kovid Goyal
e903aabf0c
... 2022-02-05 07:28:30 +05:30
Kovid Goyal
cbfbe97f4d
Update Down To Earth 2022-02-04 21:47:51 +05:30
Kovid Goyal
cf5f2ee4fc
Cleanup previous PR 2022-02-04 20:32:28 +05:30
Kovid Goyal
b927925d2a
Merge branch 'master' of https://github.com/cbhaley/calibre 2022-02-04 20:23:57 +05:30
Charles Haley
fae3fb28d0 Migrate the remaining edit metadata tweaks to gprefs. 2022-02-04 13:26:14 +00:00
Kovid Goyal
ca0a977b09
Better handling of empty prefix list 2022-02-04 16:41:08 +05:30
Kovid Goyal
b4e6ae8c2b
Handle empty sort prefixes 2022-02-04 16:34:00 +05:30
Kovid Goyal
99ef0b5782
Merge branch 'tooltip' of https://github.com/413Michele/calibre 2022-02-04 16:28:41 +05:30
413Michele
39137915bd
Fix typo: missing space 2022-02-04 11:51:07 +01:00
Kovid Goyal
48ec109eab
Merge branch 'tooltip' of https://github.com/413Michele/calibre 2022-02-04 16:13:50 +05:30
Kovid Goyal
10b738b533
Remove coloring of splitter handles
It's inconsistent to have this in one dialog in the application and
no where else. If needed, this should be implemented in the calibre
style application wide.
2022-02-04 16:08:04 +05:30
Kovid Goyal
0b38930e94
Merge branch 'master' of https://github.com/cbhaley/calibre
Fixes #1959928 [All-In-One Edit Metadata Screen File Area Adjustment](https://bugs.launchpad.net/calibre/+bug/1959928)
2022-02-04 16:06:02 +05:30
413Michele
c992418341
Update Column icons tooltip information
I added some info on the difference between "with text" and "without text" icons, as I couldn't understand the effect that option had before testing it
2022-02-04 11:30:41 +01:00
Charles Haley
3cd97e670f Enhancement #1959928: add a splitter between cover and formats in all-on-one metadata edit.
While there, slightly color the splitters to make them easier to discover and use.
2022-02-04 10:19:01 +00:00
Kovid Goyal
a7782679fe
version 5.36.0 2022-02-04 10:40:10 +05:30
Kovid Goyal
b36c5e7624
When reviewing metadata if the newly downloaded metadata has no language but there is an existing language, ensure it is preserved. Fixes #1959981 [book metadata download fails language attribute](https://bugs.launchpad.net/calibre/+bug/1959981) 2022-02-04 10:39:16 +05:30
Kovid Goyal
8ceb229914
... 2022-02-04 08:09:06 +05:30
Kovid Goyal
91443bc3bd
Normalize command line args for ebook-meta 2022-02-04 08:01:08 +05:30
Kovid Goyal
fce128a10e
Edit book: Fix pasting files from another editor instance failing if a file with the same name already exists. Fixes #1959782 [Problems with drag and drop or adding files in the editor](https://bugs.launchpad.net/calibre/+bug/1959782) 2022-02-03 20:05:43 +05:30
Kovid Goyal
ed209b9374
Fix #1959893 [Trim Image - Size of selected area is incorrect](https://bugs.launchpad.net/calibre/+bug/1959893) 2022-02-03 19:14:05 +05:30
Kovid Goyal
57d24f0538
Merge branch 'master' of https://github.com/cbhaley/calibre 2022-02-03 18:58:56 +05:30
Charles Haley
1bb20d414f Use splitters in the all-in-one-tab edit metadata dialog. 2022-02-03 13:04:07 +00:00
Kovid Goyal
00d4459071
Amazon metadata download: Fix paragraphs in the comments being merged. Fixes #1959659 [Metadata download: preserve paragraph tags in comments](https://bugs.launchpad.net/calibre/+bug/1959659) 2022-02-03 13:21:38 +05:30
Kovid Goyal
68b08f4a6a
Metadata download: Fix published date and series information not being fetched for some books from amazon.de. Fixes #1958979 [Amazon metadata download gets not all fields in some cases](https://bugs.launchpad.net/calibre/+bug/1958979) 2022-02-03 12:15:42 +05:30
Kovid Goyal
0ffbd4e3a8
py310: more float->int goodness 2022-02-03 07:56:45 +05:30
Kovid Goyal
9d0b555d80
more pyqt6 enum goodness 2022-02-02 22:01:41 +05:30
Kovid Goyal
dc710d8cbe
pep8 2022-02-02 21:58:51 +05:30
Kovid Goyal
668fd790d7
Merge branch 'master' of https://github.com/cbhaley/calibre 2022-02-02 21:58:23 +05:30
Charles Haley
312807ca94 Two changes to edit metadata custom columns:
1) Ensure the height of a widget doesn't grow in two column mode.
2) Add an option to ignore the column selection and order specifications.
2022-02-02 12:04:12 +00:00
Kovid Goyal
b8de124575
Move tabs for cover grid widget to top 2022-02-01 22:36:57 +05:30
Kovid Goyal
8fcd59ce34
Use a list instead of tabs for Preferences->Look & feel 2022-02-01 22:34:55 +05:30
Kovid Goyal
98b4b9a3c2
Cleanup previous PR 2022-02-01 21:50:49 +05:30
Kovid Goyal
ef109d55a2
Merge branch 'master' of https://github.com/cbhaley/calibre 2022-02-01 21:34:02 +05:30
Charles Haley
cc9bb5fb57 Add a tab to Look/feel to choose which fields to show in edit metadata as well as set their order. 2022-02-01 15:56:36 +00:00
Kovid Goyal
55f6b4ee2c
Improve the email known relay setup dialog 2022-02-01 21:11:47 +05:30
Kovid Goyal
cdecdaf519
rename hotmail to outlook 2022-02-01 19:48:22 +05:30
Kovid Goyal
885be4936f
... 2022-02-01 15:05:47 +05:30
Kovid Goyal
f457ee5122
Fix #1959631 [Ampersand rendering bug](https://bugs.launchpad.net/calibre/+bug/1959631) 2022-02-01 07:31:43 +05:30
Kovid Goyal
3f2aa59072
Also, I believe hotmail requires full email address as username too 2022-01-31 08:07:23 +05:30
Kovid Goyal
9aaaa1b103
Replace smtp.live.com with smtp-mail.outlook.com when sending mail from the GUI so users dont all hve to change their email settings 2022-01-31 08:02:53 +05:30
Kovid Goyal
e1730e1a3b
Hotmail SMTP server has changed 2022-01-31 07:52:50 +05:30
Kovid Goyal
07f59656b3
Merge branch 'master' of https://github.com/cbhaley/calibre 2022-01-30 18:59:48 +05:30
Charles Haley
1009054cf2 Ooops. Really did need to escape the URL 2022-01-30 11:54:29 +00:00
Charles Haley
7334080406 New affiliate program for ebook.de 2022-01-30 11:25:49 +00:00
Kovid Goyal
99d85b9791
Merge branch 'master' of https://github.com/cbhaley/calibre 2022-01-29 08:08:16 +05:30
Charles Haley
4feecf4863 Fix highlighting to correctly highlight things like =='aa'. Given the way highlighting works, this change will break highlighting for statements like
for a in $tags:'aa' rof. I think that strings following operators is far more common than strings following the colon in a for statement.
2022-01-28 21:32:15 +00:00
Kovid Goyal
2620f6685a
Dont remove articles for titles in the polish language. Fixes #1959220 [Wrong/Unnecessary Title Sorting of Polish Titles Begninning with Word "A"](https://bugs.launchpad.net/calibre/+bug/1959220) 2022-01-27 22:05:47 +05:30
Kovid Goyal
f5771797c1
more context menu icons 2022-01-27 21:32:31 +05:30
Kovid Goyal
344baecb90
E-book viewer: When using Read aloud do not automatically lookup the highlighted word until read aloud is paused or stopped. Fixes #1959207 [E-book viewer's "read the text aloud" function conflicts with dictionary lookup](https://bugs.launchpad.net/calibre/+bug/1959207) 2022-01-27 21:19:05 +05:30
Kovid Goyal
2f07353be9
Merge branch 'master' of https://github.com/cbhaley/calibre
Fixes #1959202 [Column icons and stored templates](https://bugs.launchpad.net/calibre/+bug/1959202)
2022-01-27 19:22:46 +05:30
Charles Haley
37d73caab8 Bug #1959202: Column icons and stored templates 2022-01-27 13:43:47 +00:00
Kovid Goyal
5706c95ce2
Update India Today 2022-01-27 18:11:32 +05:30
Kovid Goyal
7f433e8f30
Update Financial Express 2022-01-27 17:45:30 +05:30
Kovid Goyal
dbb307809d
Update Indian Express 2022-01-27 15:00:56 +05:30
Kovid Goyal
1a31460d08
Update Live Mint 2022-01-27 14:58:27 +05:30
Kovid Goyal
c92c2c78c3
Ignore metadata_pre_restore.db when doing a library check 2022-01-27 14:46:16 +05:30
Kovid Goyal
80a4cb8a46
Merge branch 'master' of https://github.com/ConstrictM/calibre 2022-01-27 10:52:55 +05:30
ConstrictM
d900ed3020 Fix Google Search Engine Results 2022-01-26 22:52:39 -05:00
Kovid Goyal
36a71e713f
Update test for new dictionary 2022-01-26 21:30:07 +05:30
Kovid Goyal
c342d3b378
Update bundled dictionaries
Taken from https://github.com/LibreOffice/dictionaries
2022-01-26 21:04:45 +05:30
Kovid Goyal
295c225722
Use a specific eng dictionary in the hunspell test 2022-01-26 16:11:04 +05:30
Kovid Goyal
e8d28233bb
Update Al Jazeera in English 2022-01-26 10:40:56 +05:30
Kovid Goyal
9cc2efc885
Update The Financial Express 2022-01-26 10:31:57 +05:30
Kovid Goyal
47c44c308e
Update The Straits Times 2022-01-26 10:28:15 +05:30
Kovid Goyal
800b191a63
Merge branch 'patch-2' of https://github.com/Carmina16/calibre 2022-01-26 08:47:15 +05:30
Carmina16
e60162503a
Unwrap line after more characters
Fix line unwrap for Polish. Add Cyrillic alphabet.
2022-01-26 03:35:47 +07:00
Kovid Goyal
a81e4bec5c
E-book viewer: Fix Ctrl+p shortcut for printing not working 2022-01-25 21:01:46 +05:30
Kovid Goyal
a59be7d4dc
More context menu icons 2022-01-25 20:24:00 +05:30
Kovid Goyal
960cf5e713
Some more context menu icons 2022-01-25 20:18:34 +05:30
Kovid Goyal
6dc13b86dc
More context menu icons 2022-01-25 19:55:33 +05:30
Kovid Goyal
51287dae54
Show an error when viewing a specific format and the file is missing. Fixes #1958882 [Format present in metadata, but missing file: clicking on format to open e-book reader does nothing](https://bugs.launchpad.net/calibre/+bug/1958882) 2022-01-24 21:51:47 +05:30
Kovid Goyal
a107534286
More email address validation 2022-01-24 08:08:33 +05:30
Kovid Goyal
9c2c036702
Revert "Remove unused code"
This reverts commit da339e639d.
Fixes #1958776
2022-01-24 08:02:50 +05:30
Kovid Goyal
6f58b77566
BibTeX catalogs: Support tags like custom columns. Fixes #1958773 [bibtex export ignores custom fields](https://bugs.launchpad.net/calibre/+bug/1958773) 2022-01-23 21:51:53 +05:30
Kovid Goyal
f32f8a393b
Merge branch 'patch-1' of https://github.com/felagund/calibre 2022-01-23 21:41:18 +05:30
Tomáš Hnyk
1c31f8010e
Fix 308 error that started appearing today
I tried to run the recipe today and I would get this error 

```
calibre, version 5.35.0 (linux, embedded-python: True)
Conversion error: Failed: Fetch news from Respekt Magazine – Print

Fetch news from Respekt Magazine – Print
Conversion options changed from defaults:
  verbose: 2
  output_profile: 'kindle'
Resolved conversion options
calibre version: 5.35.0
{'asciiize': False,
 'author_sort': None,
 'authors': None,
 'base_font_size': 0,
 'book_producer': None,
 'change_justification': 'original',
 'chapter': None,
 'chapter_mark': 'pagebreak',
 'comments': None,
 'cover': None,
 'debug_pipeline': None,
 'dehyphenate': True,
 'delete_blank_paragraphs': True,
 'disable_font_rescaling': False,
 'dont_compress': False,
 'dont_download_recipe': False,
 'duplicate_links_in_toc': False,
 'embed_all_fonts': False,
 'embed_font_family': None,
 'enable_heuristics': False,
 'expand_css': False,
 'extra_css': None,
 'extract_to': None,
 'filter_css': None,
 'fix_indents': True,
 'font_size_mapping': None,
 'format_scene_breaks': True,
 'html_unwrap_factor': 0.4,
 'input_encoding': None,
 'input_profile': <calibre.customize.profiles.InputProfile object at 0x7f4f2bcecbb0>,
 'insert_blank_line': False,
 'insert_blank_line_size': 0.5,
 'insert_metadata': False,
 'isbn': None,
 'italicize_common_cases': True,
 'keep_ligatures': False,
 'language': None,
 'level1_toc': None,
 'level2_toc': None,
 'level3_toc': None,
 'line_height': 0,
 'linearize_tables': False,
 'lrf': False,
 'margin_bottom': 5.0,
 'margin_left': 5.0,
 'margin_right': 5.0,
 'margin_top': 5.0,
 'markup_chapter_headings': True,
 'max_toc_links': 50,
 'minimum_line_height': 120.0,
 'mobi_file_type': 'old',
 'mobi_ignore_margins': False,
 'mobi_keep_original_images': False,
 'mobi_toc_at_start': False,
 'no_chapters_in_toc': False,
 'no_inline_navbars': True,
 'no_inline_toc': False,
 'output_profile': <calibre.customize.profiles.KindleOutput object at 0x7f4f2bcfc100>,
 'page_breaks_before': None,
 'personal_doc': '[PDOC]',
 'prefer_author_sort': False,
 'prefer_metadata_cover': False,
 'pretty_print': False,
 'pubdate': None,
 'publisher': None,
 'rating': None,
 'read_metadata_from_opf': None,
 'remove_fake_margins': True,
 'remove_first_image': False,
 'remove_paragraph_spacing': False,
 'remove_paragraph_spacing_indent_size': 1.5,
 'renumber_headings': True,
 'replace_scene_breaks': '',
 'search_replace': None,
 'series': None,
 'series_index': None,
 'share_not_sync': False,
 'smarten_punctuation': False,
 'sr1_replace': '',
 'sr1_search': '',
 'sr2_replace': '',
 'sr2_search': '',
 'sr3_replace': '',
 'sr3_search': '',
 'start_reading_at': None,
 'subset_embedded_fonts': False,
 'tags': None,
 'test': False,
 'timestamp': None,
 'title': None,
 'title_sort': None,
 'toc_filter': None,
 'toc_threshold': 6,
 'toc_title': None,
 'transform_css_rules': None,
 'transform_html_rules': None,
 'unsmarten_punctuation': False,
 'unwrap_lines': True,
 'use_auto_toc': False,
 'verbose': 2}
Failed to initialize plugin: '/home/drew/.config/calibre/plugins/DeDRM.zip'
InputFormatPlugin: Recipe Input running
Downloading recipe urn: builtin:respekt_magazine
Trying to get latest version of recipe: respekt_magazine
Using user agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36
Traceback (most recent call last):
  File "runpy.py", line 194, in _run_module_as_main
  File "runpy.py", line 87, in _run_code
  File "site.py", line 45, in <module>
  File "site.py", line 41, in main
  File "calibre/utils/ipc/worker.py", line 215, in main
  File "calibre/gui2/convert/gui_conversion.py", line 31, in gui_convert_recipe
  File "calibre/gui2/convert/gui_conversion.py", line 25, in gui_convert
  File "calibre/ebooks/conversion/plumber.py", line 1108, in run
  File "calibre/customize/conversion.py", line 242, in __call__
  File "calibre/ebooks/conversion/plugins/recipe_input.py", line 137, in convert
  File "calibre/web/feeds/news.py", line 1056, in download
  File "calibre/web/feeds/news.py", line 1225, in build_index
  File "<string>", line 77, in parse_index
  File "calibre/web/feeds/news.py", line 706, in index_to_soup
  File "mechanize/_mechanize.py", line 241, in open_novisit
  File "mechanize/_mechanize.py", line 313, in _mech_open
mechanize._response.httperror_seek_wrapper: HTTP Error 308: Permanent Redirect
```

changind the urls to https instead of https fixes this.

Otherwise, it is more proper to use a dash and not a hyphen in a name.
2022-01-23 17:05:50 +01:00
Kovid Goyal
0d14705d6a
string changes 2022-01-23 12:43:08 +05:30
Kovid Goyal
78ad0ae6f1
Edit book: Fix renaming of classes that start/end with non word characters not working 2022-01-23 12:20:50 +05:30
Kovid Goyal
0172b61217
Edit book: Preview panel: Fix hyphenation at end of line being rendered as boxes on macOS. Fixes #1958730 [Ebook editor: Breaking long words at the ends of lines causing boxes to be rendered instead of hyphens on macOS](https://bugs.launchpad.net/calibre/+bug/1958730) 2022-01-23 11:44:37 +05:30
Kovid Goyal
ad12732edc
less confusing name for website_en 2022-01-21 15:33:20 +05:30
Kovid Goyal
20e76a13b9
... 2022-01-21 15:26:07 +05:30
Kovid Goyal
73a2648bfa
Unicode normalize string received from metadata download plugins 2022-01-21 15:24:22 +05:30
Kovid Goyal
38aca62463
Use sphinx extlinks for various website links 2022-01-21 10:54:42 +05:30
Kovid Goyal
e90b87cdfe
version 5.35.0 2022-01-21 07:52:17 +05:30
Kovid Goyal
876b8bb127
Merge branch 'master' of https://github.com/davidfor/calibre 2022-01-21 07:28:23 +05:30
David
547868a4c8 Bump supported Kobo firmware version
No other changes are needed for supporting this version.
2022-01-21 10:25:16 +11:00
Kovid Goyal
d82e76b32d
pep8 2022-01-20 20:14:41 +05:30
Kovid Goyal
5d60be4033
Tag browser: Fix the find box not using all available width. Fixes #1958490 [Private bug](https://bugs.launchpad.net/calibre/+bug/1958490) 2022-01-20 14:38:26 +05:30
Kovid Goyal
73ffadea06
Fix a spurious error when cancelling addition of a tag to the insert tag menu 2022-01-20 14:17:42 +05:30
Kovid Goyal
e303e85d2a
... 2022-01-20 09:39:07 +05:30
Kovid Goyal
e14f96454f
Also sanitize email address used for testing 2022-01-20 09:32:20 +05:30
Kovid Goyal
da339e639d
Remove unused code 2022-01-20 08:50:04 +05:30
Kovid Goyal
f689517d1a
Fix #1954890 [[Feature Request] Content Server: Search results with number of items found](https://bugs.launchpad.net/calibre/+bug/1954890) 2022-01-19 11:04:16 +05:30
Kovid Goyal
23fe52192b
Fix #1957841 [[Enhancement] Use the same date format in context menu as in Book details panel/window](https://bugs.launchpad.net/calibre/+bug/1957841) 2022-01-18 11:15:40 +05:30
Kovid Goyal
0cf7af69ac
Comic conversion: Fix conversion of comic images that are stored as 8-bit grayscale images in JPEG format not working when converting to PDF. Fixes #1956932 [pdf convertion of 8 bit jpg](https://bugs.launchpad.net/calibre/+bug/1956932) 2022-01-17 21:24:27 +05:30
Kovid Goyal
5d15c9ded4
Merge branch 'master' of https://github.com/cbhaley/calibre 2022-01-17 17:29:48 +05:30
Charles Haley
32b6f9943a 1) Performance improvements for icon etc rules.
2) Make comparisons of undefined floats and ints consistent with template language conditionals, where undefined is assumed to be zero.
2022-01-17 11:50:16 +00:00
Kovid Goyal
8423f761af
Hide date conditions when match type is set/unset 2022-01-17 13:02:11 +05:30
Kovid Goyal
7c59955b54
Add set/unset operators for date searches in the advanced search dialog 2022-01-17 12:16:08 +05:30
Kovid Goyal
575c46310a
DRYer 2022-01-17 12:09:16 +05:30
Kovid Goyal
d72a4a106f
LRF Input: Fix a regression in calibre 5 that broke parsing of some LRF files
Fixes #1958115 [Viewing or converting LRF fails with TypeError](https://bugs.launchpad.net/calibre/+bug/1958115)
2022-01-17 12:06:31 +05:30
Kovid Goyal
3488e9107e
Coloring/icon rules: Allow creating a rule for date columns that matches *today*
Fixes #1956006 [[Enhancement] Harmonise Date Conditions](https://bugs.launchpad.net/calibre/+bug/1956006)
2022-01-17 11:58:19 +05:30
Kovid Goyal
2b41671370
ODT metadata: Support reading tags from multiple <keyword> elements 2022-01-16 19:32:52 +05:30
Kovid Goyal
57d67d9deb
Use QStylePainter for drawing hover raised frames
This is needed for correct styling with Qt6 and is nicer code anyway
2022-01-16 05:14:55 +05:30
Kovid Goyal
b29a8f8afa
Update Foreign Affairs 2022-01-16 04:51:08 +05:30
Kovid Goyal
8760b3cf71
... 2022-01-16 04:33:31 +05:30
Kovid Goyal
8841a9201b
E-book viewer: Fix searching for text near the end of a chapter sometimes not working. Fixes #1958028 [ebook-viewer search claims text at end of chapter is "hidden"](https://bugs.launchpad.net/calibre/+bug/1958028) 2022-01-16 04:31:55 +05:30
Kovid Goyal
a75aea2346
More context menu icons 2022-01-15 13:28:04 +05:30
Kovid Goyal
d25a9e830f
Icons for book details cover context menu 2022-01-15 13:17:41 +05:30
Kovid Goyal
1fad7b32ab
Edit book: Reports: Show thumbnail previews of SVG images 2022-01-15 13:07:20 +05:30
Kovid Goyal
bf53bbf07a
String changes 2022-01-14 15:18:26 +05:30
Kovid Goyal
a96272c678
Fix #1955458 [[Enhancement] Unnecessary delimiter](https://bugs.launchpad.net/calibre/+bug/1955458) 2022-01-14 15:11:13 +05:30
Kovid Goyal
0915f05e82
Fix #1957741 [[Enhancement] Padding larger for Transform HTML tab content](https://bugs.launchpad.net/calibre/+bug/1957741) 2022-01-14 14:54:33 +05:30
Kovid Goyal
afd1aaeb24
Use library icons in the choose and copy menus 2022-01-14 14:34:54 +05:30
Kovid Goyal
cff77aab39
Simple QIcon.ic implementation
Can be used for new code so that it works in master and qt6 branches
2022-01-14 14:22:25 +05:30
Kovid Goyal
b4fb003820
Fix #1957163 [[Enhancement] Add icon to context menu](https://bugs.launchpad.net/calibre/+bug/1957163) 2022-01-12 16:46:44 +05:30
Kovid Goyal
60ae49087b
Merge branch 'master' of https://github.com/cbhaley/calibre 2022-01-12 15:41:00 +05:30
Charles Haley
06b366fae2 Bug 1957122: Search results after updating composite column 2022-01-12 09:33:20 +00:00
Charles Haley
a0ebf203a6 Bug 1957131: Hierarchical search: "Current search is not a saved search" when getting expression from tag browser 2022-01-12 09:25:15 +00:00
Kovid Goyal
17eee10e6a
string changes 2022-01-11 12:16:45 +05:30
Kovid Goyal
29e9a86619
Show number of files to be pasted from other instance 2022-01-11 12:02:33 +05:30
Kovid Goyal
0e90df8926
Ignore icons.rcc 2022-01-11 11:28:20 +05:30
Kovid Goyal
3a216330b4
Dw.de by xav
https://www.mobileread.com/forums/showthread.php?t=344295
2022-01-11 11:21:36 +05:30
Kovid Goyal
44ee1de2f5
Merge branch 'master' of https://github.com/cbhaley/calibre 2022-01-09 20:35:13 +05:30
Charles Haley
a42caf4532 Fix for new CALIBRE_FORCE_BUILD_UI_FORMS environment variable causing exception because of a missing import. 2022-01-09 14:59:34 +00:00
Kovid Goyal
4a3bb3ac93
... 2022-01-09 19:08:55 +05:30
Kovid Goyal
5e3244c65c
Allow using an env var to force forms to be re-built 2022-01-09 18:30:26 +05:30
Kovid Goyal
65923491f1
py310: More int->float goodness 2022-01-09 12:33:53 +05:30
Kovid Goyal
67ad530492
py310: more float->int goodness 2022-01-09 05:28:21 +05:30
Kovid Goyal
71246f3c2e
Merge branch 'master' of https://github.com/cbhaley/calibre 2022-01-09 04:15:55 +05:30
Charles Haley
3c97500e1a Enum problem that prevents creating custom columns on calibre 6 beta 2022-01-08 18:38:04 +00:00
Kovid Goyal
24c460faec
also upgrade code in setup folder 2022-01-08 12:15:18 +05:30
Kovid Goyal
f47f50d359
... 2022-01-08 11:51:15 +05:30
Kovid Goyal
eb78a761a9
Automated upgrade of code to python 3.7+
Done by https://github.com/asottile/pyupgrade
Consists mainly of moving string formatting to f-strings and removing
encoding declarations
2022-01-08 11:47:40 +05:30
Kovid Goyal
224db2bb02
command to upgrade source code 2022-01-08 11:26:18 +05:30
Kovid Goyal
2e56a2de31
Fix #1956779 [Cant read epub file written using ebooklib](https://bugs.launchpad.net/calibre/+bug/1956779) 2022-01-08 08:54:33 +05:30
Kovid Goyal
a0c55c9026
Merge branch 'patch-1' of https://github.com/timotheeandres/calibre 2022-01-08 08:38:10 +05:30
Kovid Goyal
831a67d127
Add link to chromium bug for hyphenate char on macos 2022-01-08 08:36:58 +05:30
Timothée Andres
36011dc3a3
Reduce image compression in equestria_daily recipe
The website https://www.equestriadaily.com/ often uses images in its articles, and from what I have seen the images get compressed so much that text is basically unreadable on them.
This fix mitigates this issue by reducing the compression factor from 16 to 4, which slightly increases the size of the newspaper but makes it more enjoyable and readable.
2022-01-07 20:08:07 +01:00
Kovid Goyal
f9fb012322
Auto trigger matching book search for not too large libraries 2022-01-07 20:36:34 +05:30
Kovid Goyal
b42b694c56
Merge branch 'master' of https://github.com/cbhaley/calibre 2022-01-07 17:28:35 +05:30
Charles Haley
c44af8e71a Create custom column dialog: Fix exception if the library has no custom columns 2022-01-07 11:54:24 +00:00
Kovid Goyal
cc96900aee
E-book viewer: Fix auto hyphenation on macOS not rendering the hyphens correctly. Fixes #1954714 [Ebook viewer: Breaking long words at the ends of lines causing boxes to be rendered instead of hyphens on macOS](https://bugs.launchpad.net/calibre/+bug/1954714) 2022-01-07 11:08:59 +05:30
Kovid Goyal
141ff585c9
... 2022-01-07 08:11:12 +05:30
Kovid Goyal
37334d19cc
Merge branch 'master' of https://github.com/cbhaley/calibre 2022-01-07 07:50:26 +05:30
Charles Haley
28257cad31 Another enum cleanup.
While testing that I found several problems related to adding and editing columns when the table was sorted differently.

Also prevented moving rows when the table is sorted by anything but row number ascending. This isn't the nicest fix but making it work with new columns while the sort is descending is harder than I want to deal with tonight.
2022-01-06 18:42:48 +00:00
Kovid Goyal
d16195472c
Cleanup previous PR 2022-01-06 20:51:57 +05:30
Kovid Goyal
e03a52e445
Merge branch 'master' of https://github.com/cbhaley/calibre 2022-01-06 20:51:45 +05:30
Charles Haley
843dc628c7 Enhancement: allow sorting the columns in the create custom column dialog. 2022-01-06 13:25:30 +00:00
Kovid Goyal
6b10f5cc81
pep8 2022-01-05 22:05:56 +05:30
Kovid Goyal
7eff3249ae
Merge branch 'master' of https://github.com/cbhaley/calibre
Fix #1956377 [lookup name duplicity is not checked when editing user-defined column](https://bugs.launchpad.net/calibre/+bug/1956377)
2022-01-05 22:04:34 +05:30
Charles Haley
ef75f82fc0 Bug 1956377: lookup name duplicity is not checked when editing user-defined column
Fixing this required substantial cleanup of the dialog.

While there I added a column to the dialog showing the status of the column: edited, new, deleted.
2022-01-05 16:23:57 +00:00
Kovid Goyal
85c25916a3
Merge branch 'patch-4' of https://github.com/reportxx/calibre 2022-01-05 14:38:30 +05:30
reportxx
8e240e37d4
Update copyright year 2022-01-05 08:28:07 +00:00
Kovid Goyal
5c3376f778
py310: More float->int goodness 2022-01-05 09:26:50 +05:30
Kovid Goyal
ec72e4f39d
Check for deletion in worker thread before emitting signal 2022-01-03 21:23:13 +05:30
Kovid Goyal
68e16a0d12
Merge branch 'master' of https://github.com/cbhaley/calibre 2022-01-03 17:36:04 +05:30
Kovid Goyal
9aa548bd3b
Update MIT Technology Review 2022-01-03 17:27:48 +05:30
Charles Haley
f30a190b36 Change db.cache.virtual_libraries_for_books() to raise an exception when recursion is detected instead of returning an empty list. Using an exception gives a better chance of telling the user that the VL expression is wrong. 2022-01-03 11:47:38 +00:00
Kovid Goyal
6a3309175a
E-book viewer: Remove books that dont exist from the recently opened book list. Fixes #1956192 [Feature request: possibility to remove book from recently opened books in Viewer](https://bugs.launchpad.net/calibre/+bug/1956192) 2022-01-03 12:11:17 +05:30
Kovid Goyal
f0d5251692
Fix #1956198 [[Enhancement] View book from Book details window by pressing 'V'](https://bugs.launchpad.net/calibre/+bug/1956198) 2022-01-03 11:18:09 +05:30
Kovid Goyal
cfb011c3ff
pyqt6: More keyboard modifiers nonsense and another py310 float->int 2022-01-03 09:02:26 +05:30
Kovid Goyal
749d0351e8
Merge branch 'master' of https://github.com/cbhaley/calibre 2022-01-02 18:49:02 +05:30
Charles Haley
9a95d8b0c2 More CreateNewCustomColumn stuff.
- Improved documentation
- Check column headings for duplicates
- Method to return the current column headings as a dict
- Improved exception handling
2022-01-02 12:59:30 +00:00
Kovid Goyal
fbb5208aac
Completion popup: Fix display of items containing line breaks 2022-01-02 08:46:18 +05:30
Kovid Goyal
eb2360f6aa
Merge branch 'master' of https://github.com/cbhaley/calibre 2022-01-01 19:43:39 +05:30
Charles Haley
7b9bb6e624 Yet another version of CreateNewCustomColumn.
My apologies for the multiple commits. I have been working with @davidfor and we cycled a few times. I hope this is the last, barring bugs.
2022-01-01 13:20:38 +00:00
Kovid Goyal
f3183880e7
Merge branch 'master' of https://github.com/cbhaley/calibre
Fixes #1956129 [[Enhancement] render line breaks in custom column *description* on hover column title](https://bugs.launchpad.net/calibre/+bug/1956129)
2022-01-01 18:42:19 +05:30
Charles Haley
6fcd0eb8a5 Enhancement #1956129: render line breaks in custom column *description* on hover column title. 2022-01-01 11:39:32 +00:00
Kovid Goyal
3f16b5ac61
Update Reuters 2022-01-01 14:34:27 +05:30
Kovid Goyal
fdbffe60fe
MOBI output: Dont fail if input document contains invalid % based lengths. Fixes #1956097 [news download crashes with TypeError: '<' not supported between instances of 'float' and 'str'](https://bugs.launchpad.net/calibre/+bug/1956097) 2021-12-31 20:48:14 +05:30
Kovid Goyal
ce138b1744
Update Clarin 2021-12-31 20:46:51 +05:30
Kovid Goyal
f0d82724f9
pep8 2021-12-31 19:45:26 +05:30
Kovid Goyal
ac5c8858d6
Merge branch 'master' of https://github.com/cbhaley/calibre 2021-12-31 19:45:00 +05:30
Charles Haley
40cae7cc81 More improvements to the new CreateNewCustomColumn class.
-- Added the ability to auto-generate a lookup name
-- Now checks the calibre "can't configure" before adding a new column
-- Fixed parameter names
2021-12-31 13:49:53 +00:00
Kovid Goyal
422258bcce
Update General Knowledge Today 2021-12-31 17:23:19 +05:30
Kovid Goyal
21ee73763a
Fix Preferences->Searching->Clear search histories not taking effect till a restart for some search boxes. Fixes #1956088 [Clear Search Histories not clearing search histories.](https://bugs.launchpad.net/calibre/+bug/1956088) 2021-12-31 13:38:49 +05:30
Kovid Goyal
addec17bb2
Merge branch 'image-xcf' of https://github.com/qykth-git/calibre 2021-12-31 12:59:25 +05:30
YOKOTA Hiroshi
bddb3bc001 media-types: use image/x-xcf rather than application/x-xcf to match gimp.desktop
See also:
  Re: [Gimp-developer] Mime type application/x-xcf in /etc/mime.types vs image/x-xcf in gimp.desktop
  https://mail.gnome.org/archives/gimp-developer-list/2021-July/msg00001.html
2021-12-31 13:39:25 +09:00
Kovid Goyal
907fd3262f
Merge branch 'master' of https://github.com/cbhaley/calibre 2021-12-31 05:48:41 +05:30
Charles Haley
f3b15ec4b4 A bit of cleanup. 2021-12-30 20:59:09 +00:00
Charles Haley
8119f71db1 Improvements to the CreateNewCustomColumn class/method: add the display as a parameter. 2021-12-30 16:27:50 +00:00
Kovid Goyal
75afcfbd1c
Update Popular Science 2021-12-30 20:54:15 +05:30
Kovid Goyal
1daad1bda9
Merge branch 'master' of https://github.com/cbhaley/calibre 2021-12-30 18:15:23 +05:30
Charles Haley
4540cd920e Enhancement 1956007: cc_icons dropdown in Template Tester.
This isn't the requested fix, which I am not going to do. Instead it extends the number of books in the test section of the template dialog from 1 to all selected.
2021-12-30 12:36:45 +00:00
Kovid Goyal
9dfa3f89db
calibredb catalog: Fix --ids and --search options not working for cvx/xml catalogs. Fixes #1955967 ['calibredb catalog' options broken: --ids and --search](https://bugs.launchpad.net/calibre/+bug/1955967) 2021-12-30 17:30:42 +05:30
Kovid Goyal
67cddcea52
Merge branch 'master' of https://github.com/cbhaley/calibre
Fix #1955732 [Hierarchical entries in user category may not merge correctly in tag browser](https://bugs.launchpad.net/calibre/+bug/1955732)
2021-12-25 19:55:14 +05:30
Charles Haley
2252d7f088 Bug #1955732: Hierarchical entries in user category may not merge correctly in tag browser
Note that this fix works with grouped search terms. 'Real' user categories will never be merged because the source category is part of the 'name'
2021-12-25 13:54:33 +00:00
Kovid Goyal
eb162a4821
pep8 2021-12-24 20:59:06 +05:30
Kovid Goyal
97934eb1b6
Remove debug print() 2021-12-24 20:58:28 +05:30
Kovid Goyal
c36036f05f
Merge branch 'master' of https://github.com/cbhaley/calibre 2021-12-24 20:57:27 +05:30
Charles Haley
53926a0cb2 Enhancement: provide a method to create a new custom column using the dialog. It is intended for use by plugins 2021-12-24 15:03:30 +00:00
Kovid Goyal
e0dfaaa389
Attempt to fix Irish Times login 2021-12-23 11:01:49 +05:30
Kovid Goyal
1ce8a59eea
Add supernote a5x product id 2021-12-23 10:26:22 +05:30
Kovid Goyal
3ce5b7f2ad
Update paths to workaround Apple's security theatre 2021-12-23 10:23:56 +05:30
Kovid Goyal
df3a19ef42
Change supernote folder from Documents to Document 2021-12-22 21:19:24 +05:30
Kovid Goyal
d51a453a73
Equestria Daily by Timothee Andres 2021-12-20 10:29:51 +05:30
Kovid Goyal
aec2c1a551
AZW3 Input: Handle AZW3 files with incorrect TAGX Offset INDX header fields. Fixes #1955308 [MOBI reader loads TAGX from wrong offset](https://bugs.launchpad.net/calibre/+bug/1955308) 2021-12-19 08:56:36 +05:30
Kovid Goyal
172ee5d531
Update The BBC
For some reason it now serializes the article JSON as a dict serialized
as string.
2021-12-19 08:30:13 +05:30
Kovid Goyal
559bba5fa9
Also remember all files for the add formats button in the edit metadata dialog 2021-12-19 08:10:55 +05:30
Kovid Goyal
b50a2449fe
py310: More float->int goodness
Fixes #1955311 [Error converting ePUB to MOBI during Rasterizing SVG images](https://bugs.launchpad.net/calibre/+bug/1955311)
2021-12-19 07:58:19 +05:30
Kovid Goyal
dafa08e921
Fix path used to init_calibre module installation
Fixes #1553 (Fix python site-package libdir creation in FreeBSD)
2021-12-17 17:23:35 +05:30
Kovid Goyal
07b4563c36
py3compat: Another PDB ereader output fix 2021-12-17 17:13:25 +05:30
Kovid Goyal
1127c285bb
Merge branch 'fix_socket_close' of https://github.com/pawl/calibre 2021-12-17 11:28:54 +05:30
Paul Brown
4763f4363b close Connection socket after server disconnect 2021-12-16 23:49:13 -06:00
Kovid Goyal
c91d35ffa4
Use the correct enum for acceptnavrequest 2021-12-17 08:38:03 +05:30
Kovid Goyal
0759ab8589
Fix closing open book panel not quitting viewer 2021-12-17 08:36:17 +05:30
Kovid Goyal
ba1b75e9fd
Sort the names in the manage file excludes list 2021-12-17 07:29:41 +05:30
Kovid Goyal
3477e6395c
version 5.34.0 2021-12-17 06:10:19 +05:30
Kovid Goyal
5e695e8d96
py310: And another. Fixes #1955069 [Quick-select Virtual Library broken w/ python3.10](https://bugs.launchpad.net/calibre/+bug/1955069) 2021-12-17 05:29:24 +05:30
Kovid Goyal
1cdb757969
Merge branch 'master' of https://github.com/cbhaley/calibre 2021-12-16 22:43:57 +05:30
Charles Haley
a66904bd9e Minor message error I happened to notice. 2021-12-16 17:05:46 +00:00
Kovid Goyal
b83560f85c
string changes 2021-12-16 21:58:01 +05:30
Kovid Goyal
535dd78c6f
Remove unused imports 2021-12-16 21:36:03 +05:30
Kovid Goyal
d350a121d8
Edit book: Spell check: Add an exclude files button 2021-12-16 21:26:44 +05:30
Kovid Goyal
a507bb01ce
py310: More float->int goodness
Fixes #1955024 [Failed to start Calibre](https://bugs.launchpad.net/calibre/+bug/1955024)
2021-12-16 16:14:16 +05:30
Kovid Goyal
183e5c3be3
Merge branch 'close' of https://github.com/xxyzz/calibre 2021-12-16 10:48:55 +05:30
Kovid Goyal
c615bf8b1c
Edit book: Fix pressing F8 to jump to next misspelled word not working after last word in current file 2021-12-16 10:46:38 +05:30
xxyzz
b37a4b1f7a
close sysfs file 2021-12-16 13:15:21 +08:00
Kovid Goyal
c3925db827
py310: Yet another float->int 2021-12-16 08:18:09 +05:30
Kovid Goyal
ff1ee01b3b
py310: Fix #1954951 [manual trimming of cover throws exception w/ python 3.10](https://bugs.launchpad.net/calibre/+bug/1954951) 2021-12-16 08:16:46 +05:30
Kovid Goyal
0a9778caa3
py3 compat: Fix PDB ereader output broken in calibre 5
Fixes #1954889 [Error when converting to pdb ereader](https://bugs.launchpad.net/calibre/+bug/1954889)
2021-12-15 13:36:24 +05:30
Kovid Goyal
2c6a73534a
Fix #1953469 [Private bug](https://bugs.launchpad.net/calibre/+bug/1953469) 2021-12-15 13:33:41 +05:30
Kovid Goyal
c1dc45a79f
Edit book: Reports: Include descendant selectors that use classes when counting class usage. Fixes #1954839 [Style classes wrongly reported as 0 (unused)](https://bugs.launchpad.net/calibre/+bug/1954839) 2021-12-15 10:46:17 +05:30
Kovid Goyal
8c2aa4182c
DRYer 2021-12-15 08:15:26 +05:30
Kovid Goyal
4669ca7d8b
EPUB/MOBI Catalogs: Increase the maximum thumbnail size to 3 inches from 2 inches 2021-12-14 20:43:40 +05:30
Kovid Goyal
5101ca89de
Fix #1954645 [Private bug](https://bugs.launchpad.net/calibre/+bug/1954645) 2021-12-14 20:14:55 +05:30
Kovid Goyal
9ed24d754b
Allow creating a shortcut in preferences->Shortcuts->Edit metadata to paste metadata ignoring the value of the exclude_fields tweak. Fixes #1953739 [[Enhancement] Paste metadata - Override 'exclude_fields_on_paste' setting](https://bugs.launchpad.net/calibre/+bug/1953739) 2021-12-14 18:28:06 +05:30
Kovid Goyal
988b7d97f2
Edit book: Allow adding a comment to an individual HTML/OPF/NCX file to exclude it from being checked when running the spell check tool 2021-12-14 15:46:20 +05:30
Kovid Goyal
4142b93443
string changes 2021-12-14 14:44:45 +05:30
Kovid Goyal
1dfe4bd1c0
Use a UA based on random english words
Cloudflare appears to block http requests with common browser user
agents, probably it checks for some other header field with the user
agent
2021-12-14 12:52:34 +05:30
Kovid Goyal
07f72d2d94
E-book viewer: Fix an error when opening some books with highlights that span inline text formatting
Fixes #1954726 [epub file no longer opens](https://bugs.launchpad.net/calibre/+bug/1954726) [epub file no longer opens](https://bugs.launchpad.net/calibre/+bug/1954726)

normalize() modifies the text nodes, and can potentially result in a
previously selected node no longer having a parent causing wrap() to
throw an exception. In any case normalizing once after all nodes have
been wrapped is faster.
2021-12-14 12:30:54 +05:30
Kovid Goyal
27b2f3a92a
E-book viewer: Displays links marked up as glossary and bibliography links as popups. Fixes #1954715 [Support ARIA doc-biblioref and doc-glossref](https://bugs.launchpad.net/calibre/+bug/1954715) 2021-12-14 11:54:03 +05:30
Kovid Goyal
842e99428e
py310 compat: QWebEngineSettings::setFontSize
Fixes #1954688 [--pdf-default-font-size is read as float](https://bugs.launchpad.net/calibre/+bug/1954688)
2021-12-14 11:44:33 +05:30
Kovid Goyal
643de95a64
Merge branch 'master' of https://github.com/davidfor/calibre 2021-12-14 11:37:30 +05:30
Kovid Goyal
9085cc2846
Merge branch 'master' of https://github.com/michaeldleslie/calibre
Fixes #1954708 [Unhandled exception when downloading covers and metadata](https://bugs.launchpad.net/calibre/+bug/1954708)
2021-12-14 11:36:26 +05:30
David
616d9bfbbb Don't exclude slashes when parsing URLs for identifier rules
Not sure why I had excluded the slash as a valid character in the identifier. There are a few sites that do this.
2021-12-14 15:03:45 +11:00
Michael Leslie
b23064a54d py310 support: explicit cast to int 2021-12-13 18:52:59 -08:00
Kovid Goyal
aed39272af
Ignore deprecation warning from apsw 2021-12-13 22:19:04 +05:30
Kovid Goyal
f01268b2ec
Remove deprecated distutils 2021-12-13 21:55:53 +05:30
Kovid Goyal
b6da6d9680
Another 3.10 deprecation 2021-12-13 20:35:03 +05:30
Kovid Goyal
7632beb8e0
Replace use of distutils to get installation location for init_env.py 2021-12-13 20:29:35 +05:30
Kovid Goyal
821f71cc4c
Fix test failing on python 3.10 2021-12-13 20:11:30 +05:30
Kovid Goyal
a445a73e66
A simpler solution for word wrapping in the tweaks list view 2021-12-13 20:02:53 +05:30
Kovid Goyal
c171839304
more pyqt6 nonsense 2021-12-13 19:47:15 +05:30
Kovid Goyal
cd42a1c644
Avoid parsing the undefined number sort key tweak for every undefined number 2021-12-13 19:43:34 +05:30
Charles Haley
bd7dbfec43
Take 2 on the numeric sort and the tweaks scroll bar changes 2021-12-13 19:43:18 +05:30
Charles Haley
5d9c5ebd58
Enhancement: add a tweak to provide the sort value for undefined numbers. 2021-12-13 19:42:49 +05:30
Kovid Goyal
519f06b4af
Merge branch 'master' of https://github.com/cbhaley/calibre
Fixes #1954572 [Enhancement request: Template tester: Save word wrap setting](https://bugs.launchpad.net/calibre/+bug/1954572)
2021-12-12 18:08:49 +05:30
Charles Haley
986f778593 Enhancement #1954572: Template tester: Save word wrap setting 2021-12-12 11:00:45 +00:00
Kovid Goyal
4ccbc01125
Merge branch 'fix-pocket-recipe' of https://github.com/grdryn/calibre 2021-12-12 08:04:10 +05:30
Gerard Ryan
6590bcd76e
Fix Pocket/readitlater recipe
This recipe wasn't working (at least for me), where it would
consistently fail with the following error when trying to download an
article:

```
Traceback (most recent call last):
  File "calibre/utils/threadpool.py", line 100, in run
  File "calibre/web/feeds/news.py", line 1186, in fetch_obfuscated_article
  File "<string>", line 157, in get_obfuscated_article
  File "<string>", line 142, in get_textview
  File "re.py", line 201, in search
TypeError: expected string or bytes-like object
```

I believe this is because Pocket don't allow access to their
"Article View" API by default:
https://getpocket.com/developer/docs/v3/article-view

This change uses the original URL of the article, rather than the
pocket url for it (those `getpocket.com/a/read/<id>` URLs in the
browser seem to just redirect me to `getpocket.com/my-list`). I've a
feeling that the old way might have produced cleaner articles (Pocket
cleanup & then Calibre cleanup), but I've never seen it work
successfully.

We could alternatively try to convince Pocket to enable that API for
the "app" we use here (I think this usage would qualify, as it's a
"Pocket specific feature" (for Calibre)). That might require adopting
their full OAuth flow, rather than using username/password. From
reading their API docs with Calibre in mind, I think that would mean
we'd have to have a web page somewhere that the user would have to
access in their normal web browser, click a button to redirect them to
the Pocket page to authorize the Calibre app to access their Pocket
account, which would then redirect them back to our web page where
we'd instruct them to enter the access token into the "password" field
for the recipe in Calibre.
2021-12-11 22:52:20 +00:00
Kovid Goyal
2a45519e5d
Merge branch 'master' of https://github.com/cbhaley/calibre
Fixes #1954562 [Strange search results after updating stored template](https://bugs.launchpad.net/calibre/+bug/1954562)
2021-12-11 19:23:14 +05:30
Charles Haley
dd02f58568 Bug #1954562: Strange search results after updating stored template 2021-12-11 12:55:58 +00:00
Kovid Goyal
1e8e109b40
Merge branch 'master' of https://github.com/dirkgomez/calibre 2021-12-11 17:37:10 +05:30
Dirk Gómez
d473641f81 Make El Pais recipe work with redesigned site 2021-12-11 12:51:23 +01:00
Kovid Goyal
e15227eb0c
Supernote needs Documents not NOOK 2021-12-11 12:08:43 +05:30
Kovid Goyal
6db6e338e3
Add local virtual-machines.conf to gitignore 2021-12-11 08:33:15 +05:30
Kovid Goyal
6a921b2396
MTP driver: Dont send the calibre device db files to the root folder on the supernote a5 x as it fails. Fixes #1954460 [Supernote ax5](https://bugs.launchpad.net/calibre/+bug/1954460) 2021-12-11 08:31:48 +05:30
Kovid Goyal
fe7c125d6d
Use NOOK_COLOR for the Glowlight 4 2021-12-10 20:49:43 +05:30
Kovid Goyal
95b852684e
Need the qt5 branch of bypy for calibre 5 2021-12-10 20:21:23 +05:30
Kovid Goyal
ef87339298
Use a private copy of the bypy scripts so it doesnt conflict with the developments for the qt6 branch 2021-12-10 14:26:17 +05:30
Kovid Goyal
8169268ee3
Driver for Nook Glowlight 4 2021-12-10 08:03:30 +05:30
Kovid Goyal
425152cda2
Fix langauge not being detected on amazon.de 2021-12-08 20:53:14 +05:30
Kovid Goyal
0f56a27b97
ToC Editor: Workaround an occasional error when closing on Windows if the file being edited is in a DropBox/antivirus prone area 2021-12-08 20:28:54 +05:30
Kovid Goyal
631bb7652f
Fix a regression in the previous release that broke creating new keyboard shortcuts 2021-12-06 20:13:39 +05:30
Kovid Goyal
59a732d181
Merge branch 'master' of github.com:kovidgoyal/calibre 2021-12-06 20:09:36 +05:30
Kovid Goyal
48a09b77f9
Update American Prospect 2021-12-06 20:09:14 +05:30
Kovid Goyal
cb07ca7b70
pyqt6: Use QStylePainter for separators
In pyqt6 QApplication::style() returns QCommonStyle instead of the proxy
calibre style I install using C++. QStylePainter gets around that.
2021-12-06 20:09:07 +05:30
Kovid Goyal
56dd01a591
FlowToolbar: Move entire groups rather than individual buttons 2021-12-06 20:09:02 +05:30
Kovid Goyal
f4c3fb26c1
Update Mediapart 2021-12-06 05:28:38 +05:30
Kovid Goyal
d8f28f669c
version 5.33.2 2021-12-04 14:57:39 +05:30
Kovid Goyal
918d9dbd50
... 2021-12-04 14:54:13 +05:30
Kovid Goyal
e113bf1657
Use py_ssize_t for a # format when calling py_buildvalue 2021-12-04 14:52:15 +05:30
Kovid Goyal
869f556365
Fix comments editor toolbars not appearing after a hide/show toggle
Also, move the initial creation update geometry call into the comments
edit widget itself
2021-12-04 13:27:22 +05:30
Kovid Goyal
08792b74df
... 2021-12-04 11:00:00 +05:30
Kovid Goyal
8c58e3b822
version 5.33.1 2021-12-04 10:58:37 +05:30
Kovid Goyal
a475b97cef
Fix double text draw and centering in centered button 2021-12-04 10:56:42 +05:30
Kovid Goyal
260a59b17f
Fix dark mode rendering of download metadata button incorrect on windows
There is a bug in Qt where using a proxy style with dark mode breaks
rendering. So instead draw the button directly.
2021-12-04 10:44:43 +05:30
Kovid Goyal
10572c8746
Fix comments editor dialog not displaying toolbar until resized 2021-12-04 08:30:53 +05:30
Kovid Goyal
0ef264056f
Set an appropriate size hint for the comments dialog 2021-12-04 08:21:34 +05:30
Kovid Goyal
414fc5f669
Get rid of another .ui file 2021-12-04 08:14:34 +05:30
Kovid Goyal
4df7935799
Fix getting branch name not working if HEAD is also a tag 2021-12-03 10:59:05 +05:30
1168 changed files with 160989 additions and 127480 deletions

View file

@ -7,7 +7,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
os: [ubuntu-latest, macos-latest, windows-2019]
steps:
- name: Checkout source code
uses: actions/checkout@master

View file

@ -27,9 +27,6 @@ jobs:
- name: Install calibre dependencies
run: setup/arch-ci.sh
- name: Install translations dependencies
run: python -m pip install transifex-client
- name: Bootstrap calibre
run: runuser -u ci -- python setup.py bootstrap --ephemeral

2
.gitignore vendored
View file

@ -10,6 +10,7 @@ compile_commands.json
link_commands.json
src/calibre/plugins
resources/images.qrc
resources/icons.rcc
manual/generated
manual/locale
manual/.doctrees
@ -58,3 +59,4 @@ recipes/debug
/*env*/
cmake-build-*
bypy/b
bypy/virtual-machines.conf

View file

@ -1,5 +1,5 @@
Files: *
Copyright: Copyright (C) 2008-2020 Kovid Goyal <kovid@kovidgoyal.net>
Copyright: Copyright (C) 2008-2022 Kovid Goyal <kovid@kovidgoyal.net>
License: GPL-3
The full text of the GPL is distributed as in
/usr/share/common-licenses/GPL-3 on Debian systems.

View file

@ -6,7 +6,7 @@
# to the ticket list.
# Also, each release can have new and improved recipes.
# {{{ 5.x.0 2021-xx-xx
# {{{ 5.x.0 2022-xx-xx
#
# :: new features
#
@ -23,7 +23,234 @@
# - title by author
# }}}
{{{ 5.33.0 2021-12-03
{{{ 5.38.0 2022-03-04
:: new features
- [1852929] E-book viewer: When displaying estimated time to completion for reading a book, remember the reading rate the next time the book is opened
- [1961500] Dark theme: Highlight the current cell in the book list with a lighter background and different foreground to make it more obvious
- [1961639] An option to disable editing composite columns in the main book list when Tabbing through them (Preferences->Look & feel->Edit metadata)
:: bug fixes
- Tag editor: Fix regression in previous release that caused double clicking on tags to not work on non Linux platforms
- [1962365] Copy to library: Fix annotations not being copied
- [1962213] Edit book: Spell check: Fix words after a comment not being checked
- [1960554] PDF Output: Fix conversion failing if there are ToC entries pointing to removed content
- [1961775] E-book viewer: Fix an error when opening books with MathML for the second time if the last read position was at a MathML element
- Edit book: Fix double clicking to select a word also selecting smart quotes surrounding the word
- EPUB 3 metadata: Fix non-integer series index being sometimes represented using exponential notation
:: improved recipes
- Lenta.ru and aif.ru
- Indian Express
- Live Mint
- Mainichi
- Japan Times
:: new recipes
- Hindustan Times by unkn0wn
- India Legal Magazine by unkn0wn
- RT на русском by Vuizur
}}}
{{{ 5.37.0 2022-02-18
:: new features
- [1961129] Book details: Add actions to trim the cover to the right-click menu
- [1960586] Allow removing multiple email addresses at once in Preferences->Sharing by email
- Book details: Use a better mono-spaced font on Windows by default
- Add a tweak in Preferences->Tweaks to change the behavior of the Tab key when completing entries
- [1959928] Edit metadata: In "All in one" mode add an adjustable splitter between the cover and formats boxes
:: bug fixes
- [1960686] Textile output: Dont fail if input document has invalid padding or margin specifications
- [1960446] E-book viewer: Fix image display window not remembering its size and settings when run from within calibre
- E-book viewer: Fix setting to use roman numerals for series not being respected
- Edit book: When saving a copy do not fail if the original file has no write permissions
- [1960180] Embed fonts tool: Create <head> when missing
- Tag editor: Improve performance when very large number of tags present
:: improved recipes
- Live Mint
- The Hindu
- Reuters
- MMC RTV Slovenija
- Down To Earth
- Publico.PT
}}}
{{{ 5.36.0 2022-02-04
:: new features
- Edit metadata dialog: Allow controlling which custom columns are present in this dialog via Preferences->Look & feel->Edit metadata
- Edit metadata dialog: Allow manually sizing the various sections of the dialog in "All on 1 tab" mode
- Edit book: Spell checking: Update the bundled English and Spanish dictionaries
- [1958773] BibTeX catalogs: Support tags like custom columns
:: bug fixes
- [1959659] Amazon metadata download: Fix paragraphs in the comments being merged
- [1958979] Amazon.de metadata download: Fix published date and series information not being fetched for some books
- Email delivery: Fix sending email via Hotmail not working since this week because Microsoft changed the SMTP server name
- [1959220] Do not remove articles for titles in the Polish language
- [1959207] E-book viewer: When using Read aloud do not automatically lookup the highlighted word until read aloud is paused or stopped
- E-book viewer: Fix Ctrl+p shortcut for printing not working
- [1958882] Show an error when viewing a specific format and the file is missing
- Edit book: Fix renaming of classes that start/end with non word characters not working
- [1958730] Edit book: Preview panel: Fix hyphenation at end of line being rendered as boxes on macOS
- [1959893] Fix incorrect selection size displayed in Trim image dialog when image is scaled down to fit
- [1959782] Edit book: Fix pasting files from another editor instance failing if a file with the same name already exists
- [1959981] When reviewing metadata if the newly downloaded metadata has no language but there is an existing language, ensure it is preserved
:: improved recipes
- India Today
- Indian Express
- Live Mint
- Al Jazeera in English
- The Financial Express
- The Straits Times
:: new recipes
- title by author
}}}
{{{ 5.35.0 2022-01-21
:: new features
- [1956006] Coloring/icon rules: Allow creating a rule for date columns that matches *today*
- Kobo driver: Add support for new firmware
- [1954890] Content server: Show total number of results when searching for books
:: bug fixes
- [1958028] E-book viewer: Fix searching for text near the end of a chapter sometimes not working
- [1954714] E-book viewer: Fix auto hyphenation on macOS not rendering the hyphens correctly
- Edit book: Reports: Fix thumbnails of SVG images not rendered
- ODT metadata: Support reading tags from multiple <keyword> elements
- [1958115] LRF Input: Fix a regression in calibre 5 that broke parsing of some LRF files
- [1956097] MOBI output: Dont fail if input document contains invalid % based lengths
- [1955308] AZW3 Input: Handle AZW3 files with incorrect TAGX Offset INDX header fields
- [1956932] Comic conversion: Fix conversion of comic images that are stored as grayscale images in JPEG format not working when converting to PDF with image processing turned off
- [1955967] calibredb catalog: Fix --ids and --search options not working for CSV/XML catalogs
- [1958490] Tag browser: Fix the find box not using all available width
- [1956192] E-book viewer: Remove books that do not exist from the recently opened book list
- Completion popups: Fix display of items containing line breaks
- [1956129] Fix line breaks in custom column descriptions not being rendered in their tooltips
- [1956088] Fix Preferences->Searching->Clear search histories not taking effect till a restart for some search boxes
- [1955732] Hierarchical entries in user category may not merge correctly in tag browser
:: improved recipes
- Foreign Affairs
- MIT Technology Review
- Reuters
- Clarin
- General Knowledge Today
- Popular Science
:: new recipes
- Dw.de by xav
- Equestria Daily by Timothee Andres
}}}
{{{ 5.34.0 2021-12-17
:: new features
- Happy holidays to everyone!
- Driver for the new Nook Glowlight 4
- Edit book: Spell check tool: Add an exclude files button to exclude some files from being checked
- EPUB/MOBI Catalogs: Increase the maximum thumbnail size to 3 inches from 2 inches
- [1953739] Allow creating a shortcut in Preferences->Shortcuts->Edit metadata to paste metadata ignoring the value of the exclude_fields tweak
- [1954715] E-book viewer: Displays links marked up as glossary and bibliography links as popups
- [1954572] Add a tweak in Preferences->Tweaks to provide the sort value for undefined numbers
:: bug fixes
- Edit book: Fix pressing F8 to jump to next misspelled word not working after last word in current file
- [1954889] Fix PDB E-reader output broken in calibre 5
- [1954839] Edit book: Reports: Include descendant selectors that use classes when counting class usage
- [1954726] E-book viewer: Fix an error when opening some books with highlights that span in-line text formatting
- [1954460] MTP driver: Do not send the calibre device db files to the root folder on the Supernote A5 x as it fails
- ToC Editor: Workaround an occasional error when closing on Windows if the file being edited is in a DropBox/antivirus prone folder
- Fix a regression in the previous release that broke creating new keyboard shortcuts
- Comments editor: When flowing the tool bar onto multiple lines do not split up groups of buttons
- Various compatibility fixes for Python 3.10 used by some Linux distributions
:: improved recipes
- Pocket
- El Pais
- American Prospect
- Mediapart
}}}
{{{ 5.33.2 2021-12-03
:: new features
@ -53,10 +280,13 @@
- [1951507] E-book viewer: Fix sorting of highlights incorrect in books that use HTML ids with a hyphen in them
- [1951467] PDF Output: Fix the option to break long words at the ends of lines causing boxes to be rendered at the end fo the line on macOS with some fonts
- [1951467] PDF Output: Fix the option to break long words at the ends of lines causing boxes to be rendered at the end of the line on macOS with some fonts
- Google metadata plugin: When searching by ISBN if no results are found retry using an alternate query syntax
- 5.33.2 fixes a couple of regressions that broke the toolbar in the popup comments editor dialog and rendering of the download
metadata button in the edit metadata dialog on Windows, as well as reading files from MTP devices on Windows
:: improved recipes
- Smithsonian Magazine

View file

@ -17,7 +17,7 @@ First create some empty top level directory and run the following commands::
git clone https://github.com/kovidgoyal/bypy.git
git clone https://github.com/kovidgoyal/calibre.git
cd calibre
cd bypy && git switch qt5 && cd ../calibre
Now we need to bootstrap calibre, for which all its Linux build dependencies
must have already been installed (see the `Dependencies

View file

@ -253,7 +253,7 @@ def get_dependencies(self, path_to_lib):
@flush
def get_local_dependencies(self, path_to_lib):
for x, is_id in self.get_dependencies(path_to_lib):
if x.startswith('@rpath/Qt'):
if x.startswith('@rpath/Qt') or x.startswith('@rpath/libexpat'):
yield x, x[len('@rpath/'):], is_id
elif x in ('libunrar.dylib', 'libstemmer.0.dylib', 'libstemmer.dylib') and not is_id:
yield x, x, is_id

View file

@ -626,8 +626,8 @@
{
"name": "feedparser",
"unix": {
"filename": "feedparser-5.2.1.tar.bz2",
"hash": "sha256:ce875495c90ebd74b179855449040003a1beb40cd13d5f037a0654251e260b02",
"filename": "feedparser-6.0.8.tar.bz2",
"hash": "sha256:5ce0410a05ab248c8c7cfca3a0ea2203968ee9ff4486067379af4827a59f9661",
"urls": ["pypi"]
}
},

View file

@ -171,14 +171,17 @@ def sort_languages(x):
return sort_key(type(u'')(name))
website = 'https://calibre-ebook.com'
html_context['other_languages'].sort(key=sort_languages)
html_context['support_text'] = _('Support calibre')
html_context['support_tooltip'] = _('Contribute to support calibre development')
html_context['homepage_url'] = 'https://calibre-ebook.com'
html_context['homepage_url'] = website
if needs_localization:
html_context['homepage_url'] = localize_website_link(html_context['homepage_url'])
extlinks = {
'website_base': (website, None),
'website': (html_context['homepage_url'] + '/%s', None),
'download_file': (f'{website}/downloads/%s', '%s'),
}
del sort_languages, get_language
@ -236,11 +239,13 @@ def sort_languages(x):
# If false, no module index is generated.
# latex_use_modindex = True
# we use lualatex as it is actively maintained and pdflatex and xelatex fail
# to render smart quotes and dashes
latex_engine = 'lualatex'
latex_logo = 'resources/logo.png'
latex_show_pagerefs = True
latex_show_urls = 'footnote'
latex_elements = {
'papersize':'letterpaper',
'fontenc':r'\usepackage[T2A,T1]{fontenc}',
'preamble': r'\renewcommand{\pageautorefname}{%s}' % _('page'),
}

View file

@ -652,7 +652,7 @@ calibre can automatically convert ``.docx`` files created by Microsoft Word 2007
newer. Just add the file to calibre and click convert.
.. note::
There is a `demo .docx file <https://calibre-ebook.com/downloads/demos/demo.docx>`_
There is a :download_file:`demo .docx file <demos/demo.docx>`
that demonstrates the capabilities of the calibre conversion engine. Just
download it and convert it to EPUB or AZW3 to see what calibre can do.
@ -671,9 +671,8 @@ produce clean HTML that will convert well. Note that Word produces really messy
HTML, converting it can take a long time, so be patient. If you have a newer
version of Word available, you can directly save it as .docx as well.
Another alternative is to use the free OpenOffice. Open your .doc file in
OpenOffice and save it in OpenOffice's format .odt. calibre can directly convert
.odt files.
Another alternative is to use the free LibreOffice. Open your .doc file in
LibreOffice and save it as .docx, which can be directly converted in calibre.
Convert TXT documents
~~~~~~~~~~~~~~~~~~~~~~
@ -791,10 +790,10 @@ calibre will automatically convert this .cbc file into a e-book with a Table of
EPUB advanced formatting demo
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Various advanced formatting for EPUB files is demonstrated in this `demo file <https://calibre-ebook.com/downloads/demos/demo.epub>`_.
Various advanced formatting for EPUB files is demonstrated in this :download_file:`demo file <demos/demo.epub>`.
The file was created from hand coded HTML using calibre and is meant to be used as a template for your own EPUB creation efforts.
The source HTML it was created from is available `demo.zip <https://calibre-ebook.com/downloads/demos/demo.zip>`_. The settings used to create the
The source HTML it was created from is available :download_file:`demo.zip <demos/demo.zip>`. The settings used to create the
EPUB from the ZIP file are::
ebook-convert demo.zip .epub -vv --authors "Kovid Goyal" --language en --level1-toc '//*[@class="title"]' --disable-font-rescaling --page-breaks-before / --no-default-epub-cover

View file

@ -40,7 +40,7 @@ the folder in which you created :file:`__init__.py`::
are in :file:`/Applications/calibre.app/Contents/MacOS/`.
You can download the Hello World plugin from
`helloworld_plugin.zip <https://calibre-ebook.com/downloads/helloworld_plugin.zip>`_.
:download_file:`helloworld_plugin.zip`.
Every time you use calibre to convert a book, the plugin's :meth:`run` method will be called and the
converted book will have its publisher set to "Hello World". This is a trivial plugin, lets move on to
@ -54,7 +54,7 @@ This plugin will be spread over a few files (to keep the code clean). It will sh
how to create elements in the calibre user interface and how to access
and query the books database in calibre.
You can download this plugin from `interface_demo_plugin.zip <https://calibre-ebook.com/downloads/interface_demo_plugin.zip>`_
You can download this plugin from :download_file:`interface_demo_plugin.zip`
.. _import_name_txt:
@ -185,7 +185,7 @@ Edit book plugins
Now let's change gears for a bit and look at creating a plugin to add tools to
the calibre book editor. The plugin is available here:
`editor_demo_plugin.zip <https://calibre-ebook.com/downloads/editor_demo_plugin.zip>`_.
:download_file:`editor_demo_plugin.zip`.
The first step, as for all plugins is to create the
import name empty txt file, as described :ref:`above <import_name_txt>`.
@ -259,7 +259,7 @@ data in a separate process. A simple example plugin follows that shows how
to do this.
You can download the plugin from
`webengine_demo_plugin.zip <https://calibre-ebook.com/downloads/webengine_demo_plugin.zip>`_.
:download_file:`webengine_demo_plugin.zip`.
The important part of the plugin is in two functions:

View file

@ -75,7 +75,7 @@ Getting the code
------------------
You can get the calibre source code in two ways, using a version control system or
directly downloading a `tarball <https://calibre-ebook.com/dist/src>`_.
directly downloading a :website_base:`tarball <dist/src>`.
calibre uses `Git <https://www.git-scm.com/>`_, a distributed version control
system. Git is available on all the platforms calibre supports. After
@ -89,7 +89,7 @@ calibre is a very large project with a very long source control history, so the
above can take a while (10 mins to an hour depending on your internet speed).
If you want to get the code faster, the source code for the latest release is
always available as an `archive <https://calibre-ebook.com/dist/src>`_.
always available as an :website_base:`archive <dist/src>`.
To update a branch to the latest code, use the command::
@ -210,9 +210,9 @@ Create a plain text file::
export CALIBRE_DEVELOP_FROM="/Users/kovid/work/calibre/src"
calibre-debug -g
Save this file as ``/usr/bin/calibre-develop``, then set its permissions so that it can be executed::
Save this file as :file:`/usr/local/bin/calibre-develop`, then set its permissions so that it can be executed::
chmod +x /usr/bin/calibre-develop
chmod +x /usr/local/bin/calibre-develop
Once you have done this, run::
@ -309,7 +309,7 @@ You can insert the following two lines of code to start an interactive Python se
ipython(locals())
When running from the command line, this will start an interactive Python interpreter with access to all
locally defined variables (variables in the local scope). The interactive prompt even has TAB completion
locally defined variables (variables in the local scope). The interactive prompt even has :kbd:`Tab` completion
for object properties and you can use the various Python facilities for introspection, such as
:func:`dir`, :func:`type`, :func:`repr`, etc.

View file

@ -69,7 +69,7 @@ calibre is open source software while DRM by its very nature is closed. If
calibre were to support opening or viewing DRM files it could be trivially
modified to be used as a tool for DRM removal which is illegal under today's
laws. Open source software and DRM are a clash of principles. While DRM is all
about controlling the user open source software is about empowering the user.
about controlling the user, open source software is about empowering the user.
The two simply can not coexist.

View file

@ -26,8 +26,7 @@ Basic workflow
---------------
.. note::
A video tour of the calibre E-book editor is available `here
<https://calibre-ebook.com/demo#tutorials>`_.
A video tour of the calibre E-book editor is available :website:`here <demo#tutorials>`.
When you first open a book with the Edit book tool, you will be presented with
a list of files on the left. These are the individual HTML files, stylesheets,
@ -678,6 +677,14 @@ common in your book and to run a simple search and replace on individual words.
check tool. If you do not do this and continue to use the Spell check tool,
you could lose the changes you have made in the editor.
.. note::
To exclude an individual file from being spell checked when running the
spell check tool, you can use the :guilabel:`Exclude files` button or
add the following comment just under the opening tag in the file::
<!-- calibre-no-spell-check -->
Adding new dictionaries
###########################

View file

@ -158,8 +158,7 @@ How do I use some of the advanced features of the conversion tools?
You can get help on any individual feature of the converters by mousing over
it in the GUI or running ``ebook-convert dummy.html .epub -h`` at a terminal.
A good place to start is to look at the following demo file that demonstrates
some of the advanced features
`html-demo.zip <https://calibre-ebook.com/downloads/html-demo.zip>`_
some of the advanced features :download_file:`html-demo.zip <html-demo.zip>`.
Device integration
@ -196,7 +195,7 @@ We just need some information from you:
Once you send us the output for a particular operating system, support for the device in that operating system
will appear in the next release of calibre. To send us the output, open a bug report and attach the output to it.
See `how to report bugs <https://calibre-ebook.com/bugs>`_.
See :website:`how to report bugs <bugs>`.
My device is not being detected by calibre?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -216,8 +215,8 @@ Follow these steps to find the problem:
fix that by looking under :guilabel:`System Preferences > Security and
Privacy > Privacy > Files and Folders`.
* Make sure you are running the latest version of calibre (currently
|version|). The latest version can always be downloaded from `the calibre
website <https://calibre-ebook.com/download>`_. You can tell what
|version|). The latest version can always be downloaded from :website:`the calibre
website <download>`. You can tell what
version of calibre you are currently running by looking at the bottom
line of the main calibre window.
* Ensure your operating system is seeing the device. That is, the device
@ -415,7 +414,7 @@ antivirus program.
.. note::
If you are concerned about giving calibre access to your email
account, simply create a new free email account with GMX or Hotmail
account, simply create a new free email account with GMX or Outlook
and use it only for calibre.
@ -603,7 +602,7 @@ Why doesn't calibre have a column for foo?
calibre is designed to have columns for the most frequently and widely used
fields. In addition, you can add any columns you like. Columns can be added via
:guilabel:`Preferences->Interface->Add your own columns`. Watch the tutorial
`UI Power tips <https://calibre-ebook.com/demo#tutorials>`_ to learn how to
:website:`UI Power tips <demo#tutorials>` to learn how to
create your own columns, or read `this blog post
<https://blog.calibre-ebook.com/calibre-custom-columns/>`_.
@ -921,13 +920,13 @@ Downloading from the Internet can sometimes result in a corrupted download. If t
the :guilabel:`Security` tab. Make sure that your user account has full control
for this folder.
If you still cannot get the installer to work and you are on Windows, you can use the `calibre portable install <https://calibre-ebook.com/download_portable>`_, which does not need an installer (it is just a zip file).
If you still cannot get the installer to work and you are on Windows, you can use the :website:`calibre portable install <download_portable>`, which does not need an installer (it is just a ZIP file).
My antivirus program claims calibre is a virus/trojan?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The first thing to check is that you are downloading calibre from the official
website: `<https://calibre-ebook.com/download>`_. Make sure you are clicking the
website: :website:`<download>`. Make sure you are clicking the
download links on the left, not the advertisements on the right. calibre is a
very popular program and unscrupulous people try to setup websites offering it
for download to fool the unwary.
@ -995,8 +994,8 @@ proxies used by calibre in Preferences->Miscellaneous.
I want some feature added to calibre. What can I do?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You have two choices:
1. Create a patch by hacking on calibre and send it to me for review and inclusion. See `Development <https://calibre-ebook.com/get-involved>`_.
2. `Open a bug requesting the feature <https://calibre-ebook.com/bugs>`_. Remember that while you may think your feature request is extremely important/essential, calibre developers might not agree. Fortunately, calibre is open source, which means you always have the option of implementing your feature yourself, or hiring someone to do it for you. Furthermore, calibre has a comprehensive plugin architecture, so you might be able to develop your feature as a plugin, see :ref:`pluginstutorial`.
1. Create a patch by hacking on calibre and send it to me for review and inclusion. See :website:`Development <get-involved>`.
2. :website:`Open a bug requesting the feature <bugs>`. Remember that while you may think your feature request is extremely important/essential, calibre developers might not agree. Fortunately, calibre is open source, which means you always have the option of implementing your feature yourself, or hiring someone to do it for you. Furthermore, calibre has a comprehensive plugin architecture, so you might be able to develop your feature as a plugin, see :ref:`pluginstutorial`.
Why doesn't calibre have an automatic update?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -1008,8 +1007,8 @@ For many reasons:
to see if you want to update once a year or so. There is a check box to
turn off the update notification, on the update notification itself.
* calibre downloads currently use `about 150TB of bandwidth a month
<https://calibre-ebook.com/dynamic/downloads>`_. Implementing automatic
* calibre downloads currently use :website_base:`about 150TB of bandwidth a month
<dynamic/downloads>`. Implementing automatic
updates would greatly increase that and end up costing thousands of dollars
a month, which someone has to pay.
@ -1032,7 +1031,7 @@ calibre is licensed under the GNU General Public License v3 (an open source lice
How do I run calibre from my USB stick?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A portable version of calibre is available `here <https://calibre-ebook.com/download_portable>`_.
A portable version of calibre is available :website:`here <download_portable>`.
How do I run parts of calibre like news download and the Content server on my own Linux server?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View file

@ -26,4 +26,4 @@ Glossary
**URL** *(Uniform Resource Locator)* for example: ``http://example.com``
regexp
**Regular expressions** provide a concise and flexible means for identifying strings of text of interest, such as particular characters, words, or patterns of characters. See `regexp syntax <https://docs.python.org/library/re.html>`_ for the syntax of regular expressions used in Python.
**Regular expressions** provide a concise and flexible means for identifying strings of text of interest, such as particular characters, words, or patterns of characters. See :doc:`the tutorial <regexp>` for an introduction to regular expressions.

View file

@ -495,7 +495,7 @@ be configured to read metadata from the file name instead, via
:guilabel:`Preferences->Import/export->Adding books->Read metadata from file contents`.
You can also control how metadata is read from the filename using regular
expressions (see :doc:`regexp`). In the :guilabel:`Adding books` section of
expressions (see :doc:`regexp`). In the :guilabel:`Adding books` section of
the configuration dialog, you can specify a regular expression that calibre
will use to try and guess metadata from the names of e-book files that you add
to the library. The default regular expression is::
@ -566,7 +566,7 @@ The first click on an item will restrict the list of books to those that contain
Items in the Tag browser have their icons partially colored. The amount of color depends on the average rating of the books in that category. So for example if the books by Isaac Asimov have an average of four stars, the icon for Isaac Asimov in the Tag browser will be 4/5th colored. You can hover your mouse over the icon to see the average rating.
The outer-level items in the :guilabel:`Tag browser`, such as Authors and Series, are called categories. You can create your own categories, called :guilabel:`User categories`, which are useful for organizing items. For example, you can use the :guilabel:`User categories editor` (click the :guilabel:`Configure` button at the lower-left of the :guilabel:`Tag browser` and choose :guilabel:`Manage authors, series, etc->User categories`) to create a User category called ``Favorite Authors``, then put the items for your favorites into the category. User categories can have sub-categories. For example, the User category ``Favorites.Authors`` is a sub-category of ``Favorites``. You might also have ``Favorites.Series``, in which case there will be two sub-categories under ``Favorites``. Sub-categories can be created by right-clicking on a User category, choosing :guilabel:`Add sub-category to...`, and entering the sub-category name; or by using the :guilabel:`User categories editor` by entering names like the Favorites example above.
The outer-level items in the :guilabel:`Tag browser`, such as Authors and Series, are called categories. You can create your own categories, called :guilabel:`User categories`, which are useful for organizing items. For example, you can use the :guilabel:`User categories editor` (click the :guilabel:`Configure` button at the lower-left of the :guilabel:`Tag browser` and choose :guilabel:`Manage authors, tags, etc->User categories`) to create a User category called ``Favorite Authors``, then put the items for your favorites into the category. User categories can have sub-categories. For example, the User category ``Favorites.Authors`` is a sub-category of ``Favorites``. You might also have ``Favorites.Series``, in which case there will be two sub-categories under ``Favorites``. Sub-categories can be created by right-clicking on a User category, choosing :guilabel:`Add sub-category to...`, and entering the sub-category name; or by using the :guilabel:`User categories editor` by entering names like the Favorites example above.
You can search User categories in the same way as built-in categories, by clicking on them. There are four different searches cycled through by clicking:
1. "everything matching an item in the category" indicated by a single green plus sign.

View file

@ -52,7 +52,7 @@ The normal edit metadata dialog also has :guilabel:`Next` and :guilabel:`Previou
Search and replace
^^^^^^^^^^^^^^^^^^^^
The :guilabel:`Bulk metadata edit` dialog allows you to perform arbitrarily powerful search and replace operations on the selected books. By default it uses a simple text search and replace, but it also support *regular expressions*. For more on regular expressions, see :ref:`regexptutorial`.
The :guilabel:`Edit metadata for many books` dialog allows you to perform arbitrarily powerful search and replace operations on the selected books. By default it uses a simple text search and replace, but it also support *regular expressions*. For more on regular expressions, see :ref:`regexptutorial`.
As noted above, there are two search and replace modes: character match and regular expression. Character match will look in the `Search field` you choose for the characters you type in the `search for` box and replace those characters with what you type in the `replace with` box. Each occurrence of the search characters in the field will be replaced. For example, assume the field being searched contains `a bad cat`. If you search for `a` to be replaced with `HELLO`, then the result will be `HELLO bHELLOd cHELLOt`.

View file

@ -105,7 +105,7 @@ This is Python, so indentation is important. After you've added the lines, it sh
In the above, ``def print_version(self, url)`` defines a *method* that is called by calibre for every article. ``url`` is the URL of the original article. What ``print_version`` does is take that url and replace it with the new URL that points to the print version of the article. To learn about `Python <https://www.python.org>`_ see the `tutorial <https://docs.python.org/tutorial/>`_.
Now, click the :guilabel:`Add/update recipe` button and your changes will be saved. Re-download the e-book. You should have a much improved e-book. One of the problems with the new version is that the fonts on the print version webpage are too small. This is automatically fixed when converting to an e-book, but even after the fixing process, the font size of the menus and navigation bar to become too large relative to the article text. To fix this, we will do some more customization, in the next section.
Now, click the :guilabel:`Add/update recipe` button and your changes will be saved. Re-download the e-book. You should have a much improved e-book. One of the problems with the new version is that the fonts on the print version webpage are too small. This is automatically fixed when converting to an e-book, but even after the fixing process, the font size of the menus and navigation bar become too large relative to the article text. To fix this, we will do some more customization, in the next section.
Replacing article styles
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View file

@ -11,7 +11,7 @@ You've just started calibre. What do you do now? Before calibre can do anything
Once you've admired the list of books you just added to your heart's content, you'll probably want to read one. In order to do that you'll have to convert the book to a format your reader understands. When first running calibre, the :guilabel:`Welcome wizard` starts and will set up calibre for your reader device. Conversion is a breeze. Just select the book you want to convert then click the "Convert books" button. Ignore all the options for now and click "OK". The little icon in the bottom right corner will start spinning. Once it's finished spinning, your converted book is ready. Click the "View" button to read the book.
If you want to read the book on your reader, connect it to the computer, wait till calibre detects it (10-20 seconds) and then click the "Send to device" button. Once the icon stops spinning again, disconnect your reader and read away! If you didn't convert the book in the previous step, calibre will auto convert it to the format your reader device understands.
If you want to read the book on your reader, connect the reader to the computer, wait till calibre detects it (10-20 seconds) and then click the "Send to device" button. Once the icon stops spinning again, disconnect your reader and read away! If you didn't convert the book in the previous step, calibre will auto convert it to the format your reader device understands.
To get started with more advanced usage, you should read about :doc:`gui`. For even more power and versatility, learn the :doc:`generated/en/cli-index`. You will find the list of :doc:`faq` useful as well.

View file

@ -161,7 +161,7 @@ The functions intended for use in Single Function Mode are:
* ``rating_to_stars(use_half_stars)`` -- Returns the rating as string of star (````) characters. The value must be a number between 0 and 5. Set use_half_stars to 1 if you want half star characters for fractional numbers available with custom ratings columns.
* ``re(pattern, replacement)`` -- return the value after applying the regular expression. All instances of ``pattern`` in the value are replaced with ``replacement``. The template language uses case insensitive `Python regular expressions <https://docs.python.org/3/library/re.html>`_.
* ``select(key)`` -- interpret the value as a comma-separated list of items with each item having the form ``id:value`` (the calibre ``identifier`` format). The function finds the first pair with the id equal to key and returns the corresponding value. If no id matches then the function returns the empty string.
* ``shorten(left chars, middle text, right chars)`` -- Return a shortened version of the value, consisting of ``left chars`` characters from the beginning of the value, followed by ``middle text``, followed by ``right chars`` characters from the end of the value. ``Left chars`` and ``right chars`` must be non-negative integers. Example: assume you want to display the title with a length of at most 15 characters in length. One template that does this is ``{title:shorten(9,-,5)}``. For a book with the title `Ancient English Laws in the Times of Ivanhoe` the result will be `Ancient E-nhoe`: the first 9 characters of the title, a ``-``, then the last 5 characters. If the value's length is less than ``left chars`` + ``right chars`` + the length of ``middle text`` then the value will be returned unchanged. For example, the title `The Dome` would not be changed.
* ``shorten(left chars, middle text, right chars)`` -- Return a shortened version of the value, consisting of ``left chars`` characters from the beginning of the value, followed by ``middle text``, followed by ``right chars`` characters from the end of the value. ``Left chars`` and ``right chars`` must be non-negative integers. Example: assume you want to display the title with a length of at most 15 characters in length. One template that does this is ``{title:shorten(9,-,5)}``. For a book with the title `Ancient English Laws in the Times of Ivanhoe` the result will be `Ancient E-anhoe`: the first 9 characters of the title, a ``-``, then the last 5 characters. If the value's length is less than ``left chars`` + ``right chars`` + the length of ``middle text`` then the value will be returned unchanged. For example, the title `The Dome` would not be changed.
* ``str_in_list(separator, [ string, found_val, ]+ not_found_val)`` -- interpret the value as a list of items separated by ``separator`` then compare ``string`` against each value in the list. The ``string`` is not a regular expression. If ``string`` is equal to any item (ignoring case) then return the corresponding ``found_val``. If ``string`` contains ``separators`` then it is also treated as a list and each subvalue is checked. The ``string`` and ``found_value`` pairs can be repeated as many times as desired, permitting returning different values depending on string's value. If none of the strings match then ``not_found_value`` is returned. The strings are checked in order. The first match is returned.
* ``subitems(start_index, end_index)`` -- This function breaks apart lists of tag-like hierarchical items such as genres. It interprets the value as a comma-separated list of tag-like items, where each item is a period-separated list. It returns a new list made by extracting from each item the components from ``start_index`` to ``end_index``, then merging the results back together. Duplicates are removed. The first subitem in a period-separated list has an index of zero. If an index is negative then it counts from the end of the list. As a special case, an end_index of zero is assumed to be the length of the list.
@ -678,7 +678,7 @@ The same thing happens for authors, but using a different character for the cut,
Plugboards affect the metadata written into the book when it is saved to disk or written to the device. Plugboards do not affect the metadata used by ``save to disk`` and ``send to device`` to create the file names. Instead, file names are constructed using the templates entered on the appropriate preferences window.
Tips:
Tips
-----
* Use the Template Tester to test templates. Add the tester to the context menu for books in the library and/or give it a keyboard shortcut.

View file

@ -41,7 +41,7 @@ You can access the viewer controls by either:
The viewer has two modes, "paged" and "flow". In paged mode the book content
is presented as pages, similar to a paper book. In flow mode the text is
presented continuously, like in a web browser. You can switch between them
using the viewer Preferences under :guilabel:`Page layout` or by pressing the
using the viewer :guilabel:`Preferences` under :guilabel:`Page layout` or by pressing the
:kbd:`Ctrl+M` key.
@ -62,7 +62,7 @@ Table of Contents
^^^^^^^^^^^^^^^^^^^^
If the book you are reading defines a Table of Contents, you can access it by
pressing the :guilabel:`Table of Contents` button. This will bring up a list
pressing the :guilabel:`Table of Contents` button. This will bring up a list
of sections in the book. You can click on any of them to jump to that portion
of the book.

View file

@ -1,45 +1,24 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
from __future__ import with_statement, unicode_literals
from __future__ import unicode_literals
from calibre.web.feeds.news import BasicNewsRecipe
class AdvancedUserRecipe1592177429(BasicNewsRecipe):
title = 'Аргументы и Факты'
encoding = 'utf8'
language = 'ru'
class AdvancedUserRecipe1645564525(BasicNewsRecipe):
title = 'Аргументы и Факты - aif.ru'
__author__ = 'MrBeef12'
oldest_article = 7
max_articles_per_feed = 25
verbose = 3
max_articles_per_feed = 100
auto_cleanup = True
language = 'ru'
feeds = [
('AIF', 'https://www.aif.ru/rss/all.php'),
feeds = [
('ПОЛИТИКА', 'https://aif.ru/rss/politics.php'),
('ДЕНЬГИ', 'https://aif.ru/rss/money.php'),
('ОБЩЕСТВО', 'https://aif.ru/rss/society.php'),
('ЗДОРОВЬЕ', 'https://aif.ru/rss/health.php'),
('КУЛЬТУРА', 'https://aif.ru/rss/culture.php'),
('СПОРТ', 'https://aif.ru/rss/sport.php'),
('АВТОМОБИЛИ', 'https://aif.ru/rss/automobile.php'),
('НЕДВИЖИМОСТЬ', 'https://aif.ru/rss/realty.php'),
]
INDEX = 'https://www.aif.ru/rss/all.php'
def parse_index(self):
feeds = []
section_title = 'aif'
articles = []
soup = self.index_to_soup(self.INDEX)
ii = 0
for item in soup.findAll('item'):
if ii < self.max_articles_per_feed:
try:
ii = ii + 1
A = str(item)
i = A.find(u'link')
j = A.find(u'description')
ZZ = item.find('description')
ZZ1 = str(ZZ) # bs4.element.Tag to str
ZZ2 = ZZ1[24:-19]
AU = A[i:j]
try:
articles.append({'url':AU[6:-2], 'title':ZZ2})
except Exception:
pass
except Exception:
self.log("Exception handled!")
if articles:
feeds.append((section_title, articles))
return feeds

View file

@ -4,11 +4,7 @@
'''
english.aljazeera.net
'''
from calibre.web.feeds.news import BasicNewsRecipe
def has_cls(x):
return dict(attrs={'class': lambda cls: cls and x in cls.split()})
from calibre.web.feeds.news import BasicNewsRecipe, classes
class AlJazeera(BasicNewsRecipe):
@ -31,7 +27,7 @@ class AlJazeera(BasicNewsRecipe):
'publisher': publisher, 'language': language
}
keep_only_tags = [
dict(id='article-page'),
classes('article-header article-featured-image wysiwyg--all-content'),
]
remove_tags = [

View file

@ -1,20 +1,39 @@
from calibre.web.feeds.news import BasicNewsRecipe
#!/usr/bin/env python
# License: GPLv3 Copyright: 2008, Kovid Goyal <kovid at kovidgoyal.net>
from __future__ import unicode_literals
from calibre.web.feeds.news import BasicNewsRecipe, classes
class AmericanProspect(BasicNewsRecipe):
title = u'American Prospect'
__author__ = u'Michael Heinz, a.peter'
version = 2
oldest_article = 30
title = 'American Prospect'
__author__ = 'Kovid Goyal'
oldest_article = 300
language = 'en'
max_articles_per_feed = 100
recursions = 0
no_stylesheets = True
remove_javascript = True
encoding = 'utf-8'
use_embedded_content = False
no_stylesheets = True
auto_cleanup = True
feeds = [(u'Articles', u'feed://www.prospect.org/articles_rss.jsp')]
keep_only_tags = [
dict(id=['title', 'content']),
]
remove_tags = [
classes('slideout-close-btn media-options')
]
def get_feeds(self):
soup = self.index_to_soup('https://prospect.org/archive')
for a in soup.findAll('a', href=True):
href = a['href']
if href.endswith('-issue/'):
d = href.strip('/').split('/')[-1]
self.timefmt = ' [{}]'.format(d.rpartition('-')[0])
self.log('Found magazine URL', href)
return [('Articles', href + 'index.rss')]
return [('Articles', 'https://prospect.org/api/rss/all.rss')]

View file

@ -111,6 +111,23 @@ def parse_article_json(root, abort_article):
elif bt == 'text':
lines.extend(serialize_text(block))
return '<html><body id="main-content">' + '\n'.join(lines) + '</body></html>'
def parse_raw_html(html, abort_article):
q = '>window.__INITIAL_DATA__="{'
idx = html.find(q)
if idx < 0:
raise ValueError('Failed to find JSON')
data = html[idx + len(q) - 2:]
idx = data.find('}";</script>')
data = data[:idx+2]
data = json.loads(data)
root = json.loads(data)
return parse_article_json(root, abort_article)
if __name__ == '__main__':
print(parse_raw_html(open('/t/raw.html').read(), print))
# }}}
@ -269,12 +286,4 @@ class BBCNews(BasicNewsRecipe):
resolve_internal_links = True
def preprocess_raw_html(self, raw_html, url):
q = '>window.__INITIAL_DATA__={'
idx = raw_html.find(q)
if idx < 0:
raise ValueError('Failed to find JSON')
data = raw_html[idx + len(q) - 1:]
idx = data.find('};</script>')
data = data[:idx+1]
root = json.loads(data)
return parse_article_json(root, self.abort_article)
return parse_raw_html(raw_html, self.abort_article)

View file

@ -12,18 +12,20 @@
def serialize_image(block):
yield '<div>'
block = block['model']
media = block['media']
alt = prepare_string_for_xml(media.get('alt') or '', True)
img = block['image']
alt = prepare_string_for_xml(img.get('alt') or '', True)
for q in ('originalSrc', 'src'):
if q in media:
src = prepare_string_for_xml(media[q])
if q in img:
src = prepare_string_for_xml(img[q])
break
else:
raise ValueError('No src found in media block: {}'.format(media))
raise ValueError('No src found in img block: {}'.format(img))
yield '<img src="{}" alt="{}"/>'.format(src, alt)
caption = block.get('caption')
if caption:
yield '<div>{}</div>'.format(prepare_string_for_xml(caption))
if caption and caption.get('type') == 'text':
yield '<div>'
yield from serialize_paragraph(caption)
yield '</div>'
yield '</div>'
@ -102,13 +104,30 @@ def parse_article_json(root, abort_article):
lines.append('<h1>{}</h1>'.format(prepare_string_for_xml(article['headline'])))
if article.get('contributor'):
lines.extend(serialize_contributor(article['contributor']))
for block in article['blocks']:
for block in article['content']['model']['blocks']:
bt = block.get('type')
if bt == 'image':
lines.extend(serialize_image(block))
elif bt == 'text':
lines.extend(serialize_text(block))
return '<html><body id="main-content">' + '\n'.join(lines) + '</body></html>'
def parse_raw_html(html, abort_article):
q = '>window.__INITIAL_DATA__="{'
idx = html.find(q)
if idx < 0:
raise ValueError('Failed to find JSON')
data = html[idx + len(q) - 2:]
idx = data.find('}";</script>')
data = data[:idx+2]
data = json.loads(data)
root = json.loads(data)
return parse_article_json(root, abort_article)
if __name__ == '__main__':
print(parse_raw_html(open('/t/raw.html').read(), print))
# }}}
@ -124,10 +143,13 @@ class BBC(BasicNewsRecipe):
publisher = 'BBC'
category = 'news, UK, world'
language = 'en_GB'
masthead_url = 'https://news.bbcimg.co.uk/img/1_0_1/cream/hi/news/news-blocks.gif'
conversion_options = {
'comments': description, 'tags': category, 'language': language, 'publisher': publisher,
}
# Removes empty feeds - why keep them!?
remove_empty_feeds = True
ignore_duplicate_articles = {'title', 'url'}
resolve_internal_links = True
feeds = [
('Top Stories', 'https://feeds.bbci.co.uk/news/rss.xml'),
@ -150,12 +172,4 @@ class BBC(BasicNewsRecipe):
]
def preprocess_raw_html(self, raw_html, url):
q = '>window.__INITIAL_DATA__={'
idx = raw_html.find(q)
if idx < 0:
raise ValueError('Failed to find JSON')
data = raw_html[idx + len(q) - 1:]
idx = data.find('};</script>')
data = data[:idx+1]
root = json.loads(data)
return parse_article_json(root, self.abort_article)
return parse_raw_html(raw_html, self.abort_article)

View file

@ -34,14 +34,11 @@ class Clarin(BasicNewsRecipe):
needs_subscription = 'optional'
INDEX = 'http://www.clarin.com'
LOGIN = 'https://app-pase.clarin.com/pase-registracion/app/pase/ingresarNavegable?execution=e1s1'
masthead_url = 'http://www.clarin.com/images/logo_clarin.svg'
cover_url = strftime('http://tapas.clarin.com/tapa/%Y/%m/%d/%Y%m%d_thumb.jpg')
compress_news_images = True
scale_news_images_to_device = True
compress_news_images_max_size = 10 # kB
scale_news_images = True
handle_gzip = True
# To get all the data (images)
auto_cleanup = False
@ -132,7 +129,7 @@ def get_browser(self):
return br
def preprocess_html(self, soup):
for img in soup.findAll(['img']):
for img in soup.findAll(['img'], attrs={'data-big': True}):
img['src'] = img['data-big']
for figCaption in soup.findAll(['figcaption']):

View file

@ -1,8 +1,4 @@
from __future__ import with_statement
__license__ = 'GPL 3'
__copyright__ = '2014, Amit <amitkp.ias@gmail.com>'
from calibre.web.feeds.news import BasicNewsRecipe
from calibre.web.feeds.news import BasicNewsRecipe, classes
class My_Feeds(BasicNewsRecipe):
@ -16,19 +12,15 @@ class My_Feeds(BasicNewsRecipe):
center_navbar = True
use_embedded_content = False
remove_empty_feeds = True
remove_tags_before = dict(name='div', id='PageContent')
remove_tags_after = [dict(name='div'), {'class': 'taxonomy-terms'}]
keep_only_tags = [
classes('detail-heading content-main news-basic-info news-banner news-detail-content')
]
remove_tags = [
classes('add-comment btn hindi_detail_link single-news-letter'),
dict(id=['comments', 'breadcrumb', 'node_related_stories']),
dict(attrs={'class': ['commentCount', 'box']})
]
feeds = [
(u'editor', u'http://www.downtoearth.org.in/taxonomy/term/20348/0/feed'),
(u'cover story', u'http://www.downtoearth.org.in/taxonomy/term/20345/0/feed'),
(u'special report', u'http://www.downtoearth.org.in/taxonomy/term/20384/0/feed'),
(u'features', u'http://www.downtoearth.org.in/taxonomy/term/20350/0/feed'),
(u'news', u'http://www.downtoearth.org.in/taxonomy/term/20366/0/feed'),
(u'debate', u'http://www.downtoearth.org.in/taxonomy/term/20347/0/feed'),
(u'natural disasters', u'http://www.downtoearth.org.in/taxonomy/term/20822/0/feed')
('All', 'https://www.downtoearth.org.in/rss/all'),
]

29
recipes/dw_de.recipe Normal file
View file

@ -0,0 +1,29 @@
#!/usr/bin/env python
from calibre.web.feeds.news import BasicNewsRecipe
class AdvancedUserRecipe1398527969(BasicNewsRecipe):
title = u'DW-Deutsch XXL'
language = 'de_DE'
__author__ = 'xav'
oldest_article = 7
max_articles_per_feed = 100
auto_cleanup = True
no_stylesheets = True
use_embedded_content = False
remove_javascript = True
feeds = [(u'Nachrichten', u'http://rss.dw.com/xml/rss-de-news'),
(u'Themen des Tages', u'http://rss.dw.com/xml/rss-de-top'),
(u'Langsam gesprochene Nachrichten',
u'https://rss.dw.com/rdf/DKfeed_lgn_de'),
(u'Wissenschaft', u'https://rss.dw.com/xml/rss-de-wissenschaft'),
(u'Wirtschaft', u'https://rss.dw.com/xml/rss-de-eco'),
(u'Wort der Woche',
u'https://rss.dw.com/xml/DKpodcast_wortderwoche_de'),
(u'Deutschland entdecken',
u'http://rss.dw.com/xml/rss-de-deutschlandentdecken')]
def print_version(self, url):
target = url.rpartition('/')[2]
print_url = 'https://www.dw-world.de/popups/popup_printcontent/' + target
return print_url

View file

@ -42,10 +42,13 @@ class ElPais(BasicNewsRecipe):
'articulo-apertura',
'articulo__contenedor'
]}),
dict(name='div', attrs={'class': 'a_c',}),
]
remove_tags = [
dict(attrs={'class': [
dict(
attrs={'class': [
'sumario__interior',
'articulo-trust',
'compartir',
@ -54,7 +57,11 @@ class ElPais(BasicNewsRecipe):
'more_info',
'articulo-apoyos',
'top10',
]}),
]
},
),
dict(id='cta_id'),
dict(name='svg'),
]
feeds = [

View file

@ -0,0 +1,81 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
from calibre.web.feeds.news import BasicNewsRecipe
from calibre.utils.date import parse_date, utcnow
class AdvancedUserRecipe1639926896(BasicNewsRecipe):
__author__ = "Aisteru"
__copyright__ = "2021, Timothée Andres <timothee dot andres at gmail dot com>"
__license__ = 'GNU General Public License v3 - http://www.gnu.org/copyleft/gpl.html'
title = "Equestria Daily"
description = "Everything new in Equestria and beyond!"
language = 'en_US'
# Max. supported by website: 50
max_articles_per_feed = 30
compress_news_images = True
compress_news_images_auto_size = 4
no_stylesheets = True
keep_only_tags = [{'name': 'div', 'class_': ['post', 'hentry']}]
remove_tags = [{'name': 'div', 'class_': 'post-footer'}]
extra_css = '.article_date { margin-left: 10px; }'
# Masthead image dimensions
MI_WIDTH = 600
MI_HEIGHT = 200
# To discard posts under a certain section, simply comment the whole line
sections = [
("Art", 'Art'),
("News", 'News'),
("Fics", 'Fanfiction'),
("Media", 'Media'),
("Comics", 'Comic'),
("Community", 'Community'),
("Editorial", 'Editorial'),
]
def get_masthead_url(self):
soup = self.index_to_soup('https://www.equestriadaily.com')
img = soup.select_one('#header img')
return img['src']
def parse_index(self):
results = {}
current_date = utcnow()
def clean_description(description):
lines = description.split('\n')
return '\n'.join([line.strip() for line in lines if len(line.strip()) > 0])
for (section_name, section_url_name) in self.sections:
soup = self.index_to_soup(
f'https://www.equestriadaily.com/search/label/{section_url_name}?max-results={self.max_articles_per_feed}')
articles = soup.select('div.post.hentry')
previous_post_date = current_date
for article in articles:
article_entry = {}
header = article.select_one('h3 > a')
article_entry['title'] = header.text
article_entry['url'] = header['href']
article_entry['date'] = article.select_one('span.post-timestamp').text.split('\n')[1]
article_entry['description'] = clean_description(article.select_one('div.entry-content').text)
article_entry['content'] = '' # Must be empty
post_date = previous_post_date
try:
post_date = parse_date(article_entry['date'])
previous_post_date = post_date
except Exception:
pass
if (current_date - post_date).days <= self.oldest_article:
results.setdefault(section_name, []).append(article_entry)
return [(section, results[section]) for section in results]

View file

@ -19,35 +19,48 @@ class FE_India(BasicNewsRecipe):
description = 'Financial news from India'
publisher = 'The Indian Express Limited'
category = 'news, politics, finances, India'
oldest_article = 30
oldest_article = 2
max_articles_per_feed = 200
no_stylesheets = True
encoding = 'utf-8'
use_embedded_content = False
language = 'en_IN'
remove_empty_feeds = True
ignore_duplicate_articles = {'url'}
publication_type = 'magazine'
conversion_options = {
'comment': description, 'tags': category, 'publisher': publisher, 'language': language
}
keep_only_tags = [classes('post-title place-line leftstory')]
keep_only_tags = [classes('wp-block-post-title wp-block-post-excerpt ie-network-post-meta-wrapper wp-block-post-featured-image wp-block-post-content')]
remove_attributes = ['width', 'height']
feeds = [
('Latest news', 'https://www.financialexpress.com/feed/'),
# https://www.financialexpress.com/syndication/
# Print feeds
('Front Page','https://www.financialexpress.com/print/front-page/feed/'),
('Corporate Markets','https://www.financialexpress.com/print/corporate-markets/feed/'),
('Economy','https://www.financialexpress.com/print/economy-print/feed/'),
('Opinion','https://www.financialexpress.com/print/edits-columns/feed/'),
('personal Finance','https://www.financialexpress.com/print/personal-finance-print/feed/'),
# ('Brandwagon', 'https://www.financialexpress.com/print/brandwagon/feed/'),
# Other Feeds
('Economy', 'https://www.financialexpress.com/economy/feed/'),
('Industry', 'https://www.financialexpress.com/industry/feed/'),
('Banking & finance', 'https://www.financialexpress.com/industry/banking-finance/feed/'),
('Companies', 'https://www.financialexpress.com/industry/companies/feed/'),
('Jobs', 'https://www.financialexpress.com/industry/jobs/feed/'),
('Tech', 'https://www.financialexpress.com/industry/tech/feed/'),
('Lifestyle', 'https://www.financialexpress.com/industry/lifestyle/feed/'),
('Health', 'https://www.financialexpress.com/industry/health/feed/'),
('Science', 'https://www.financialexpress.com/industry/science/feed/'),
('Sports', 'https://www.financialexpress.com/industry/sports/feed/'),
('Fe Columnist', 'https://www.financialexpress.com/industry/fe-columnist/feed/'),
('Opinion', 'https://www.financialexpress.com/opinion/feed/'),
('Editorial', 'https://www.financialexpress.com/editorial/feed/'),
('Budget', 'https://www.financialexpress.com/budget/feed/'),
('Industry', 'https://www.financialexpress.com/industry/feed/'),
('Market', 'https://www.financialexpress.com/market/feed/'),
('Jobs', 'https://www.financialexpress.com/jobs/feed/'),
('SME', 'https://www.financialexpress.com/industry/sme/feed/'),
('Mutual Funds', 'https://www.financialexpress.com/money/mutual-funds/feed/'),
('Health','https://www.financialexpress.com/lifestyle/health/feed'),
# ('Health Care','https://www.financialexpress.com/healthcare/feed'),
('Science','https://www.financialexpress.com/lifestyle/science/feed'),
('Infrastructure','https://www.financialexpress.com/infrastructure/feed'),
('Money','https://www.financialexpress.com/money/feed'),
]
def preprocess_html(self, soup, *a):

View file

@ -136,7 +136,7 @@ class ForeignAffairsRecipe(BasicNewsRecipe):
classes('article-header article-body article-lead-image article-body-text'),
]
remove_tags = [
classes('loading-indicator paywall article-footer')
classes('loading-indicator paywall article-footer article-tools')
]
conversion_options = {'comments': description, 'tags': category, 'language': 'en',
@ -149,10 +149,12 @@ def parse_index(self):
soup.head.title.string))[0]
self.title = "Foreign Affairs ({})".format(date)
self.timefmt = u' [%s]' % date
link = soup.find('link', rel='revision', href=True)['href']
link = soup.find('link', rel='canonical', href=True)['href']
year, volnum, issue_vol = link.split('/')[-3:]
self.cover_url = (soup.find('img', {'class': 'subscribe-callout-image'})['data-src']
.split("|", 1)[0].replace('issue_small_1x', 'issue_large_2x'))
self.cover_url = soup.find(**classes('subscribe-callout-image'))['data-src'].split("|")[-1]
self.cover_url = self.cover_url.split('?')[0]
self.cover_url = self.cover_url.replace('.webp', '')
self.cover_url = self.cover_url.replace('_webp_issue_small_2x', 'issue_large_2x')
cls = soup.find('body')['class']
if isinstance(cls, (list, tuple)):

View file

@ -1,4 +1,4 @@
from calibre.web.feeds.news import BasicNewsRecipe
from calibre.web.feeds.news import BasicNewsRecipe, classes
class GKT(BasicNewsRecipe):
@ -12,33 +12,36 @@ class GKT(BasicNewsRecipe):
no_javascript = True
auto_cleanup = True
def parse_gkt_section(self, url, ignore_error=False):
try:
root = self.index_to_soup(url, as_tree=True)
except Exception:
if ignore_error:
return
raise
for a in root.xpath('//div[@class="posts-listing"]/h1/a[@href]'):
title = self.tag_to_string(a).strip()
url = a.get('href')
if title and url:
self.log('\tFound article:', title, 'at', url)
yield {'title': title, 'url': url}
def parse_index(self):
url = 'http://www.gktoday.in/'
root = self.index_to_soup(url, as_tree=True)
ans = []
h3 = root.xpath('//h3[@class="widget-title"]')[1]
for a in h3.getparent().xpath('descendant::li/a[@href]'):
category = self.tag_to_string(a).strip()
if 'PDF' in category or not category:
continue
url = a.get('href')
self.log('Found section:', category, 'at', url)
articles = list(self.parse_gkt_section(url)) + \
list(self.parse_gkt_section(url + '/page/2', ignore_error=True))
if articles:
ans.append((category, articles))
return ans
securl = 'https://www.gktoday.in/current-affairs/'
ans = {}
def p_tags(h1):
for sib in h1.next_siblings:
if sib.name == 'h1':
break
if sib.name == 'p':
yield sib
def find_cat(ps):
for p in ps:
for a in p.findAll('a', rel='tag'):
return self.tag_to_string(a)
for i in range(1, 6):
page = '' if i == 1 else 'page/' + str(i)
self.log('Trying:', securl + page)
soup = self.index_to_soup(securl + page)
container = soup.find(**classes('left_middle_content'))
for h1 in container.findAll('h1'):
title = self.tag_to_string(h1)
a = h1.find('a')
if a is None:
continue
url = a['href']
ps = tuple(p_tags(h1))
category = find_cat(ps) or 'Unknown'
ans.setdefault(category, []).append({
'title': title, 'url': url, 'description': self.tag_to_string(ps[0])})
self.log('\t' + title + ' ' + url)
return list(ans.items())

View file

@ -23,7 +23,7 @@ class TheHindu(BasicNewsRecipe):
__author__ = 'Kovid Goyal'
max_articles_per_feed = 100
no_stylesheets = True
remove_attributes = ['style']
remove_attributes = ['style', 'height', 'width']
extra_css = '.lead-img-cont { text-align: center; } ' \
'.lead-img-caption { font-size: small; font-style: italic; } ' \
'.mobile-author-cont { font-size: small; text-transform: uppercase; } ' \
@ -37,8 +37,9 @@ class TheHindu(BasicNewsRecipe):
]
def get_browser(self):
br = BasicNewsRecipe.get_browser(self)
br = BasicNewsRecipe.get_browser(self, user_agent='common_words/based')
br.addheaders += [('Referer', self.epaper_url)] # needed for fetching cover
# br.set_debug_http(True)
return br
def get_cover_url(self):
@ -54,6 +55,8 @@ def preprocess_html(self, soup):
source.extract()
except Exception:
pass
for img in soup.findAll(attrs={'data-original': True}):
img['src'] = img['data-original']
# Place intro beneath the title, skip duplicates
try:
soup.h1.insert_after(soup.find('h2', attrs={'class': 'intro'}))
@ -76,7 +79,7 @@ def populate_article_metadata(self, article, soup, first):
def articles_from_soup(self, soup):
ans = []
div = soup.find('section', attrs={'id': 'section_'})
div = soup.find('section', attrs={'id': 'section_1'})
if div is None:
return ans
for ul in div.findAll('ul', attrs={'class': 'archive-list'}):
@ -99,7 +102,7 @@ def parse_index(self):
# {'title':'xxx', 'url':'http://www.thehindu.com/opinion/op-ed/rohingya-bangladeshs-burden-to-bear/article19694058.ece'},
# {'title':'yyy', 'url':'http://www.thehindu.com/sci-tech/energy-and-environment/on-river-washed-antique-plains/article19699327.ece'}
# ])]
soup = self.index_to_soup('http://www.thehindu.com/todays-paper/')
soup = self.index_to_soup('https://www.thehindu.com/todays-paper/')
nav_div = soup.find(id='subnav-tpbar-latest')
section_list = []

View file

@ -0,0 +1,58 @@
#!/usr/bin/env python
from calibre.web.feeds.news import BasicNewsRecipe, classes
class HindustanTimes(BasicNewsRecipe):
title = u'Hindustan Times'
description = 'News from India.'
language = 'en_IN'
__author__ = 'unkn0wn'
oldest_article = 1 # days
max_articles_per_feed = 50
encoding = 'utf-8'
use_embedded_content = False
no_stylesheets = True
remove_attributes = ['style', 'height', 'width']
ignore_duplicate_articles = {'url'}
extra_css = 'button { display: none; } '
keep_only_tags = [
dict(name='h1'),
dict(name='div', attrs={'class':'sortDec'}),
dict(name='picture'),
dict(name='figcaption'),
classes('dateTime storyBy storyDetails detail freemiumText paywall'),
]
remove_tags = [
classes('htsWrapper shareArticle new__newsletter__signup signup__box subscribe freemium-card adMinHeight313'
' storyTopics embed_div shareIcons close-btn'),
dict(name='div', attrs={'class':[]}),
dict(name='footer'),
]
feeds = [
('Editorial','https://www.hindustantimes.com/feeds/rss/editorials/rssfeed.xml'),
('Opinion','https://www.hindustantimes.com/feeds/rss/opinion/rssfeed.xml'),
('HT Insight','https://www.hindustantimes.com/feeds/rss/ht-insight/rssfeed.xml'),
('Analysis','https://www.hindustantimes.com/feeds/rss/analysis/rssfeed.xml'),
('India News','https://www.hindustantimes.com/feeds/rss/india-news/rssfeed.xml'),
('World News','https://www.hindustantimes.com/feeds/rss/world-news/rssfeed.xml'),
('Business','https://www.hindustantimes.com/feeds/rss/business/rssfeed.xml'),
('Science','https://www.hindustantimes.com/feeds/rss/science/rssfeed.xml'),
('Education','https://www.hindustantimes.com/feeds/rss/education/rssfeed.xml'),
('Elections','https://www.hindustantimes.com/feeds/rss/elections/rssfeed.xml'),
('Sports','https://www.hindustantimes.com/feeds/rss/sports/rssfeed.xml'),
('Books','https://www.hindustantimes.com/feeds/rss/books/rssfeed.xml'),
('HT Weekend','https://www.hindustantimes.com/feeds/rss/ht-weekend/rssfeed.xml'),
# ('Entertainment','https://www.hindustantimes.com/feeds/rss/entertainment/rssfeed.xml'),
# ('Lifestyle',''https://www.hindustantimes.com/feeds/rss/lifestyle/rssfeed.xml'),
# ('Cities',''https://www.hindustantimes.com/feeds/rss/cities/rssfeed.xml'),
# ('Budget',''https://www.hindustantimes.com/feeds/rss/budget/rssfeed.xml')
]
def preprocess_html(self, soup):
for img in soup.findAll('img', attrs={'data-src': True}):
img['src'] = img['data-src']
return soup

View file

@ -0,0 +1,40 @@
#!/usr/bin/env python
from calibre.web.feeds.news import BasicNewsRecipe, classes
class IndiaLegalLive(BasicNewsRecipe):
title = 'India Legal Magazine'
language = 'en_IN'
__author__ = 'unkn0wn'
oldest_article = 7 # days
max_articles_per_feed = 50
encoding = 'utf-8'
use_embedded_content = False
no_stylesheets = True
remove_attributes = ['style', 'height', 'width']
masthead_url = 'https://d2r2ijn7njrktv.cloudfront.net/IL/uploads/2020/12/03181846/india-legal-live-logo-218x73-1.png'
def get_cover_url(self):
soup = self.index_to_soup('https://www.indialegallive.com/')
for citem in soup.findAll('img', src=lambda s: s and s.endswith('shot.jpg')):
return citem['src']
keep_only_tags = [
dict(name='h1'),
classes(
'tdb_single_subtitle tdb_single_date tdb_single_featured_image tdb_single_content'
),
]
remove_tags = [
dict(name='div', attrs={'style':'position:absolute;top:0;left:-9999px;'}),
]
feeds = [
('Courts', 'https://www.indialegallive.com/constitutional-law-news/courts-news/rss'),
('Ring Side', 'https://www.indialegallive.com/ringside/rss'),
('Cover Story Articles', 'https://www.indialegallive.com/cover-story-articles/rss'),
('Special', 'https://www.indialegallive.com/special/rss'),
('Columns', 'https://www.indialegallive.com/column-news/rss'),
]

View file

@ -1,4 +1,4 @@
from calibre.web.feeds.news import BasicNewsRecipe
from calibre.web.feeds.news import BasicNewsRecipe, classes
class IndiaToday(BasicNewsRecipe):
@ -7,14 +7,41 @@ class IndiaToday(BasicNewsRecipe):
__author__ = 'Krittika Goyal'
oldest_article = 15 # days
max_articles_per_feed = 25
no_stylesheets = True
auto_cleanup = True
use_embedded_content = False
remove_attributes = ['style']
keep_only_tags = [
dict(name='h1'),
classes('story-kicker story-right'),
dict(itemProp='articleBody'),
]
feeds = [
('The Big Story', 'https://www.indiatoday.in/rss/1206614'),
('Editor\'s Note','https://www.indiatoday.in/rss/1206516'),
('Cover Story', 'https://www.indiatoday.in/rss/1206509'),
('The Big Story', 'https://www.indiatoday.in/rss/1206614'),
('UP Front','https://www.indiatoday.in/rss/1206609'),
('Liesure','https://www.indiatoday.in/rss/1206551'),
('Nation', 'https://www.indiatoday.in/rss/1206514'),
('Health','https://www.indiatoday.in/rss/1206515'),
('Defence','https://www.indiatoday.in/rss/1206517'),
('Guest Column','https://www.indiatoday.in/rss/1206612'),
('States', 'https://www.indiatoday.in/rss/1206500'),
('Economy', 'https://www.indiatoday.in/rss/1206513'),
('Special Report','https://www.indiatoday.in/rss/1206616'),
('Investigation','https://www.indiatoday.in/rss/1206617'),
('Diplomacy','https://www.indiatoday.in/rss/1206512'),
('Sports','https://www.indiatoday.in/rss/1206518'),
]
def preprocess_raw_html(self, raw_html, url):
from calibre.ebooks.BeautifulSoup import BeautifulSoup
soup = BeautifulSoup(raw_html)
for script in soup.findAll('script'):
script.extract()
for style in soup.findAll('style'):
style.extract()
for img in soup.findAll('img', attrs={'data-src': True}):
img['src'] = img['data-src']
return str(soup)

View file

@ -17,38 +17,31 @@ class IndianExpress(BasicNewsRecipe):
no_stylesheets = True
use_embedded_content = False
remove_attributes = ['style','height','width']
ignore_duplicate_articles = {'url'}
keep_only_tags = [
classes('heading-part full-details')
]
remove_tags = [
classes('share-social appstext story-tags')
dict(name='div', attrs={'id':'ie_story_comments'}),
dict(name='img', attrs={'src':'https://images.indianexpress.com/2021/06/explained-button-300-ie.jpeg'}),
dict(name='a', attrs={'href':'https://indianexpress.com/section/explained/?utm_source=newbanner'}),
dict(name='img', attrs={'src':'https://images.indianexpress.com/2021/06/opinion-button-300-ie.jpeg'}),
dict(name='a', attrs={'href':'https://indianexpress.com/section/opinion/?utm_source=newbanner'}),
classes('share-social appstext story-tags ie-int-campign-ad ie-breadcrumb custom_read_button unitimg copyright')
]
feeds = [
('Front Page',
'http://indianexpress.com/print/front-page/feed/'),
('Editorials',
'http://indianexpress.com/section/opinion/editorials/feed/'),
('Crime',
'http://indianexpress.com/section/india/crime/feed/'),
('Cricket',
'http://indianexpress.com/section/sports/cricket/feed/'),
('Health',
'http://www.indianexpress.com/lifestyle/health/feed/'),
('Asia',
'http://indianexpress.com/section/world/asia/'),
('Politics',
'http://indianexpress.com/section/india/politics/feed/'),
('Mumbai',
'http://www.indianexpress.com/cities/mumbai/feed/'),
('Op-Ed',
'http://indianexpress.com/section/opinion/feed/'),
('Lifestyle',
'http://indianexpress.com/section/lifestyle/feed/'),
('Science & Technology',
'http://indianexpress.com/section/technology/feed/'),
('Bollywood',
'http://indianexpress.com/section/entertainment/bollywood/feed/'),
('Front Page', 'https://indianexpress.com/print/front-page/feed/'),
('Op-Ed', 'http://indianexpress.com/section/opinion/feed/'),
('Science & Technology', 'http://indianexpress.com/section/technology/feed/'),
('Movie Reviews', 'https://indianexpress.com/section/entertainment/movie-review/feed/'),
('Sunday Eye', 'https://indianexpress.com/print/eye/feed/'),
('Explained', 'https://indianexpress.com/section/explained/feed/'),
('Delhi Confidential', 'https://indianexpress.com/section/delhi-confidential/feed'),
('Economy', 'https://indianexpress.com/print/economy/feed'),
('Express Network', 'https://indianexpress.com/print/express-network/'),
# Want to add more? go-to:https://indianexpress.com/syndication/
]
def preprocess_html(self, soup):

View file

@ -51,26 +51,37 @@ def get_browser(self):
# To understand the signin logic read signin javascript from submit button from
# https://www.irishtimes.com/signin
br = BasicNewsRecipe.get_browser(self, user_agent='curl/7.80.0')
ip_data = json.loads(br.open('https://ipapi.co//json').read())
br = BasicNewsRecipe.get_browser(self)
url = 'https://www.irishtimes.com/signin'
deviceid = str(uuid4()).replace('-', '')
# Enable debug stuff?
# br.set_debug_http(True)
br.open(url).read()
from pprint import pprint
pprint(ip_data)
br.set_cookie('IT_country', ip_data['country_code'], '.irishtimes.com')
br.set_cookie('IT_eu', 'true' if ip_data['in_eu'] else 'false', '.irishtimes.com')
rurl = 'https://www.irishtimes.com/auth-rest-api/v1/paywall/login'
rq = Request(rurl, headers={
'Accept': '*/*',
'Accept-Language': 'en-US,en;q=0.5',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'Origin': 'https://www.irishtimes.com',
'Referer': url,
'X-Requested-With': 'XMLHttpRequest',
}, data=urlencode({'username': self.username, 'password': self.password,'deviceid':deviceid, 'persistent':'on'}))
'sec-fetch-site': 'same-origin',
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
}, data=urlencode({'username': self.username, 'password': self.password, 'deviceid':deviceid, 'persistent':'on', 'rid': ''}))
r = br.open(rq)
raw = r.read()
data = json.loads(raw)
# print(data)
if r.code != 200 or b'user_id' not in raw:
pprint(data)
raise ValueError('Failed to log in check username/password')
# Set cookie

View file

@ -1,58 +1,69 @@
__license__ = 'GPL v3'
__copyright__ = '2008-2013, Darko Miletic <darko.miletic at gmail.com>'
'''
#!/usr/bin/env python
# -*- coding: utf-8 -*-
__license__ = "GPL v3"
__copyright__ = (
"2008-2013, Darko Miletic <darko.miletic at gmail.com>. "
"2022, Albert Aparicio Isarn <aaparicio at posteo.net>"
)
"""
japantimes.co.jp
'''
"""
from calibre.web.feeds.news import BasicNewsRecipe
def classes(classes):
q = frozenset(classes.split(' '))
return dict(attrs={
'class': lambda x: x and frozenset(x.split()).intersection(q)})
class JapanTimes(BasicNewsRecipe):
title = 'The Japan Times'
__author__ = 'Darko Miletic'
description = "Daily news and features on Japan from the most widely read English-language newspaper in Japan. Coverage includes national news, business news, sports news, commentary and features on living in Japan, entertainment, the arts, education and more." # noqa
language = 'en_JP'
category = 'news, politics, japan'
publisher = 'The Japan Times'
title = "The Japan Times"
__author__ = "Albert Aparicio Isarn (original recipe by Darko Miletic)"
description = (
"The latest news from Japan Times, Japan's leading English-language daily newspaper"
)
language = "en_JP"
category = "news, politics, japan"
publisher = "The Japan Times"
oldest_article = 2
max_articles_per_feed = 150
no_stylesheets = True
remove_javascript = True
use_embedded_content = False
encoding = 'utf8'
publication_type = 'newspaper'
extra_css = 'body{font-family: Geneva,Arial,Helvetica,sans-serif}'
encoding = "utf8"
publication_type = "newspaper"
masthead_url = "https://cdn-japantimes.com/wp-content/themes/jt_theme/library/img/japantimes-logo-tagline.png"
extra_css = "body{font-family: Geneva,Arial,Helvetica,sans-serif}"
conversion_options = {
'comment': description, 'tags': category, 'publisher': publisher, 'language': language
"comment": description,
"tags": category,
"publisher": publisher,
"language": language,
}
remove_tags_after = dict(name='div', attrs={'class': 'entry'}),
keep_only_tags = [dict(name='div', attrs={'class': 'padding_block'})]
remove_tags_before = {"name": "h1"}
remove_tags_after = {"name": "ul", "attrs": {"class": "single-sns-area"}}
keep_only_tags = [
{"name": "div", "attrs": {"class": "padding_block"}},
# {"name": "h5", "attrs": {"class": "writer", "role": "author"}},
# {"name": "p", "attrs": {"class": "credit"}},
]
remove_tags = [
dict(name=['iframe', 'embed', 'object', 'base', 'form']), dict(attrs={'class': [
'meta_extras', 'related_articles']}), dict(attrs={'id': 'content_footer_menu'}),
dict(id='no_js_blocker'),
classes('single-sns-area jt-related-stories'),
{"name": "div", "id": "no_js_blocker", "attrs": {"class": "padding_block"}},
{"name": "div", "attrs": {"class": "single-upper-meta"}},
{"name": "ul", "attrs": {"class": "single-sns-area"}},
]
feeds = [
(u'News', u'http://www.japantimes.co.jp/news/feed/'),
(u'Opinion', u'http://www.japantimes.co.jp/opinion/feed/'),
(u'Life', u'http://www.japantimes.co.jp/opinion/feed/'),
(u'Community', u'http://www.japantimes.co.jp/community/feed/'),
(u'Culture', u'http://www.japantimes.co.jp/culture/feed/'),
(u'Sports', u'http://www.japantimes.co.jp/sports/feed/')
(u"Top Stories", u"https://www.japantimes.co.jp/feed/topstories/"),
(u"News", u"https://www.japantimes.co.jp/news/feed/"),
(u"Opinion", u"https://www.japantimes.co.jp/opinion/feed/"),
(u"Life", u"https://www.japantimes.co.jp/life/feed/"),
(u"Community", u"https://www.japantimes.co.jp/community/feed/"),
(u"Culture", u"https://www.japantimes.co.jp/culture/feed/"),
(u"Sports", u"https://www.japantimes.co.jp/sports/feed/"),
]
def get_article_url(self, article):
rurl = BasicNewsRecipe.get_article_url(self, article)
return rurl.partition('?')[0]
return rurl.partition("?")[0]
def preprocess_raw_html(self, raw, url):
return '<html><head>' + raw[raw.find('</head>'):]
return "<html><head>" + raw[raw.find("</head>") :]

View file

@ -17,10 +17,10 @@ class JournalofHospitalMedicine(BasicNewsRecipe):
def get_browser(self):
br = BasicNewsRecipe.get_browser(self)
br.open('http://www3.interscience.wiley.com/cgi-bin/home')
br.open('https://onlinelibrary.wiley.com/')
br.select_form(nr=0)
br['j_username'] = self.username
br['j_password'] = self.password
br['login'] = self.username
br['password'] = self.password
response = br.submit()
raw = response.read()
if '<h2>LOGGED IN</h2>' not in raw:
@ -29,7 +29,7 @@ def get_browser(self):
# TO GET ARTICLE TOC
def johm_get_index(self):
return self.index_to_soup('http://onlinelibrary.wiley.com/journal/10.1002/(ISSN)1553-5606/currentissue')
return self.index_to_soup('https://shmpublications.onlinelibrary.wiley.com/toc/15535606/current')
# To parse artice toc
def parse_index(self):

View file

@ -1,181 +1,17 @@
#!/usr/bin/env python
'''
Lenta.ru
'''
from calibre.web.feeds.feedparser import parse
from calibre.ebooks.BeautifulSoup import Tag
# vim:fileencoding=utf-8
from __future__ import unicode_literals
from calibre.web.feeds.news import BasicNewsRecipe
import re
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)
class LentaRURecipe(BasicNewsRecipe):
title = u'Lenta.ru: \u041d\u043e\u0432\u043e\u0441\u0442\u0438'
__author__ = 'Nikolai Kotchetkov'
publisher = 'lenta.ru'
category = 'news, Russia'
description = u'''\u0415\u0436\u0435\u0434\u043d\u0435\u0432\u043d\u0430\u044f
\u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u0433\u0430\u0437\u0435\u0442\u0430.
\u041d\u043e\u0432\u043e\u0441\u0442\u0438 \u0441\u043e
\u0432\u0441\u0435\u0433\u043e \u043c\u0438\u0440\u0430 \u043d\u0430
\u0440\u0443\u0441\u0441\u043a\u043e\u043c
\u044f\u0437\u044b\u043a\u0435'''
description = u'Ежедневная интернет-газета. Новости со всего мира на русском языке'
oldest_article = 3
class AdvancedUserRecipe1645563203(BasicNewsRecipe):
title = 'Lenta.ru - Новости'
__author__ = 'MrBeef12'
oldest_article = 7
max_articles_per_feed = 100
masthead_url = u'http://img.lenta.ru/i/logowrambler.gif'
cover_url = u'http://img.lenta.ru/i/logowrambler.gif'
# Add feed names if you want them to be sorted (feeds of this list appear
# first)
sortOrder = [u'_default', u'В России', u'б.СССР', u'В мире']
encoding = 'cp1251'
auto_cleanup = True
language = 'ru'
no_stylesheets = True
remove_javascript = True
recursions = 0
conversion_options = {
'comment': description, 'tags': category, 'publisher': publisher, 'language': language
}
keep_only_tags = [dict(name='td', attrs={'class': ['statya', 'content']})]
remove_tags_after = [dict(name='p', attrs={'class': 'links'}), dict(
name='div', attrs={'id': 'readers-block'})]
remove_tags = [dict(name='table', attrs={'class': ['vrezka', 'content']}), dict(name='div', attrs={
'class': 'b240'}), dict(name='div', attrs={'id': 'readers-block'}), dict(name='p', attrs={'class': 'links'})]
feeds = [u'http://lenta.ru/rss/']
extra_css = 'h1 {font-size: 1.2em; margin: 0em 0em 0em 0em;} h2 {font-size: 1.0em; margin: 0em 0em 0em 0em;} h3 {font-size: 0.8em; margin: 0em 0em 0em 0em;}' # noqa
def parse_index(self):
try:
feedData = parse(self.feeds[0])
if not feedData:
raise NotImplementedError
self.log("parse_index: Feed loaded successfully.")
def get_virtual_feed_articles(feed):
if feed in feeds:
return feeds[feed][1]
self.log("Adding new feed: ", feed)
articles = []
feeds[feed] = (feed, articles)
return articles
feeds = {}
# Iterate feed items and distribute articles using tags
for item in feedData.entries:
link = item.get('link', '')
title = item.get('title', '')
if '' == link or '' == title:
continue
article = {'title': title, 'url': link, 'description': item.get(
'description', ''), 'date': item.get('date', ''), 'content': ''}
if not item.get('tags'):
get_virtual_feed_articles('_default').append(article)
continue
for tag in item.tags:
addedToDefault = False
term = tag.get('term', '')
if '' == term:
if (not addedToDefault):
get_virtual_feed_articles(
'_default').append(article)
continue
get_virtual_feed_articles(term).append(article)
# Get feed list
# Select sorted feeds first of all
result = []
for feedName in self.sortOrder:
if (not feeds.get(feedName)):
continue
result.append(feeds[feedName])
del feeds[feedName]
result = result + feeds.values()
return result
except Exception as err:
self.log(err)
raise NotImplementedError
def preprocess_html(self, soup):
return self.adeify_images(soup)
def postprocess_html(self, soup, first_fetch):
contents = new_tag(soup, 'div')
# Extract tags with given attributes
extractElements = {'div': [{'id': 'readers-block'}]}
# Remove all elements that were not extracted before
for tag, attrs in extractElements.items():
for attr in attrs:
garbage = soup.findAll(tag, attr)
if garbage:
for pieceOfGarbage in garbage:
pieceOfGarbage.extract()
# Find article text using header
# and add all elements to contents
element = soup.find({'h1': True, 'h2': True})
if (element):
element.name = 'h1'
while element:
nextElement = element.nextSibling
element.extract()
contents.insert(len(contents.contents), element)
element = nextElement
# Place article date after header
dates = soup.findAll(text=re.compile(
r'\d{2}\.\d{2}\.\d{4}, \d{2}:\d{2}:\d{2}'))
if dates:
for date in dates:
for string in date:
parent = date.parent
if (parent and isinstance(parent, Tag) and 'div' == parent.name and 'dt' == ''.join(parent['class'])):
# Date div found
parent.extract()
parent[
'style'] = 'font-size: 0.5em; color: gray; font-family: monospace;'
contents.insert(1, parent)
break
# Place article picture after date
pic = soup.find('img')
if pic:
picDiv = new_tag(soup, 'div')
picDiv['style'] = 'width: 100%; text-align: center;'
pic.extract()
picDiv.insert(0, pic)
title = pic.get('title', None)
if title:
titleDiv = new_tag(soup, 'div')
titleDiv['style'] = 'font-size: 0.5em;'
titleDiv.insert(0, title)
picDiv.insert(1, titleDiv)
contents.insert(2, picDiv)
body = soup.find('td', {'class': ['statya', 'content']})
if body:
body.replaceWith(contents)
return soup
feeds = [
('Lenta.ru - Новости России и мира сегодня', 'https://lenta.ru/rss/'),
]

View file

@ -1,36 +1,81 @@
from calibre.web.feeds.news import BasicNewsRecipe
#!/usr/bin/env python
from calibre.web.feeds.news import BasicNewsRecipe, classes
from datetime import date
is_saturday = date.today().weekday() == 5
class LiveMint(BasicNewsRecipe):
title = u'Live Mint'
description = 'Financial News from India.'
language = 'en_IN'
__author__ = 'Krittika Goyal'
oldest_article = 1 # days
max_articles_per_feed = 50
encoding = 'utf-8'
use_embedded_content = False
no_stylesheets = True
auto_cleanup = True
remove_attributes = ['style', 'height', 'width']
feeds = [
('News',
'http://www.livemint.com/rss/news'),
('Technology',
'http://www.livemint.com/rss/technology'),
('Companies',
'http://www.livemint.com/rss/companies'),
('Consumer',
'http://www.livemint.com/rss/consumer'),
('Opinion',
'http://www.livemint.com/rss/opinion'),
('Money',
'http://www.livemint.com/rss/money'),
('Industry',
'http://www.livemint.com/rss/industry'),
('Economy Politics',
'http://www.livemint.com/rss/economy_politics'),
('Lounge',
'http://www.livemint.com/rss/lounge'),
('Sports',
'http://www.livemint.com/rss/sports'),
]
if is_saturday:
keep_only_tags = [
dict(name='h1'),
dict(name='h2', attrs={'id':'story-summary-0'}),
dict(name='picture'),
dict(name='div', attrs={'class':'innerBanCaption'}),
dict(name='div', attrs={'id':'date-display-before-content'}),
dict(name='div', attrs={'class':'storyContent'}),
]
remove_tags = [
classes(
'sidebarAdv similarStoriesClass moreFromSecClass'
)
]
feeds = [
('News', 'https://lifestyle.livemint.com/rss/news'),
('Food','https://lifestyle.livemint.com/rss/food'),
('Fashion','https://lifestyle.livemint.com/rss/fashion'),
('How to Lounge','https://lifestyle.livemint.com/rss/how-to-lounge'),
('Smart Living','https://lifestyle.livemint.com/rss/smart-living'),
]
else:
keep_only_tags = [
dict(name='h1'),
dict(name='picture'),
dict(name='figcaption'),
classes('articleInfo FirstEle summary highlights paywall'),
]
remove_tags = [
classes(
'trendingSimilarHeight moreNews mobAppDownload label msgError msgOk'
)
]
feeds = [
('Companies', 'https://www.livemint.com/rss/companies'),
('Opinion', 'https://www.livemint.com/rss/opinion'),
('Money', 'https://www.livemint.com/rss/money'),
('Economy', 'https://www.livemint.com/rss/economy/'),
('Politics', 'https://www.livemint.com/rss/politics'),
('Science', 'https://www.livemint.com/rss/science'),
('Industry', 'https://www.livemint.com/rss/industry'),
('Education', 'https://www.livemint.com/rss/education'),
('Sports', 'https://www.livemint.com/rss/sports'),
('Technology', 'https://www.livemint.com/rss/technology'),
('News', 'https://www.livemint.com/rss/news'),
('Mutual Funds', 'https://www.livemint.com/rss/Mutual Funds'),
('Markets', 'https://www.livemint.com/rss/markets'),
('AI', 'https://www.livemint.com/rss/AI'),
('Insurance', 'https://www.livemint.com/rss/insurance'),
('Budget', 'https://www.livemint.com/rss/budget'),
('Elections', 'https://www.livemint.com/rss/elections'),
]
def preprocess_html(self, soup):
for img in soup.findAll('img', attrs={'data-src': True}):
img['src'] = img['data-src']
if is_saturday:
for img in soup.findAll('img', attrs={'data-img': True}):
img['src'] = img['data-img']
return soup

View file

@ -1,64 +1,142 @@
__license__ = 'GPL v3'
__copyright__ = '2010, Hiroshi Miura <miurahr@linux.com>'
'''
www.mainichi.jp
'''
#!/usr/bin/env python
# -*- coding: utf-8 -*-
__license__ = "GPL v3"
__copyright__ = (
"2010, Hiroshi Miura <miurahr@linux.com>. "
"2021, Albert Aparicio Isarn <aaparicio at posteo.net>"
)
"""
www.mainichi.jp/english
"""
from datetime import datetime
import re
from calibre.web.feeds.news import BasicNewsRecipe
class MainichiEnglishNews(BasicNewsRecipe):
title = u'The Mainichi'
__author__ = 'Hiroshi Miura'
title = u"The Mainichi"
__author__ = "Albert Aparicio Isarn (old version by Hiroshi Miura)"
description = "Japanese traditional newspaper Mainichi news in English"
publisher = "Mainichi News"
publication_type = "newspaper"
category = "news, japan"
language = "en_JP"
index = "http://mainichi.jp/english/"
masthead_url = index + "images/themainichi.png"
oldest_article = 2
max_articles_per_feed = 40
description = 'Japanese traditional newspaper Mainichi news in English'
publisher = 'Mainichi News'
category = 'news, japan'
language = 'en_JP'
index = 'http://mainichi.jp/english/english/index.html'
no_stylesheets = True
remove_javascript = True
masthead_url = 'http://mainichi.jp/english/images/themainichi.png'
remove_tags_before = {'class': "NewsTitle"}
remove_tags_after = {'class': "NewsBody clr"}
remove_tags_before = {"id": "main-cont"}
remove_tags_after = {"class": "main-text"}
remove_tags = [{"name": "div", "id": "tools"}, {"name": "div", "class": "sub"}]
def parse_feeds(self):
def get_pickup_section(self, soup):
# Topmost story
top = soup.find("section", attrs={"class": "pickup section"})
top_link = top.find("p", attrs={"class": "midashi"}).find("a")
feeds = BasicNewsRecipe.parse_feeds(self)
try:
top_date = (
soup.find("div", attrs={"id": "main"})
.find("div", attrs={"class": "date-box"})
.find("p", attrs={"class": "date"})
.string
)
for curfeed in feeds:
delList = []
for a, curarticle in enumerate(curfeed.articles):
if re.search(r'pheedo.jp', curarticle.url):
delList.append(curarticle)
if re.search(r'rssad.jp', curarticle.url):
delList.append(curarticle)
if len(delList) > 0:
for d in delList:
index = curfeed.articles.index(d)
curfeed.articles[index:index + 1] = []
top_date_formatted = datetime.strptime(top_date, "%A, %B %d, %Y").strftime("%Y/%m/%d")
except AttributeError:
# If date not present, assume it is from today
top_date_formatted = datetime.now().strftime("%Y/%m/%d")
return feeds
top_description = top.find("p", attrs={"class": "txt"}).text
return [
{
"title": top_link.string,
"date": top_date_formatted,
"url": "https:" + top_link["href"],
"description": top_description,
}
]
def retrieve_news_from_column(self, column):
column_news = []
for item in column.findAll("li"):
if item:
itema = item.find("a")
date_item = itema.find("p", attrs={"class": "date"})
column_news.append(
{
"title": itema.find("span").string,
"date": date_item.string.strip("") if date_item else "",
"url": "https:" + itema["href"],
"description": "",
}
)
return column_news
def get_top_stories(self, soup):
top_stories = self.get_pickup_section(soup)
news_section = soup.find("section", attrs={"class": "newslist"})
top_news = news_section.find("div", attrs={"class": "main-box"}).find("ul")
top_stories.extend(self.retrieve_news_from_column(top_news))
return top_stories
def get_editor_picks(self, soup):
editor_picks = []
news_section = soup.find("section", attrs={"class": "newslist"})
news = news_section.find("div", attrs={"class": "sub-box"}).find("ul")
editor_picks.extend(self.retrieve_news_from_column(news))
return editor_picks
def get_section(self, section):
soup = self.index_to_soup(self.index + section + "index.html")
section_news_items = self.get_pickup_section(soup)
news_columns = (
soup.find("section", attrs={"class": "newslist section"})
.find("div", attrs={"class": "col-set"})
.find("ul")
)
section_news_items.extend(self.retrieve_news_from_column(news_columns))
return section_news_items
def parse_index(self):
feeds = []
soup = self.index_to_soup(self.index)
for section in soup.findAll('section'):
newsarticles = []
section_name = 'news'
hds = section.find('div', attrs={'class': 'CategoryHead clr'})
if hds:
section_item = hds.find('h1')
if section_item:
section_name = section_item.find('a').string
items = section.find('ul', attrs={'class': 'MaiLink'})
for item in items.findAll('li'):
if item:
itema = item.find('a')
newsarticles.append({
'title': itema.string, 'date': '', 'url': itema['href'], 'description': ''
})
feeds.append((section_name, newsarticles))
soup = self.index_to_soup(self.index + "index.html")
feeds = [
("Top Stories", self.get_top_stories(soup)),
("Editor's Picks", self.get_editor_picks(soup)),
# ("Latest Articles", self.get_section(self.index + "latest"+"index.html")),
("Japan", self.get_section("japan")),
("World", self.get_section("world")),
("Business", self.get_section("business")),
("Sports", self.get_section("sports")),
("Science", self.get_section("science")),
("Entertainment", self.get_section("entertainment")),
("Opinion", self.get_section("opinion")),
("Lifestyle", self.get_section("lifestyle")),
("Obituaries", self.get_section("obituaries")),
]
return feeds

View file

@ -45,9 +45,12 @@ class Mediapart(BasicNewsRecipe):
keep_only_tags = [
dict(name='h1'),
dict(name='div', **classes('author')),
classes('introduction content-article')
classes('news__heading__top__intro news__body__center__article')
]
remove_tags = [
classes('login-subscribe print-source_url'),
dict(name='svg'),
]
remove_tags = [classes('login-subscribe print-source_url')]
conversion_options = {'smarten_punctuation': True}
masthead_url = "https://raw.githubusercontent.com/lhoupert/calibre_contrib/main/mediapart_masthead.png"

View file

@ -7,8 +7,7 @@
'''
technologyreview.com
'''
from calibre.web.feeds.news import BasicNewsRecipe
import re
from calibre.web.feeds.news import BasicNewsRecipe, prefixed_classes
def absurl(x):
@ -38,26 +37,14 @@ class MitTechnologyReview(BasicNewsRecipe):
tags = 'news, technology, science'
no_stylesheets = True
"""
regex for class names
"""
articleHeaderRegex= '^.*contentHeader__wrapper.*$'
editorLetterHeaderRegex = "^.*contentHeader--vertical__wrapper.*$"
articleContentRegex = "^.*contentbody__wrapper.*$"
imagePlaceHolderRegex = "^.*image__placeholder.*$"
advertisementRegex = "^.*sliderAd__wrapper.*$"
keep_only_tags = [
dict(name='header', attrs={'class': re.compile(editorLetterHeaderRegex, re.IGNORECASE)}),
dict(name='header', attrs={'class': re.compile(articleHeaderRegex, re.IGNORECASE)}),
dict(name='div', attrs={'class': re.compile(articleContentRegex, re.IGNORECASE)})
prefixed_classes('contentHeader contentArticleHeader contentBody')
]
remove_tags = [
dict(name="aside"),
dict(name="svg"),
dict(name="blockquote"),
dict(name="img", attrs={'class': re.compile(imagePlaceHolderRegex, re.IGNORECASE)}),
dict(name="div", attrs={'class': re.compile(advertisementRegex, re.IGNORECASE)}),
prefixed_classes('image__placeholder sliderAd__wrapper'),
]
def parse_index(self):

View file

@ -1,58 +1,48 @@
__license__ = 'GPL v3'
__copyright__ = '2010, BlonG'
'''
www.rtvslo.si
'''
#!/usr/bin/env python
# News source: https://www.rtvslo.si
# License: GPLv3
# Copyright: 2022, TadejS
from calibre.web.feeds.news import BasicNewsRecipe
class MMCRTV(BasicNewsRecipe):
title = u'MMC RTV Slovenija'
__author__ = u'BlonG'
__author__ = u'TadejS'
description = u"Prvi interaktivni multimedijski portal, MMC RTV Slovenija"
oldest_article = 3
max_articles_per_feed = 20
max_articles_per_feed = 100
language = 'sl'
no_stylesheets = True
use_embedded_content = False
encoding = 'utf-8'
publication_type = 'newspaper'
cover_url = 'https://sites.google.com/site/javno2010/home/rtv_slo_cover.jpg'
extra_css = '''
h1{font-family:Arial,Helvetica,sans-serif; font-weight:bold;font-size:large;}
h2{font-family:Arial,Helvetica,sans-serif; font-weight:normal;font-size:small;}
p{font-family:Arial,Helvetica,sans-serif;font-size:small;}
body{font-family:Helvetica,Arial,sans-serif;font-size:small;}
'''
def print_version(self, url):
split_url = url.split("/")
print_url = 'http://www.rtvslo.si/index.php?c_mod=news&op=print&id=' + \
split_url[-1]
return print_url
cover_url = 'https://img.rtvslo.si/_static/novi/logo/tvmmc-light-bg.png'
keep_only_tags = [
dict(name='div', attrs={'class': 'title'}),
dict(name='div', attrs={'id': 'newsbody'}),
dict(name='div', attrs={'id': 'newsblocks'}),
dict(name='header', attrs={'class': 'article-header'}),
dict(name='div', attrs={'class': 'article-body'}),
]
remove_tags=[
dict(name='div', attrs={'class':'gallery-grid'}),
dict(name='div', attrs={'class':'gallery'}),
dict(name='div', attrs={'class':'exposed-article'}),
dict(name='div', attrs={'class':'d-lg-none'}),
dict(name='div', attrs={'class':'section-heading'}),
]
# remove_tags=[
# 40 dict(name='div', attrs={'id':'newsblocks'}),
# ]
feeds = [
(u'Slovenija', u'http://www.rtvslo.si/feeds/01.xml'),
(u'Svet', u'http://www.rtvslo.si/feeds/02.xml'),
(u'Evropska unija', u'http://www.rtvslo.si/feeds/16.xml'),
(u'Gospodarstvo', u'http://www.rtvslo.si/feeds/04.xml'),
(u'\u010crna kronika', u'http://www.rtvslo.si/feeds/08.xml'),
(u'Okolje', u'http://www.rtvslo.si/feeds/12.xml'),
(u'Znanost in tehnologija', u'http://www.rtvslo.si/feeds/09.xml'),
(u'Zabava', u'http://www.rtvslo.si/feeds/06.xml'),
(u'Ture avanture', u'http://www.rtvslo.si/feeds/28.xml'),
(u'Slovenija', u'https://www.rtvslo.si/feeds/01.xml'),
(u'Evropska unija', u'https://www.rtvslo.si/feeds/16.xml'),
(u'Svet', u'https://www.rtvslo.si/feeds/02.xml'),
(u'Gospodarstvo', u'https://www.rtvslo.si/feeds/04.xml'),
(u'Okolje', u'https://www.rtvslo.si/feeds/12.xml'),
(u'Znanost in tehnologija', u'https://www.rtvslo.si/feeds/09.xml'),
(u'Kultura', u'https://www.rtvslo.si/feeds/05.xml'),
(u'Šport', u'https://www.rtvslo.si/feeds/03.xml'),
(u'Zabava', u'https://www.rtvslo.si/feeds/06.xml'),
(u'Ture avanture', u'https://www.rtvslo.si/feeds/28.xml'),
(u'Črna kronika', u'https://www.rtvslo.si/feeds/08.xml'),
]
# def preprocess_html(self, soup):
# newsblocks = soup.find('div',attrs = ['id':'newsblocks'])
# soup.find('div', attrs = {'id':'newsbody'}).insert(-1, newsblocks)
# return soup

View file

@ -186,7 +186,8 @@ def parse_todays_page(self):
soup = self.read_nyt_metadata()
script = soup.findAll('script', text=lambda x: x and 'window.__preloadedData' in x)[0]
script = type(u'')(script)
data = json.loads(script[script.find('{'):script.rfind(';')].strip().rstrip(';'))['initialState']
json_data = script[script.find('{'):script.rfind(';')].strip().rstrip(';')
data = json.loads(json_data.replace(':undefined', ':null'))['initialState']
containers, sections = {}, {}
article_map = {}
gc_pat = re.compile(r'groupings.(\d+).containers.(\d+)')

View file

@ -186,7 +186,8 @@ def parse_todays_page(self):
soup = self.read_nyt_metadata()
script = soup.findAll('script', text=lambda x: x and 'window.__preloadedData' in x)[0]
script = type(u'')(script)
data = json.loads(script[script.find('{'):script.rfind(';')].strip().rstrip(';'))['initialState']
json_data = script[script.find('{'):script.rfind(';')].strip().rstrip(';')
data = json.loads(json_data.replace(':undefined', ':null'))['initialState']
containers, sections = {}, {}
article_map = {}
gc_pat = re.compile(r'groupings.(\d+).containers.(\d+)')

View file

@ -100,7 +100,7 @@ def process_image_block(lines, block, data):
def json_to_html(raw):
data = json.loads(raw)
data = json.loads(raw.replace(':undefined', ':null'))
data = data['initialState']
article = next(iter(data.values()))
body = data[article['sprinkledBody']['id']]

View file

@ -0,0 +1,48 @@
#!/usr/bin/env python
from calibre.web.feeds.news import BasicNewsRecipe, classes
class OpenMagazine(BasicNewsRecipe):
title = u'Open Magazine'
description = 'The weekly current affairs and features magazine.'
language = 'en_IN'
__author__ = 'unkn0wn'
oldest_article = 7 # days
max_articles_per_feed = 50
encoding = 'utf-8'
use_embedded_content = False
no_stylesheets = True
remove_attributes = ['style', 'height', 'width']
masthead_url = 'https://openthemagazine.com/wp-content/themes/open/images/logo.png'
ignore_duplicate_articles = {'url'}
extra_css = '[id^="caption-attachment"] {font-size: small;font-style: italic;}'
def get_cover_url(self):
soup = self.index_to_soup('https://openthemagazine.com/magazine/')
tag = soup.find(attrs={'class': 'mb-2 right-image'})
if tag:
self.cover_url = tag.find('img')['src']
return super().get_cover_url()
keep_only_tags = [
classes('post-data post-thumb post-meta post-excerp'),
]
remove_tags = [
classes('top-social menu-social post-author blurb-social button-links'),
]
remove_tags_after = [
classes('post-meta post-excerp'),
]
feeds = [
('Cover Story', 'https://openthemagazine.com/cover-story/feed/'),
('Columns', 'https://openthemagazine.com/columns/feed'),
('Essays', 'https://openthemagazine.com/essays/feed'),
('Features', 'https://openthemagazine.com/features/feed'),
('Books', 'https://openthemagazine.com/lounge/books/feed'),
('Art & Culture', 'https://openthemagazine.com/art-culture/feed'),
('Cinema', 'https://openthemagazine.com/cinema/feed'),
]

View file

@ -23,18 +23,18 @@ class AdvancedUserRecipe1282101454(BasicNewsRecipe):
ignore_duplicate_articles = {'url'}
no_stylesheets = True
keep_only_tags = [
classes('content-body article-header featured-img'),
classes('Article-header Article-excerpt Article-author Article-thumbnail Article-bodyText'),
]
def parse_section_index(self, slug):
soup = self.index_to_soup('https://www.popsci.com/{}/'.format(slug))
main = soup.find(**classes('main-module'))
for div in main.findAll(**classes('main-item')):
a = div.find('a', href=True, **classes('linkable'))
main = soup.find(**classes('main-content'))
for div in main.findAll(**classes('Post')):
a = div.find('a', href=True, **classes('Post-link'))
url = a['href']
title = self.tag_to_string(a.find(**classes('title')))
title = self.tag_to_string(div.find(**classes('Post-title')))
desc = ''
dek = a.find(**classes('dek'))
dek = div.find(**classes('Post-excerpt'))
if dek is not None:
desc = self.tag_to_string(dek)
self.log(' ', title, url)

View file

@ -9,6 +9,7 @@
'''
from calibre.web.feeds.news import BasicNewsRecipe
from polyglot.urllib import urlencode
def classes(classes):
@ -29,6 +30,7 @@ class PublicoPT(BasicNewsRecipe):
language = 'pt'
remove_empty_feeds = True
extra_css = ' body{font-family: Arial,Helvetica,sans-serif } img{margin-bottom: 0.4em} '
needs_subscription = True
keep_only_tags = [
dict(id='story-content story-header'.split()),
@ -53,6 +55,23 @@ class PublicoPT(BasicNewsRecipe):
(u'Tecnologia', u'http://feeds.feedburner.com/PublicoTecnologia')
]
def get_browser(self):
br = BasicNewsRecipe.get_browser(self)
if self.username is not None and self.password is not None:
postdata = urlencode({
'username': self.username,
'password': self.password
})
br.open(
'https://www.publico.pt/api/user/login',
data=postdata,
timeout=self.timeout
)
br.set_handle_refresh(True)
return br
def preprocess_html(self, soup):
for img in soup.findAll('img', attrs={'data-media-viewer':True}):
img['src'] = img['data-media-viewer']

View file

@ -1,17 +1,10 @@
"""
Pocket Calibre Recipe v1.4
Pocket Calibre Recipe v1.5
"""
from calibre import strftime
from calibre.web.feeds.news import BasicNewsRecipe
from string import Template
import json
import operator
import re
import tempfile
try:
from urllib.parse import urlencode
except ImportError:
from urllib import urlencode
try:
from urllib.error import HTTPError, URLError
except ImportError:
@ -39,7 +32,7 @@ class Pocket(BasicNewsRecipe):
# Settings people change
oldest_article = 7.0
max_articles_per_feed = 50
minimum_articles = 10
minimum_articles = 1
mark_as_read_after_dl = True # Set this to False for testing
sort_method = 'oldest' # MUST be either 'oldest' or 'newest'
# To filter by tag this needs to be a single tag in quotes; IE 'calibre'
@ -49,7 +42,7 @@ class Pocket(BasicNewsRecipe):
no_stylesheets = True
use_embedded_content = False
needs_subscription = True
articles_are_obfuscated = True
articles_are_obfuscated = False
apikey = '19eg0e47pbT32z4793Tf021k99Afl889'
index_url = u'https://getpocket.com'
read_api_url = index_url + u'/v3/get'
@ -118,7 +111,7 @@ def parse_index(self):
'item_id': pocket_article[0],
'title': pocket_article[1]['resolved_title'],
'date': pocket_article[1]['time_updated'],
'url': u'{0}/a/read/{1}'.format(self.index_url, pocket_article[0]),
'url': pocket_article[1]['resolved_url'],
'real_url': pocket_article[1]['resolved_url'],
'description': pocket_article[1]['excerpt'],
'sort': pocket_article[1]['sort_id']
@ -126,49 +119,6 @@ def parse_index(self):
self.articles = sorted(self.articles, key=operator.itemgetter('sort'))
return [("My Pocket Articles for {0}".format(strftime('[%I:%M %p]')), self.articles)]
def get_textview(self, url):
"""
Since Pocket's v3 API they removed access to textview. They also
redesigned their page to make it much harder to scrape their textview.
We need to pull the article, retrieve the formcheck id, then use it
to querty for the json version
This function will break when pocket hates us
"""
ajax_url = self.index_url + u'/a/x/getArticle.php'
soup = self.index_to_soup(url)
fc_tag = soup.find('script', text=re.compile("formCheck"))
fc_id = re.search(r"formCheck = \'([\d\w]+)\';", fc_tag).group(1)
article_id = url.split("/")[-1]
data = urlencode({'itemId': article_id, 'formCheck': fc_id})
try:
response = self.browser.open(ajax_url, data)
except HTTPError as e:
self.log.exception("unable to get textview {0}".format(e.info()))
raise e
return json.load(response)['article']
def get_obfuscated_article(self, url):
"""
Our get_textview returns parsed json so prettify it to something well
parsed by calibre.
"""
article = self.get_textview(url)
template = Template('<h1>$title</h1><div class="body">$body</div>')
with tempfile.NamedTemporaryFile(delete=False) as tf:
tmpbody = article['article']
for img in article['images']:
imgdiv = '<div id="RIL_IMG_{0}" class="RIL_IMG"></div>'.format(
article['images'][img]['image_id'])
imgtag = r'<img src="{0}" \>'.format(
article['images'][img]['src'])
tmpbody = tmpbody.replace(imgdiv, imgtag)
tf.write(template.safe_substitute(
title=article['title'],
body=tmpbody
))
return tf.name
def mark_as_read(self, mark_list):
actions_list = []
for article_id in mark_list:

View file

@ -12,14 +12,14 @@
# This imports the version bundled with Calibre
import lxml
from lxml.builder import E
respekt_url = 'http://www.respekt.cz'
respekt_url = 'https://www.respekt.cz'
class respektRecipe(BasicNewsRecipe):
__author__ = 'Tomáš Hnyk'
publisher = u'Respekt Publishing a. s.'
description = u'Articles from the print edition'
title = u'Respekt Magazine Print'
title = u'Respekt Magazine Print'
encoding = 'utf-8'
language = 'cs'
delay = 0.001
@ -74,10 +74,10 @@ def preprocess_raw_html(self, raw_html, url):
return raw_html
def parse_index(self):
raw1 = self.index_to_soup('http://www.respekt.cz/tydenik/', raw=True)
raw1 = self.index_to_soup('https://www.respekt.cz/tydenik/', raw=True)
root1 = lxml.html.fromstring(raw1)
current_edition_url = root1.xpath("//div[@class='heroissue']/a")[0].items()[0][1]
raw2 = self.index_to_soup('http://www.respekt.cz/' + current_edition_url, raw=True)
raw2 = self.index_to_soup('https://www.respekt.cz/' + current_edition_url, raw=True)
root2 = lxml.html.fromstring(raw2)
self.cover_url = root2.xpath("//i[contains(@class, 'heroissue-cover')]")[0].get("data-src")
# Fetch date

View file

@ -4,17 +4,18 @@
from __future__ import absolute_import, division, print_function, unicode_literals
from calibre.web.feeds.news import BasicNewsRecipe, classes
import json
from calibre.web.feeds.news import BasicNewsRecipe
country = 'us'
country_defs = {
'us': ('www.reuters.com', {
'Business': 'finance',
'Markets': 'finance/markets',
'World': 'world',
'Politics': 'politics',
'Tech': 'news/technology',
'Wealth': 'finance/wealth',
'Business': 'business',
'Markets': 'markets',
'Tech': 'technology',
'Sports': 'lifestyle/sports',
'Wealth': 'markets/wealth',
})
}
@ -32,6 +33,25 @@ def matcher(x):
return {'attrs': {'class': matcher}}
def extract_article_list(raw):
if isinstance(raw, bytes):
raw = raw.decode('utf-8')
# open('/t/raw.html', 'w').write(raw)
idx = raw.index(';Fusion.globalContent={')
d = raw[idx:]
d = d[d.index('{'):]
data = json.JSONDecoder().raw_decode(d)[0]
# from pprint import pformat
# print(pformat(data), file=open('/t/raw.py', 'w'))
k = 'arcResult' if 'arcResult' in data else 'result'
for article in data[k]['articles']:
yield {'title': article['title'], 'description': article['description'], 'url': article['canonical_url']}
# if __name__ == '__main__':
# print(list(extract_article_list(open('/t/World News _ Latest Top Stories _ Reuters.html').read())))
class Reuters(BasicNewsRecipe):
title = 'Reuters'
description = 'News from all over'
@ -39,29 +59,32 @@ class Reuters(BasicNewsRecipe):
language = 'en'
keep_only_tags = [
prefixed_classes('ArticlePage-article-header ArticlePage-article-body'),
prefixed_classes('article-header__heading___ article-header__author___ article-body__content___'),
]
remove_tags = [
prefixed_classes('ArticleBody-read-time-and-social Slideshow-expand-button- TwoColumnsLayout-footer-'),
prefixed_classes(
'context-widget__tabs___'
' ArticleBody-read-time-and-social Slideshow-expand-button- TwoColumnsLayout-footer- RegistrationPrompt__container___'
' SocialEmbed__inner___'
),
dict(name=['button', 'link']),
]
remove_attributes = ['style']
extra_css = '''
img { max-width: 100%; }
'''
def preprocess_html(self, soup, *a):
meta = soup.find(attrs={'name': "sailthru.image.full"})
if meta is not None:
url = meta['content']
body = soup.find(**prefixed_classes('ArticlePage-article-body'))
if body is not None:
div = soup.new_tag('div')
div.append(soup.new_tag('img', src=url))
body.insert(0, div)
for noscript in soup.findAll('noscript'):
if noscript.findAll('img'):
noscript.name = 'div'
return soup
def parse_index(self):
base, sections = country_defs[country]
ans = []
for section_title in sorted(sections):
for section_title in sections:
slug = sections[section_title]
self.log(section_title)
articles = list(self.parse_reuters_section(base, slug))
@ -73,15 +96,8 @@ def parse_index(self):
def parse_reuters_section(self, base, slug):
url = 'https://' + base + '/' + slug
try:
soup = self.index_to_soup(url)
except Exception:
self.log.error('Failed to load Reuters section:', url)
return
for div in soup.findAll(**classes('news-headline-list')):
h3 = div.find(**classes('story-title'))
a = h3.parent
title = self.tag_to_string(h3)
url = 'https://{}{}'.format(base, a['href'])
self.log('\t', title, url)
yield {'title': title, 'url': url}
raw = self.index_to_soup(url, raw=True)
for article in extract_article_list(raw):
article['url'] = 'https://{}{}'.format(base, article['url'])
yield article
self.log('\t', article['title'], article['url'])

25
recipes/rt.recipe Normal file
View file

@ -0,0 +1,25 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
from calibre.web.feeds.news import BasicNewsRecipe
class RtRecipe(BasicNewsRecipe):
title = 'RT на русском'
__author__ = 'Vuizur'
oldest_article = 7
max_articles_per_feed = 100
auto_cleanup = False
language = 'ru'
remove_tags_before = dict(name='h1')
remove_tags_after = dict(name='a', attrs={'class':'tags-trends__link'})
remove_tags = [
dict(name='div', attrs={'class':'error-on-page'}),
dict(name='div', attrs={'class':'short-url'}),
dict(name='div', attrs={'class':'follows-channel'}),
dict(name='a', attrs={'class':'tags-trends__link'})
]
feeds = [
('RT на русском', 'https://russian.rt.com/rss'),
]

View file

@ -4,7 +4,7 @@
CATEGORIES = {
'smart-news': 'Smart News',
'history': 'History',
'science': 'Science',
'science-nature': 'Science',
'innovation': 'Innovation',
'arts-culture': 'Arts & Culture',
'travel': 'Travel',
@ -58,7 +58,7 @@ def parse_index(self):
ans = []
for slug, title in CATEGORIES.items():
url = 'https://www.smithsonianmag.com/category/' + slug + '/'
self.log('Parsing section:', title)
self.log('Parsing section:', title, 'at:', url)
articles = list(self.parse_section(url))
if articles:
ans.append((title, articles))

View file

@ -31,27 +31,24 @@ class StraitsTimes(BasicNewsRecipe):
'comments': description, 'tags': category, 'language': language, 'publisher': publisher
}
keep_only_tags = [
classes('node-header node-subheadline group-byline-info group-updated-timestamp group-image-frame field-name-body')
classes('node-header node-subheadline group-byline-info group-updated-timestamp group-image-frame field-name-body article-content-rawhtml')
]
remove_tags = [
classes('st_telegram_boilerplate'),
classes('st_telegram_boilerplate dropdown-menu ads'),
dict(name='source'),
]
feeds = [
(u'Top of the News' , u'http://www.straitstimes.com/print/top-of-the-news/rss.xml')
,(u'World' , u'http://www.straitstimes.com/print/world/rss.xml')
,(u'Home' , u'http://www.straitstimes.com/print/home/rss.xml')
,(u'Business' , u'http://www.straitstimes.com/print/business/rss.xml')
,(u'Life' , u'http://www.straitstimes.com/print/life/rss.xml')
,(u'Science' , u'http://www.straitstimes.com/print/science/rss.xml')
,(u'Digital' , u'http://www.straitstimes.com/print/digital/rss.xml')
,(u'Insight' , u'http://www.straitstimes.com/print/insight/rss.xml')
,(u'Opinion' , u'http://www.straitstimes.com/print/opinion/rss.xml')
,(u'Forum' , u'http://www.straitstimes.com/print/forum/rss.xml')
,(u'Big Picture' , u'http://www.straitstimes.com/print/big-picture/rss.xml')
,(u'Community' , u'http://www.straitstimes.com/print/community/rss.xml')
,(u'Education' , u'http://www.straitstimes.com/print/education/rss.xml')
(u'World' , u'https://www.straitstimes.com/news/world/rss.xml')
,(u'Business' , u'https://www.straitstimes.com/news/business/rss.xml')
,(u'Life' , u'https://www.straitstimes.com/news/life/rss.xml')
,(u'Tech' , u'https://www.straitstimes.com/news/tech/rss.xml')
,(u'Opinion' , u'https://www.straitstimes.com/news/opinion/rss.xml')
,(u'Life' , u'https://www.straitstimes.com/news/life/rss.xml')
,(u'Singapore' , u'https://www.straitstimes.com/news/singapore/rss.xml')
,(u'Asia' , u'https://www.straitstimes.com/news/asia/rss.xml')
,(u'Multimedia' , u'https://www.straitstimes.com/news/multimedia/rss.xml')
,(u'Sport' , u'https://www.straitstimes.com/news/sport/rss.xml')
]
def preprocess_html(self, soup):

44
recipes/swarajya.recipe Normal file
View file

@ -0,0 +1,44 @@
from calibre.web.feeds.news import BasicNewsRecipe, classes
class SwarajyaMag(BasicNewsRecipe):
title = u'Swarajya Magazine'
__author__ = 'unkn0wn'
description = 'Swarajya - a big tent for liberal right of centre discourse that reaches out, engages and caters to the new India.'
language = 'en_IN'
no_stylesheets = True
remove_javascript = True
use_embedded_content = False
remove_attributes = ['height', 'width']
encoding = 'utf-8'
keep_only_tags = [
classes('_2PqtR _1sMRD ntw8h author-bio'),
]
remove_tags = [
classes('_JscD _2r17a'),
]
def preprocess_html(self, soup):
for img in soup.findAll('img', attrs={'data-src': True}):
img['src'] = img['data-src'].split('?')[0]
return soup
def parse_index(self):
soup = self.index_to_soup('https://swarajyamag.com/all-issues')
a = soup.find('a', href=lambda x: x and x.startswith('/issue/'))
url = a['href']
self.log('Downloading issue:', url)
self.cover_url = a.find('img', attrs={'data-src': True})['data-src']
soup = self.index_to_soup('https://swarajyamag.com' + url)
ans = []
for a in soup.findAll(**classes('_2eOQr')):
url = a['href']
if url.startswith('/'):
url = 'https://swarajyamag.com' + url
title = self.tag_to_string(a)
self.log(title, ' at ', url)
ans.append({'title': title, 'url': url})
return [('Articles', ans)]

View file

@ -16,29 +16,53 @@ class Federalist(BasicNewsRecipe):
title = 'The Federalist'
__author__ = 'Kovid Goyal'
language = 'en'
oldest_article = 7
oldest_article = 10
max_articles_per_feed = 100
no_stylesheets = True
encoding = 'utf-8'
use_embedded_content = False
remove_attributes = ['xmlns', 'lang', 'style', 'width', 'height']
extra_css = '''
.shortbio { margin: 1em; padding: 1em; font-style: italic }
'''
extra_css = """
.shortbio,.article-excerpt{font-style: italic}
.article-author-details,.article-author-description,.article-meta-author,.article-meta-date,.article-thumbnail-caption{font-size: small}
"""
keep_only_tags = [
classes('entry-header'),
classes('wp-post-image post-categories entry-content shortbio byline-month byline-standard alpha-byline'),
classes(
'title-lg article-thumbnail post-categories article-excerpt article-author-details'
' article-meta-author article-meta-date article-content article-body shortbio entry-header'
' byline-month byline-standard alpha-byline article-author-description article-author-details'),
]
remove_tags = [
dict(name=['meta', 'link']),
classes('auth-ad attachment-post-thumbnail attachment-author-bio'),
classes('auth-ad article-share article-tags attachment-post-thumbnail attachment-author-bio'),
]
feeds = [
('All', 'http://thefederalist.com/feed/'),
('All', 'https://thefederalist.com/feed/'),
]
# def parse_index(self):
# return [('Articles', [
# {
# 'title': 'test',
# 'url': 'https://thefederalist.com/2022/03/09/propaganda-press-wield-bidens-russia-blame-game-to-gaslight-americans-about-expensive-gas/'},
# {
# 'title': 'test2',
# 'url': 'https://thefederalist.com/2022/03/10/white-house-will-blame-anyone-but-biden-for-februarys-7-9-inflation-jump/',
# }
# ])]
def preprocess_raw_html_(self, raw_html, url):
soup = self.index_to_soup(raw_html)
# this website puts article-thumbnail images inside article-body in
# some articles and outside it in others, so we have to special case it
for ab in soup.findAll(**classes('article-body')):
for img in ab.findAll(**classes('article-thumbnail')):
del img['class']
return str(soup)
def preprocess_html(self, soup):
for img in soup.findAll('img', attrs={'data-lazy-src': True}):
img['src'] = img['data-lazy-src']
@ -49,9 +73,3 @@ def preprocess_html(self, soup):
img.extract()
seen.add(src)
return soup
# def parse_index(self):
# return [('Articles', [
# {'title':'img', 'url':'http://thefederalist.com/2018/05/09/venezuelas-economic-problems-caused-socialism-not-falling-oil-prices/'},
# {'title':'xxx', 'url':'http://thefederalist.com/2018/05/04/fans-take-on-marvel-dc-and-the-comic-book-industrys-sjw-self-destruction/'},
# ])]

File diff suppressed because it is too large Load diff

View file

@ -38,11 +38,9 @@
use_series_auto_increment_tweak_when_importing = False
#: Add separator after completing an author name
# Should the completion separator be append
# to the end of the completed text to
# automatically begin a new completion operation
# for authors.
# Can be either True or False
# Set this if the completion separator should be appended to the end of the
# completed text to automatically begin a new completion operation for authors.
# It can be either True or False
authors_completer_append_separator = False
#: Author sort name algorithm
@ -250,6 +248,8 @@
# French
'fra' : (r'Le\s+', r'La\s+', r"L'", u'L´', u'L', r'Les\s+', r'Un\s+', r'Une\s+',
r'Des\s+', r'De\s+La\s+', r'De\s+', r"D'", u'D´', u'L'),
# Polish
'pol': (),
# Italian
'ita': ('Lo\\s+', 'Il\\s+', "L'", 'L´', 'La\\s+', 'Gli\\s+',
'I\\s+', 'Le\\s+', 'Uno\\s+', 'Un\\s+', 'Una\\s+', "Un'",
@ -426,37 +426,6 @@
# Example: locale_for_sorting = 'nb' -- sort using Norwegian rules.
locale_for_sorting = ''
#: Number of columns for custom metadata in the edit metadata dialog
# Set whether to use one or two columns for custom metadata when editing
# metadata one book at a time. If True, then the fields are laid out using two
# columns. If False, one column is used.
metadata_single_use_2_cols_for_custom_fields = True
#: Order of custom column(s) in edit metadata
# Controls the order that custom columns are listed in edit metadata single
# and bulk. The columns listed in the tweak are displayed first and in the
# order provided. Any columns not listed are displayed after the listed ones,
# in alphabetical order. Do note that this tweak does not change the size of
# the edit widgets. Putting comments widgets in this list may result in some
# odd widget spacing when using two-column mode.
# Enter a comma-separated list of custom field lookup names, as in
# metadata_edit_custom_column_order = ['#genre', '#mytags', '#etc']
metadata_edit_custom_column_order = []
#: Edit metadata custom column label width and elision point
# Set the width of custom column labels shown in the edit metadata dialogs.
# If metadata_edit_elide_labels is True then labels wider than the width
# will be elided, otherwise they will be word wrapped. The maximum width is
# computed by multiplying the average width of characters in the font by the
# appropriate number.
# Set the elision point to 'middle' to put the ellipsis (…) in the middle of
# the label, 'right' to put it at the right end of the label, and 'left' to
# put it at the left end.
metadata_edit_elide_labels = True
metadata_edit_bulk_cc_label_length = 25
metadata_edit_single_cc_label_length = 12
metadata_edit_elision_point = 'right'
#: The number of seconds to wait before sending emails
# The number of seconds to wait before sending emails when using a
# public email server like GMX/Hotmail/Gmail. Default is: 5 minutes
@ -466,7 +435,7 @@
# to be public relays here. Any relay host ending with one of the suffixes
# in the list below will be considered a public email server.
public_smtp_relay_delay = 301
public_smtp_relay_host_suffixes = ['gmail.com', 'live.com', 'gmx.com']
public_smtp_relay_host_suffixes = ['gmail.com', 'live.com', 'gmx.com', 'outlook.com']
#: The maximum width and height for covers saved in the calibre library
# All covers in the calibre library will be resized, preserving aspect ratio,
@ -531,7 +500,14 @@
# completions you will now have to press Tab to select one before pressing
# Enter. Which technique you prefer will depend on the state of metadata in
# your library and your personal editing style.
#
# If preselect_first_completion is False and you want Tab to accept what you
# typed instead of the first completion then set tab_accepts_uncompleted_text
# to True. If you do this then to select from the completions you must press
# the Down or Up arrow keys. The tweak tab_accepts_uncompleted_text is ignored
# if preselect_first_completion is True
preselect_first_completion = False
tab_accepts_uncompleted_text = False
#: Completion mode when editing authors/tags/series/etc.
# By default, when completing items, calibre will show you all the candidates
@ -582,6 +558,8 @@
# Edit metadata->Copy metadata/Paste metadata actions. For example,
# exclude_fields_on_paste = ['cover', 'timestamp', '#mycolumn']
# to prevent pasting of the cover, Date and custom column, mycolumn.
# You can also add a shortcut in Preferences->Shortcuts->Edit metadata
# to paste metadata ignoring this tweak.
exclude_fields_on_paste = []
#: Skip internet connected check
@ -594,3 +572,16 @@
# Sets the width of the tab stop in the template editor in "average characters".
# For example, a value of 1 results in a space with the width of one average character.
template_editor_tab_stop_width = 4
#: Value for undefined numbers when sorting
# Sets the value to use for undefined numbers when sorting.
# For example, the value -10 sorts undefined numbers as if they were set to -10.
# Use 'maximum' for the largest possible number. Use 'minimum' for the smallest
# possible number. Quotes are optional if entering a number.
# Examples:
# value_for_undefined_numbers_when_sorting = -100
# value_for_undefined_numbers_when_sorting = '2'
# value_for_undefined_numbers_when_sorting = -0.01
# value_for_undefined_numbers_when_sorting = 'minimum'
# value_for_undefined_numbers_when_sorting = 'maximum'
value_for_undefined_numbers_when_sorting = 0

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,5 @@
SET UTF-8
FLAG UTF-8
TRY aeroinsctldumpbgfvhzóíjáqéñxyúükwAEROINSCTLDUMPBGFVHZÓÍJÁQÉÑXYÚÜKW
REP 20
REP ás az
@ -105,15 +106,22 @@ PFX u e tras e[^s]
PFX v Y 2
PFX v 0 contra [^r]
PFX v 0 contrar r
SFX A Y 9
PFX w Y 1
PFX w 0 ex .
SFX A Y 14
SFX A r ción/S ar
SFX A er ición/S [^cn]er
SFX A er ición/S [^e]cer
SFX A ecer ición/S ecer
SFX A er ición/S [^o]ner
SFX A ner sición/S oner
SFX A r ción/S [^c]ir
SFX A r ción/S [^u]cir
SFX A r ción/S [^bc]ir
SFX A bir pción/S ebir
SFX A bir pción/S [^ch]ibir
SFX A ibir epción/S cibir
SFX A r ción/S hibir
SFX A ecir ición/S [^ae]decir
SFX A ecir icción/S [ae]decir
SFX A ir ción/S ucir
SFX B Y 3
SFX B r dura/S [aií]r
@ -194,13 +202,14 @@ SFX M o eza/S nto
SFX M o eza/S [aie]sto
SFX M o ez/S usto
SFX M o uez/S go
SFX N Y 18
SFX N Y 19
SFX N a illa/S [bdfhjlmnprstv]a
SFX N o illo/S [bdhjlmnprstv]o
SFX N 0 cilla/S ve
SFX N za cilla/S za
SFX N 0 ecilla/S d
SFX N ón oncillo/S ón
SFX N ión ioncilla/S [cglnstx]ión
SFX N ón oncillo/S [^i]ón
SFX N 0 cillo/S or
SFX N zo cillo/S zo
SFX N 0 cillo/S [djlnu]e
@ -261,7 +270,7 @@ SFX T r ble/S ar
SFX T er ible/S [^aeo]er
SFX T er íble/S [aeo]er
SFX T r ble/S ir
SFX U Y 18
SFX U Y 19
SFX U a ita/S [bdfhjlmnprstv]a
SFX U o ito/S [bdhjlmnprstv]o
SFX U 0 cita/S ve
@ -269,6 +278,7 @@ SFX U za cita/S za
SFX U 0 ecita/S d
SFX U ón oncito/S ón
SFX U 0 cito/S or
SFX U o íto/S eo
SFX U zo cito/S zo
SFX U 0 cito/S [djlnu]e
SFX U z cecita/S z
@ -280,8 +290,7 @@ SFX U co quito/S co
SFX U go guito/S go
SFX U ca quita/S ca
SFX U ga guita/S ga
SFX R Y 240
SFX R ar ás ar
SFX R Y 235
SFX R r mos [aei]r
SFX R ar áis ar
SFX R r ba ar
@ -337,12 +346,10 @@ SFX R 0 es ar
SFX R ar áremos ar
SFX R 0 eis ar
SFX R 0 en ar
SFX R ar á ar
SFX R r d [aei]r
SFX R r ndo ar
SFX R ar ándose ar
SFX R 0 se [aeií]r
SFX R er és er
SFX R er éis er
SFX R er ía er
SFX R er ías er
@ -396,7 +403,6 @@ SFX R er yendo [aeo]er
SFX R er yéndose [aeo]er
SFX R r ndo ñer
SFX R er éndose ñer
SFX R er é er
SFX R ir ís ir
SFX R ir ía ir
SFX R ir ías ir
@ -520,7 +526,6 @@ SFX R r endo [gq]uir
SFX R r éndose [gq]uir
SFX R ir yendo [^gq]uir
SFX R ir yéndose [^gq]uir
SFX R ir í ir
SFX E Y 73
SFX E ar o ar
SFX E r s [ae]r
@ -595,10 +600,9 @@ SFX E cir zan cir
SFX E gir jan gir
SFX E uir an guir
SFX E quir can quir
SFX I Y 741
SFX I Y 738
SFX I ertar ierto ertar
SFX I ertar iertas ertar
SFX I ar ás ar
SFX I ertar ierta ertar
SFX I ertar iertan ertar
SFX I ertar ierte ertar
@ -1138,7 +1142,6 @@ SFX I usar úses usar
SFX I usar úsen usar
SFX I cer zco [ae]cer
SFX I r s [ae]cer
SFX I er és er
SFX I r 0 [ae]cer
SFX I r n [ae]cer
SFX I cer zca [ae]cer
@ -1274,7 +1277,6 @@ SFX I er igan oer
SFX I er yan oer
SFX I ir go sir
SFX I ir es sir
SFX I ir ís ir
SFX I ir e sir
SFX I ir en sir
SFX I ir ga sir
@ -1337,14 +1339,13 @@ SFX I ir yas uir
SFX I ir yamos uir
SFX I ir yáis uir
SFX I ir yan uir
SFX X Y 1141
SFX X Y 1137
SFX X er go oner
SFX X r s oner
SFX X r 0 oner
SFX X r mos [ei]r
SFX X er éis [^v]er
SFX X er éis [es]ver
SFX X er és [^v]er
SFX X r n oner
SFX X erer iero erer
SFX X erer ieres erer
@ -2017,26 +2018,26 @@ SFX X aber upierais aber
SFX X aber upieseis aber
SFX X aber upieran aber
SFX X aber upiesen aber
SFX X r ra ñer
SFX X r se ñer
SFX X r ras ñer
SFX X r ses ñer
SFX X er éramos ñer
SFX X er ésemos ñer
SFX X r rais ñer
SFX X r seis ñer
SFX X r ran ñer
SFX X r sen ñer
SFX X er iera [lv]er
SFX X er iese [lv]er
SFX X er ieras [lv]er
SFX X er ieses [lv]er
SFX X er iéramos [lv]er
SFX X er iésemos [lv]er
SFX X er ierais [lv]er
SFX X er ieseis [lv]er
SFX X er ieran [lv]er
SFX X er iesen [lv]er
SFX X r ra ñer
SFX X r se ñer
SFX X r ras ñer
SFX X r ses ñer
SFX X er éramos ñer
SFX X er ésemos ñer
SFX X r rais ñer
SFX X r seis ñer
SFX X r ran ñer
SFX X r sen ñer
SFX X er iera [lv]er
SFX X er iese [lv]er
SFX X er ieras [lv]er
SFX X er ieses [lv]er
SFX X er iéramos [lv]er
SFX X er iésemos [lv]er
SFX X er ierais [lv]er
SFX X er ieseis [lv]er
SFX X er ieran [lv]er
SFX X er iesen [lv]er
SFX X erir iriera erir
SFX X erir iriese erir
SFX X erir irieras erir
@ -2297,16 +2298,16 @@ SFX X aber upieres aber
SFX X aber upiéremos aber
SFX X aber upiereis aber
SFX X aber upieren aber
SFX X r re ñer
SFX X r res ñer
SFX X er éremos ñer
SFX X r reis ñer
SFX X r ren ñer
SFX X er iere [lv]er
SFX X er ieres [lv]er
SFX X er iéremos [lv]er
SFX X er iereis [lv]er
SFX X er ieren [lv]er
SFX X r re ñer
SFX X r res ñer
SFX X er éremos ñer
SFX X r reis ñer
SFX X r ren ñer
SFX X er iere [lv]er
SFX X er ieres [lv]er
SFX X er iéremos [lv]er
SFX X er iereis [lv]er
SFX X er ieren [lv]er
SFX X erir iriere erir
SFX X erir irieres erir
SFX X erir iriéremos erir
@ -2423,9 +2424,6 @@ SFX X ír yéremos oír
SFX X ír yereis oír
SFX X ír yeren oír
SFX X r d [ei]r
SFX X er é er
SFX X ir í ir
SFX X r 0 ír
SFX X er iendo [^añ]er
SFX X er iéndose [^añ]er
SFX X er yendo aer
@ -3065,10 +3063,6 @@ SFX Ì abar ábala abar
SFX Ì abar ábalas abar
SFX Ì abar ábalo abar
SFX Ì abar ábalos abar
SFX Ì r la r
SFX Ì r las r
SFX Ì r lo r
SFX Ì r los r
SFX Ì r dla r
SFX Ì r dlas r
SFX Ì r dlo r
@ -3445,11 +3439,13 @@ SFX Ì utar útalas utar
SFX Ì utar útala utar
SFX Ì utar útalos utar
SFX Ì utar útalo utar
SFX Í Y 164
SFX Ì uzar úzalas uzar
SFX Ì uzar úzala uzar
SFX Ì uzar úzalos uzar
SFX Ì uzar úzalo uzar
SFX Í Y 172
SFX Í abar ábame abar
SFX Í abar ábanos abar
SFX Í r me r
SFX Í r nos r
SFX Í r dme r
SFX Í r dnos r
SFX Í ablar áblame ablar
@ -3490,6 +3486,8 @@ SFX Í argar árgame argar
SFX Í argar árganos argar
SFX Í arrar árrame arrar
SFX Í arrar árranos arrar
SFX Í asar ásame asar
SFX Í asar ásanos asar
SFX Í atar átame atar
SFX Í atar átanos atar
SFX Í avar ávame avar
@ -3504,6 +3502,8 @@ SFX Í eer éeme eer
SFX Í eer éenos eer
SFX Í egar égame egar
SFX Í egar éganos egar
SFX Í eger égeme eger
SFX Í eger égenos eger
SFX Í egrar égrame egrar
SFX Í egrar égranos egrar
SFX Í ejar éjame ejar
@ -3528,6 +3528,8 @@ SFX Í ercar ércame ercar
SFX Í ercar ércanos ercar
SFX Í esar ésame esar
SFX Í esar ésanos esar
SFX Í escar éscame escar
SFX Í escar éscanos escar
SFX Í estar éstame estar
SFX Í estar éstanos estar
SFX Í etar étame etar
@ -3538,6 +3540,8 @@ SFX Í evar évame evar
SFX Í evar évanos evar
SFX Í ibir íbeme ibir
SFX Í ibir íbenos ibir
SFX Í ibrar íbrame ibrar
SFX Í ibrar íbranos ibrar
SFX Í icar ícame icar
SFX Í icar ícanos icar
SFX Í iciar íciame iciar
@ -3558,6 +3562,8 @@ SFX Í obrar óbrame obrar
SFX Í obrar óbranos obrar
SFX Í ocar ócame ocar
SFX Í ocar ócanos ocar
SFX Í ocer óceme ocer
SFX Í ocer ócenos ocer
SFX Í oger ógeme oger
SFX Í oger ógenos oger
SFX Í ojar ójame ojar
@ -3613,8 +3619,6 @@ SFX Í uscar úscanos uscar
SFX Î Y 86
SFX Î abar ábale abar
SFX Î abar ábales abar
SFX Î r le r
SFX Î r les r
SFX Î r dle r
SFX Î r dles r
SFX Î ablar áblale ablar
@ -3655,6 +3659,8 @@ SFX Î eter étele eter
SFX Î eter ételes eter
SFX Î evar évale evar
SFX Î evar évales evar
SFX Î ibir íbele ibir
SFX Î ibir íbeles ibir
SFX Î icar ícale icar
SFX Î icar ícales icar
SFX Î iciar íciale iciar
@ -3697,7 +3703,7 @@ SFX Î untar úntales untar
SFX Î untar úntale untar
SFX Î uscar úscales uscar
SFX Î uscar úscale uscar
SFX Ï Y 300
SFX Ï Y 288
SFX Ï adir ádemela adir
SFX Ï adir ádemelas adir
SFX Ï adir ádemelo adir
@ -3710,18 +3716,6 @@ SFX Ï adir ádesela adir
SFX Ï adir ádeselas adir
SFX Ï adir ádeselo adir
SFX Ï adir ádeselos adir
SFX Ï ir ímela ir
SFX Ï ir ímelas ir
SFX Ï ir ímelo ir
SFX Ï ir ímelos ir
SFX Ï ir ínosla ir
SFX Ï ir ínoslas ir
SFX Ï ir ínoslo ir
SFX Ï ir ínoslos ir
SFX Ï ir ísela ir
SFX Ï ir íselas ir
SFX Ï ir íselo ir
SFX Ï ir íselos ir
SFX Ï ir ídmela ir
SFX Ï ir ídmelas ir
SFX Ï ir ídmelo ir
@ -3746,18 +3740,6 @@ SFX Ï ambiar ámbiasela ambiar
SFX Ï ambiar ámbiaselas ambiar
SFX Ï ambiar ámbiaselo ambiar
SFX Ï ambiar ámbiaselos ambiar
SFX Ï ar ámela ar
SFX Ï ar ámelas ar
SFX Ï ar ámelo ar
SFX Ï ar ámelos ar
SFX Ï ar ánosla ar
SFX Ï ar ánoslas ar
SFX Ï ar ánoslo ar
SFX Ï ar ánoslos ar
SFX Ï ar ásela ar
SFX Ï ar áselas ar
SFX Ï ar áselo ar
SFX Ï ar áselos ar
SFX Ï ar ádmela ar
SFX Ï ar ádmelas ar
SFX Ï ar ádmelo ar
@ -3782,6 +3764,18 @@ SFX Ï ancar áncasela ancar
SFX Ï ancar áncaselas ancar
SFX Ï ancar áncaselo ancar
SFX Ï ancar áncaselos ancar
SFX Ï andar ándamela andar
SFX Ï andar ándamelas andar
SFX Ï andar ándamelo andar
SFX Ï andar ándamelos andar
SFX Ï andar ándanosla andar
SFX Ï andar ándanoslas andar
SFX Ï andar ándanoslo andar
SFX Ï andar ándanoslos andar
SFX Ï andar ándasela andar
SFX Ï andar ándaselas andar
SFX Ï andar ándaselo andar
SFX Ï andar ándaselos andar
SFX Ï antar ántamela antar
SFX Ï antar ántamelas antar
SFX Ï antar ántamelo antar
@ -3806,6 +3800,18 @@ SFX Ï anzar ánzasela anzar
SFX Ï anzar ánzaselas anzar
SFX Ï anzar ánzaselo anzar
SFX Ï anzar ánzaselos anzar
SFX Ï ardar árdamela ardar
SFX Ï ardar árdamelas ardar
SFX Ï ardar árdamelo ardar
SFX Ï ardar árdamelos ardar
SFX Ï ardar árdanosla ardar
SFX Ï ardar árdanoslas ardar
SFX Ï ardar árdanoslo ardar
SFX Ï ardar árdanoslos ardar
SFX Ï ardar árdasela ardar
SFX Ï ardar árdaselas ardar
SFX Ï ardar árdaselo ardar
SFX Ï ardar árdaselos ardar
SFX Ï asar ásamela asar
SFX Ï asar ásamelas asar
SFX Ï asar ásamelo asar
@ -3842,18 +3848,6 @@ SFX Ï eder édesela eder
SFX Ï eder édeselas eder
SFX Ï eder édeselo eder
SFX Ï eder édeselos eder
SFX Ï er émela er
SFX Ï er émelas er
SFX Ï er émelo er
SFX Ï er émelos er
SFX Ï er énosla er
SFX Ï er énoslas er
SFX Ï er énoslo er
SFX Ï er énoslos er
SFX Ï er ésela er
SFX Ï er éselas er
SFX Ï er éselo er
SFX Ï er éselos er
SFX Ï er édmela er
SFX Ï er édmelas er
SFX Ï er édmelo er
@ -3998,15 +3992,11 @@ SFX Ï urar úraselas urar
SFX Ï urar úrasela urar
SFX Ï urar úraselos urar
SFX Ï urar úraselo urar
SFX Ð Y 60
SFX Ð Y 56
SFX Ð egar iégala egar
SFX Ð egar iégalas egar
SFX Ð egar iégalo egar
SFX Ð egar iégalos egar
SFX Ð r la r
SFX Ð r las r
SFX Ð r lo r
SFX Ð r los r
SFX Ð r dla r
SFX Ð r dlas r
SFX Ð r dlo r
@ -4059,11 +4049,9 @@ SFX Ð ostrar uéstrala ostrar
SFX Ð ostrar uéstralas ostrar
SFX Ð ostrar uéstralo ostrar
SFX Ð ostrar uéstralos ostrar
SFX Ñ Y 26
SFX Ñ Y 24
SFX Ñ ecer éceme ecer
SFX Ñ ecer écenos ecer
SFX Ñ r me r
SFX Ñ r nos r
SFX Ñ r dme r
SFX Ñ r dnos r
SFX Ñ ender iéndeme ender
@ -4086,11 +4074,9 @@ SFX Ñ order uérdeme order
SFX Ñ order uérdenos order
SFX Ñ ostrar uéstrame ostrar
SFX Ñ ostrar uéstranos ostrar
SFX Ò Y 22
SFX Ò Y 20
SFX Ò ecer écele ecer
SFX Ò ecer éceles ecer
SFX Ò r le r
SFX Ò r les r
SFX Ò r dle r
SFX Ò r dles r
SFX Ò egar iégale egar
@ -4109,7 +4095,7 @@ SFX Ò order uérdele order
SFX Ò order uérdeles order
SFX Ò ostrar uéstrale ostrar
SFX Ò ostrar uéstrales ostrar
SFX Ó Y 120
SFX Ó Y 96
SFX Ó ecer écemela ecer
SFX Ó ecer écemelas ecer
SFX Ó ecer écemelo ecer
@ -4122,18 +4108,6 @@ SFX Ó ecer écesela ecer
SFX Ó ecer éceselas ecer
SFX Ó ecer éceselo ecer
SFX Ó ecer éceselos ecer
SFX Ó er émela er
SFX Ó er émelas er
SFX Ó er émelo er
SFX Ó er émelos er
SFX Ó er énosla er
SFX Ó er énoslas er
SFX Ó er énoslo er
SFX Ó er énoslos er
SFX Ó er ésela er
SFX Ó er éselas er
SFX Ó er éselo er
SFX Ó er éselos er
SFX Ó er édmela er
SFX Ó er édmelas er
SFX Ó er édmelo er
@ -4158,18 +4132,6 @@ SFX Ó iar íasela iar
SFX Ó iar íaselas iar
SFX Ó iar íaselo iar
SFX Ó iar íaselos iar
SFX Ó ar ámela ar
SFX Ó ar ámelas ar
SFX Ó ar ámelo ar
SFX Ó ar ámelos ar
SFX Ó ar ánosla ar
SFX Ó ar ánoslas ar
SFX Ó ar ánoslo ar
SFX Ó ar ánoslos ar
SFX Ó ar ásela ar
SFX Ó ar áselas ar
SFX Ó ar áselo ar
SFX Ó ar áselos ar
SFX Ó ar ádmela ar
SFX Ó ar ádmelas ar
SFX Ó ar ádmelo ar
@ -4235,10 +4197,6 @@ SFX Ô aer áela aer
SFX Ô aer áelas aer
SFX Ô aer áelo aer
SFX Ô aer áelos aer
SFX Ô r la r
SFX Ô r las r
SFX Ô r lo r
SFX Ô r los r
SFX Ô r dla r
SFX Ô r dlas r
SFX Ô r dlo r
@ -4255,6 +4213,10 @@ SFX Ô edir ídela edir
SFX Ô edir ídelas edir
SFX Ô edir ídelo edir
SFX Ô edir ídelos edir
SFX Ô egir ígela egir
SFX Ô egir ígelas egir
SFX Ô egir ígelo egir
SFX Ô egir ígelos egir
SFX Ô eguir íguela eguir
SFX Ô eguir íguelas eguir
SFX Ô eguir íguelo eguir
@ -4291,11 +4253,9 @@ SFX Ô uir úyelas uir
SFX Ô uir úyela uir
SFX Ô uir úyelos uir
SFX Ô uir úyelo uir
SFX Õ Y 28
SFX Õ Y 26
SFX Õ aber ábeme aber
SFX Õ aber ábenos aber
SFX Õ r me r
SFX Õ r nos r
SFX Õ r dme r
SFX Õ r dnos r
SFX Õ aer áeme aer
@ -4320,11 +4280,9 @@ SFX Õ r me ver
SFX Õ r nos ver
SFX Õ ucir úceme ucir
SFX Õ ucir úcenos ucir
SFX Ö Y 16
SFX Ö Y 14
SFX Ö aber ábele aber
SFX Ö aber ábeles aber
SFX Ö r le r
SFX Ö r les r
SFX Ö r dle r
SFX Ö r dles r
SFX Ö aer áele aer
@ -4337,7 +4295,7 @@ SFX Ö er le ner
SFX Ö er les ner
SFX Ö r le ver
SFX Ö r les ver
SFX Ø Y 84
SFX Ø Y 60
SFX Ø aer áemela aer
SFX Ø aer áemelas aer
SFX Ø aer áemelo aer
@ -4350,18 +4308,6 @@ SFX Ø aer áesela aer
SFX Ø aer áeselas aer
SFX Ø aer áeselo aer
SFX Ø aer áeselos aer
SFX Ø er émela er
SFX Ø er émelas er
SFX Ø er émelo er
SFX Ø er émelos er
SFX Ø er énosla er
SFX Ø er énoslas er
SFX Ø er énoslo er
SFX Ø er énoslos er
SFX Ø er ésela er
SFX Ø er éselas er
SFX Ø er éselo er
SFX Ø er éselos er
SFX Ø er édmela er
SFX Ø er édmelas er
SFX Ø er édmelo er
@ -4386,18 +4332,6 @@ SFX Ø edir ídesela edir
SFX Ø edir ídeselas edir
SFX Ø edir ídeselo edir
SFX Ø edir ídeselos edir
SFX Ø ir ímela ir
SFX Ø ir ímelas ir
SFX Ø ir ímelo ir
SFX Ø ir ímelos ir
SFX Ø ir ínosla ir
SFX Ø ir ínoslas ir
SFX Ø ir ínoslo ir
SFX Ø ir ínoslos ir
SFX Ø ir ísela ir
SFX Ø ir íselas ir
SFX Ø ir íselo ir
SFX Ø ir íselos ir
SFX Ø ir ídmela ir
SFX Ø ir ídmelas ir
SFX Ø ir ídmelo ir
@ -6285,9 +6219,8 @@ SFX ó r éndome ucir
SFX ó r éndonos ucir
SFX ó r éndoos ucir
SFX ó r éndote ucir
SFX ô Y 136
SFX ô Y 137
SFX ô abar ábate abar
SFX ô r te [aei]r
SFX ô r os r
SFX ô acar ácate acar
SFX ô achar áchate achar
@ -6331,6 +6264,7 @@ SFX ô azar ázate azar
SFX ô ear éate ear
SFX ô ecar écate ecar
SFX ô echar échate echar
SFX ô ectar éctate ectar
SFX ô edar édate edar
SFX ô egar égate egar
SFX ô eger égete eger
@ -6373,6 +6307,7 @@ SFX ô intar íntate intar
SFX ô irar írate irar
SFX ô ir íos ir
SFX ô istar ístate istar
SFX ô istrar ístrate istrar
SFX ô itar ítate itar
SFX ô itir ítete itir
SFX ô izar ízate izar
@ -6422,9 +6357,8 @@ SFX ô urlar úrlate urlar
SFX ô uscar úscate uscar
SFX ô ustar ústate ustar
SFX ô ustrar ústrate ustrar
SFX õ Y 31
SFX õ Y 30
SFX õ aer áete aer
SFX õ r te [aei]r
SFX õ r os [^i]r
SFX õ ecer écete ecer
SFX õ egar iégate egar
@ -6454,9 +6388,8 @@ SFX õ over uévete over
SFX õ uar úate uar
SFX õ unir únete unir
SFX õ ir íos ir
SFX ö Y 18
SFX ö Y 17
SFX ö aer áete aer
SFX ö r te [eií]r
SFX ö r os [^i]r
SFX ö aler álete aler
SFX ö cer zte cer

File diff suppressed because it is too large Load diff

View file

@ -875,7 +875,6 @@ application/x-ustar ustar
application/x-wais-source src
application/x-wingz wz
application/x-x509-ca-cert crt der
application/x-xcf xcf
application/x-xfig fig
application/x-xpinstall xpi
application/x400-bp
@ -1146,6 +1145,7 @@ image/x-portable-graymap pgm
image/x-portable-pixmap ppm
image/x-rgb rgb
image/x-xbitmap xbm
image/x-xcf xcf
image/x-xpixmap xpm
image/x-xwindowdump xwd
message/cpim

View file

@ -35,6 +35,8 @@
// is U+2010 but that does not render with the default Times font on macOS as of Monterey
// and Qt 15.5 See https://bugs.launchpad.net/bugs/1951467 and can be easily reproduced
// by converting a plain text file with the --pdf-hyphenate option
// https://bugs.chromium.org/p/chromium/issues/detail?id=1267606 (fix released Feb 1 2022 v98)
// See also settings.pyj
if (HYPHEN_CHAR) {
for (const elem of document.getElementsByTagName('*')) {
if (elem.style) {

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
__license__ = 'GPL v3'
@ -92,7 +91,7 @@ def build_cache_dir():
_cache_dir_built = True
try:
os.mkdir(ans)
except EnvironmentError as err:
except OSError as err:
if err.errno != errno.EEXIST:
raise
return ans
@ -100,7 +99,7 @@ def build_cache_dir():
def require_git_master(branch='master'):
if subprocess.check_output(['git', 'symbolic-ref', '--short', 'HEAD']).decode('utf-8').strip() != branch:
raise SystemExit('You must be in the {} git branch'.format(branch))
raise SystemExit(f'You must be in the {branch} git branch')
def require_clean_git():
@ -225,7 +224,7 @@ def run_cmd(self, cmd, opts):
st = time.time()
self.running(cmd)
cmd.run(opts)
self.info('* %s took %.1f seconds' % (command_names[cmd], time.time() - st))
self.info(f'* {command_names[cmd]} took {time.time() - st:.1f} seconds')
if os.environ.get('CI'):
self.info('::endgroup::')

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
# License: GPLv3 Copyright: 2017, Kovid Goyal <kovid at kovidgoyal.net>

View file

@ -1,11 +1,10 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
__license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
import textwrap, os, shlex, subprocess, glob, shutil, sys, json, errno
import textwrap, os, shlex, subprocess, glob, shutil, sys, json, errno, sysconfig
from collections import namedtuple
from setup import Command, islinux, isbsd, isfreebsd, ismacos, ishaiku, SRC, iswindows
@ -28,7 +27,7 @@ def init_symbol_name(name):
def absolutize(paths):
return list(set([x if os.path.isabs(x) else os.path.join(SRC, x.replace('/', os.sep)) for x in paths]))
return list({x if os.path.isabs(x) else os.path.join(SRC, x.replace('/', os.sep)) for x in paths})
class Extension:
@ -167,9 +166,20 @@ def read_extensions():
return ans
def get_python_include_paths():
ans = []
for name in sysconfig.get_path_names():
if 'include' in name:
ans.append(name)
def gp(x):
return sysconfig.get_path(x)
return sorted(frozenset(filter(None, map(gp, sorted(ans)))))
def init_env(debug=False, sanitize=False):
from setup.build_environment import win_ld, is64bit, win_inc, win_lib, NMAKE, win_cc
from distutils import sysconfig
linker = None
if isunix:
cc = os.environ.get('CC', 'gcc')
@ -202,17 +212,20 @@ def init_env(debug=False, sanitize=False):
ldflags.append('-shared')
if islinux or isbsd or ishaiku:
cflags.append('-I'+sysconfig.get_python_inc())
# getattr(..., 'abiflags') is for PY2 compat, since PY2 has no abiflags
# member
ldflags.append('-lpython{}{}'.format(
sysconfig.get_config_var('VERSION'), getattr(sys, 'abiflags', '')))
cflags.extend('-I' + x for x in get_python_include_paths())
ldlib = sysconfig.get_config_var('LIBDIR')
if ldlib:
ldflags += ['-L' + ldlib]
ldlib = sysconfig.get_config_var('VERSION')
if ldlib:
ldflags += ['-lpython' + ldlib + sys.abiflags]
ldflags += (sysconfig.get_config_var('LINKFORSHARED') or '').split()
if ismacos:
cflags.append('-D_OSX')
ldflags.extend('-bundle -undefined dynamic_lookup'.split())
cflags.extend(['-fno-common', '-dynamic'])
cflags.append('-I'+sysconfig.get_python_inc())
cflags.extend('-I' + x for x in get_python_include_paths())
if iswindows:
cc = cxx = win_cc
@ -233,8 +246,8 @@ def init_env(debug=False, sanitize=False):
for p in win_lib:
if p:
ldflags.append('/LIBPATH:'+p)
cflags.append('-I%s'%sysconfig.get_python_inc())
ldflags.append('/LIBPATH:'+os.path.join(sysconfig.PREFIX, 'libs'))
cflags.extend('-I' + x for x in get_python_include_paths())
ldflags.append('/LIBPATH:'+os.path.join(sysconfig.get_config_var('prefix'), 'libs'))
linker = win_ld
return namedtuple('Environment', 'cc cxx cflags ldflags linker make')(
cc=cc, cxx=cxx, cflags=cflags, ldflags=ldflags, linker=linker, make=NMAKE if iswindows else 'make')

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
__license__ = 'GPL v3'

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
# License: GPL v3 Copyright: 2020, Kovid Goyal <kovid at kovidgoyal.net>
from datetime import date

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
__license__ = 'GPL v3'
@ -16,7 +15,19 @@ def __init__(self, filename, lineno, msg):
self.filename, self.lineno, self.msg = filename, lineno, msg
def __str__(self):
return '%s:%s: %s' % (self.filename, self.lineno, self.msg)
return f'{self.filename}:{self.lineno}: {self.msg}'
def checkable_python_files(SRC):
for dname in ('odf', 'calibre'):
for x in os.walk(os.path.join(SRC, dname)):
for f in x[-1]:
y = os.path.join(x[0], f)
if (f.endswith('.py') and f not in (
'dict_data.py', 'unicodepoints.py', 'krcodepoints.py',
'jacodepoints.py', 'vncodepoints.py', 'zhcodepoints.py') and
'prs500/driver.py' not in y) and not f.endswith('_ui.py'):
yield y
class Check(Command):
@ -26,15 +37,7 @@ class Check(Command):
CACHE = 'check.json'
def get_files(self):
for dname in ('odf', 'calibre'):
for x in os.walk(self.j(self.SRC, dname)):
for f in x[-1]:
y = self.j(x[0], f)
if (f.endswith('.py') and f not in (
'dict_data.py', 'unicodepoints.py', 'krcodepoints.py',
'jacodepoints.py', 'vncodepoints.py', 'zhcodepoints.py') and
'prs500/driver.py' not in y) and not f.endswith('_ui.py'):
yield y
yield from checkable_python_files(self.SRC)
for x in os.walk(self.j(self.d(self.SRC), 'recipes')):
for f in x[-1]:
@ -91,7 +94,7 @@ def run(self, opts):
try:
with open(self.cache_file, 'rb') as f:
cache = json.load(f)
except EnvironmentError as err:
except OSError as err:
if err.errno != errno.ENOENT:
raise
dirty_files = tuple(f for f in self.get_files() if not self.is_cache_valid(f, cache))
@ -114,6 +117,24 @@ def report_errors(self, errors):
def clean(self):
try:
os.remove(self.cache_file)
except EnvironmentError as err:
except OSError as err:
if err.errno != errno.ENOENT:
raise
class UpgradeSourceCode(Command):
description = 'Upgrade python source code'
def run(self, opts):
files = []
for f in os.listdir(os.path.dirname(os.path.abspath(__file__))):
q = os.path.join('setup', f)
if f.endswith('.py') and f not in ('linux-installer.py',) and not os.path.isdir(q):
files.append(q)
for path in checkable_python_files(self.SRC):
q = path.replace(os.sep, '/')
if '/metadata/sources/' in q or '/store/stores/' in q:
continue
files.append(q)
subprocess.call(['pyupgrade', '--py37-plus'] + files)

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
__license__ = 'GPL v3'
@ -13,7 +12,7 @@
'git_version',
'develop', 'install',
'kakasi', 'rapydscript', 'cacerts', 'recent_uas', 'resources',
'check', 'test', 'test_rs',
'check', 'test', 'test_rs', 'upgrade_source_code',
'sdist', 'bootstrap', 'extdev',
'manual', 'tag_release',
'upload_to_server',
@ -66,8 +65,9 @@
from setup.gui import GUI
gui = GUI()
from setup.check import Check
from setup.check import Check, UpgradeSourceCode
check = Check()
upgrade_source_code = UpgradeSourceCode()
from setup.test import Test, TestRS
test = Test()

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
# License: GPL v3 Copyright: 2020, Kovid Goyal <kovid at kovidgoyal.net>
import os

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
__license__ = 'GPL v3'

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
__license__ = 'GPL v3'
__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
@ -10,7 +9,7 @@
def get_branch_name(rev):
return subprocess.check_output(['git', 'name-rev', '--name-only', rev]).decode('utf-8').strip()
return subprocess.check_output(['git', 'name-rev', '--name-only', '--refs=refs/heads/*', rev]).decode('utf-8').strip()
base = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
__license__ = 'GPL v3'
__copyright__ = '2014, Kovid Goyal <kovid at kovidgoyal.net>'

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
# License: GPLv3 Copyright: 2008, Kovid Goyal <kovid at kovidgoyal.net>
@ -55,7 +54,7 @@ def __call__(self, match):
print('Working on bug:', summary)
if int(bug) > 100000 and action != 'See':
self.close_bug(bug, action)
return match.group() + ' [%s](%s)' % (summary, LAUNCHPAD_BUG % bug)
return match.group() + f' [{summary}]({LAUNCHPAD_BUG % bug})'
return match.group() + ' (%s)' % summary
return match.group()
@ -66,7 +65,7 @@ def close_bug(self, bug, action):
'calibre is usually released every alternate Friday.'
)
action += 'ed'
msg = '%s in branch %s. %s' % (action, 'master', suffix)
msg = '{} in branch {}. {}'.format(action, 'master', suffix)
msg = msg.replace('Fixesed', 'Fixed')
msg += '\n\n status fixreleased'

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
# License: GPLv3 Copyright: 2019, Eli Schwartz <eschwartz@archlinux.org>

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
__license__ = 'GPL v3'

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
__license__ = 'GPL v3'
__copyright__ = '2011, Kovid Goyal <kovid@kovidgoyal.net>'
@ -150,7 +149,7 @@ def __call__(self):
existing_assets = self.existing_assets(release['id'])
for path, desc in self.files.items():
self.info('')
url = self.API + 'repos/%s/%s/releases/assets/{}' % (
url = self.API + 'repos/{}/{}/releases/assets/{{}}'.format(
self.username, self.reponame
)
fname = os.path.basename(path)
@ -206,7 +205,7 @@ def clean_older_releases(self, releases):
def do_upload(self, url, path, desc, fname):
mime_type = mimetypes.guess_type(fname)[0] or 'application/octet-stream'
self.info('Uploading to GitHub: %s (%s)' % (fname, mime_type))
self.info(f'Uploading to GitHub: {fname} ({mime_type})')
with ReadFileWithProgressReporting(path) as f:
return self.requests.post(
url,
@ -229,7 +228,7 @@ def already_exists(self, r):
return error_code == 'already_exists'
def existing_assets(self, release_id):
url = self.API + 'repos/%s/%s/releases/%s/assets' % (
url = self.API + 'repos/{}/{}/releases/{}/assets'.format(
self.username, self.reponame, release_id
)
r = self.requests.get(url)
@ -238,7 +237,7 @@ def existing_assets(self, release_id):
return {asset['name']: asset['id'] for asset in r.json()}
def releases(self):
url = self.API + 'repos/%s/%s/releases' % (self.username, self.reponame)
url = self.API + f'repos/{self.username}/{self.reponame}/releases'
r = self.requests.get(url)
if r.status_code != 200:
self.fail(r, 'Failed to list releases')
@ -250,7 +249,7 @@ def create_release(self, releases):
# Check for existing release
if release['tag_name'] == self.current_tag_name:
return release
url = self.API + 'repos/%s/%s/releases' % (self.username, self.reponame)
url = self.API + f'repos/{self.username}/{self.reponame}/releases'
r = self.requests.post(
url,
data=json.dumps({
@ -275,7 +274,7 @@ def generate_index(): # {{{
releases = set()
for x in os.listdir('.'):
if os.path.isdir(x) and '.' in x:
releases.add(tuple((int(y) for y in x.split('.'))))
releases.add(tuple(int(y) for y in x.split('.')))
rmap = OrderedDict()
for rnum in sorted(releases, reverse=True):
series = rnum[:2] if rnum[0] == 0 else rnum[:1]
@ -301,10 +300,10 @@ def generate_index(): # {{{
body.append(
'<li><a href="{0}.html" title="Releases in the {0}.x series">{0}.x</a>\xa0\xa0\xa0<span style="font-size:smaller">[{1} releases]</span></li>'
.format( # noqa
'.'.join(map(type(''), series)), len(rmap[series])
'.'.join(map(str, series)), len(rmap[series])
)
)
body = '<ul>{0}</ul>'.format(' '.join(body))
body = '<ul>{}</ul>'.format(' '.join(body))
index = template.format(
title='Previous calibre releases',
style=style,
@ -315,13 +314,13 @@ def generate_index(): # {{{
f.write(index.encode('utf-8'))
for series, releases in rmap.items():
sname = '.'.join(map(type(''), series))
sname = '.'.join(map(str, series))
body = [
'<li><a href="{0}/" title="Release {0}">{0}</a></li>'.format(
'.'.join(map(type(''), r))
'.'.join(map(str, r))
) for r in releases
]
body = '<ul class="release-list">{0}</ul>'.format(' '.join(body))
body = '<ul class="release-list">{}</ul>'.format(' '.join(body))
index = template.format(
title='Previous calibre releases (%s.x)' % sname,
style=style,
@ -332,7 +331,7 @@ def generate_index(): # {{{
f.write(index.encode('utf-8'))
for r in releases:
rname = '.'.join(map(type(''), r))
rname = '.'.join(map(str, r))
os.chdir(rname)
try:
body = []
@ -346,7 +345,7 @@ def generate_index(): # {{{
) for x in windows
]
body.append(
'<dt>Windows</dt><dd><ul>{0}</ul></dd>'.format(
'<dt>Windows</dt><dd><ul>{}</ul></dd>'.format(
' '.join(windows)
)
)
@ -373,7 +372,7 @@ def generate_index(): # {{{
) for x in linux
]
body.append(
'<dt>Linux</dt><dd><ul>{0}</ul></dd>'.format(
'<dt>Linux</dt><dd><ul>{}</ul></dd>'.format(
' '.join(linux)
)
)
@ -384,7 +383,7 @@ def generate_index(): # {{{
.format(source[0], 'Source code (all platforms)')
)
body = '<dl>{0}</dl>'.format(''.join(body))
body = '<dl>{}</dl>'.format(''.join(body))
index = template.format(
title='calibre release (%s)' % rname,
style=style,

View file

@ -1,7 +1,5 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:fdm=marker:ai
# License: GPLv3 Copyright: 2019, Kovid Goyal <kovid at kovidgoyal.net>
from __future__ import absolute_import, division, print_function, unicode_literals
import glob
import hashlib
@ -100,7 +98,7 @@ def run(self, opts):
for dic in dics:
with open(os.path.join(output_dir, dic), 'rb') as f:
m.update(f.read())
hsh = type('')(m.hexdigest())
hsh = str(m.hexdigest())
buf = BytesIO()
with tarfile.TarFile(fileobj=buf, mode='w') as tf:
for dic in dics:

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
# License: GPLv3 Copyright: 2009, Kovid Goyal <kovid at kovidgoyal.net>
@ -155,12 +154,15 @@ def run(self, opts):
self.success()
def install_env_module(self):
import distutils.sysconfig as s
libdir = s.get_python_lib(prefix=self.opts.staging_root)
import sysconfig
libdir = os.path.join(
self.opts.staging_root, sysconfig.get_config_var('PLATLIBDIR') or 'lib',
os.path.basename(sysconfig.get_config_var('DESTLIB') or sysconfig.get_config_var('LIBDEST') or f'python{sysconfig.get_python_version()}'),
'site-packages')
try:
if not os.path.exists(libdir):
os.makedirs(libdir)
except EnvironmentError:
except OSError:
self.warn('Cannot install calibre environment module to: '+libdir)
else:
path = os.path.join(libdir, 'init_calibre.py')
@ -364,7 +366,7 @@ def add_options(self, parser):
def pre_sub_commands(self, opts):
tdir = self.j(self.d(self.SRC), 'translations')
clone_cmd = [
'git', 'clone', 'https://github.com/{}.git'.format(self.TRANSLATIONS_REPO), 'translations']
'git', 'clone', f'https://github.com/{self.TRANSLATIONS_REPO}.git', 'translations']
if opts.ephemeral:
if os.path.exists(tdir):
shutil.rmtree(tdir)

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
# License: GPLv3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
@ -13,7 +12,9 @@
def get_paths():
base = d(d(os.path.abspath(__file__)))
bypy = os.path.join(d(base), 'bypy')
traditional_bypy_location = os.path.join(d(base), 'bypy')
compat_bypy_location = os.path.join(base, 'bypy', 'b', 'bypy-old')
bypy = compat_bypy_location if os.path.exists(compat_bypy_location) else traditional_bypy_location
bypy = os.environ.get('BYPY_LOCATION', bypy)
if not os.path.isdir(bypy):
raise SystemExit(
@ -84,7 +85,7 @@ def build_single(which='windows', bitness='64', shutdown=True, sign_installers=T
dest = os.path.join(base, 'dist', x)
try:
os.remove(dest)
except EnvironmentError:
except OSError:
pass
os.link(src, dest)
if shutdown:
@ -246,9 +247,9 @@ def run(self, opts):
try:
path = path.format(ext)
src = os.path.join(ext_dir, os.path.basename(path))
subprocess.check_call(['ssh', '-S', control_path, host, 'chmod', '+w', '"{}"'.format(path)])
subprocess.check_call(['ssh', '-S', control_path, host, 'chmod', '+w', f'"{path}"'])
with open(src, 'rb') as f:
p = subprocess.Popen(['ssh', '-S', control_path, host, 'cat - > "{}"'.format(path)], stdin=subprocess.PIPE)
p = subprocess.Popen(['ssh', '-S', control_path, host, f'cat - > "{path}"'], stdin=subprocess.PIPE)
p.communicate(f.read())
if p.wait() != 0:
raise SystemExit(1)

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python3
# vim:fileencoding=utf-8
__license__ = 'GPL v3'

View file

@ -1,7 +1,5 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:fdm=marker:ai
# License: GPLv3 Copyright: 2019, Kovid Goyal <kovid at kovidgoyal.net>
from __future__ import absolute_import, division, print_function, unicode_literals
import glob
import os

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:fdm=marker:ai
__license__ = 'GPL v3'

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
__license__ = 'GPL v3'

View file

@ -1,7 +1,5 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
# License: GPLv3 Copyright: 2013, Kovid Goyal <kovid at kovidgoyal.net>
from __future__ import absolute_import, division, print_function, unicode_literals
# Imports {{{
@ -128,7 +126,7 @@ def parse_index(raw=None): # {{{
thread_id = url_to_plugin_id(url, deprecated)
if thread_id in seen:
raise ValueError('thread_id for %s and %s is the same: %s' % (seen[thread_id], name, thread_id))
raise ValueError(f'thread_id for {seen[thread_id]} and {name} is the same: {thread_id}')
seen[thread_id] = name
entry = IndexEntry(name, url, donate, history, uninstall, deprecated, thread_id)
yield entry
@ -147,7 +145,7 @@ def load_plugins_index():
try:
with open(PLUGINS, 'rb') as f:
raw = f.read()
except IOError as err:
except OSError as err:
if err.errno == errno.ENOENT:
return {}
raise
@ -173,13 +171,13 @@ def convert_node(fields, x, names={}, import_data=None):
return dict(zip(keys, values))
elif name == 'Call':
if len(x.args) != 1 and len(x.keywords) != 0:
raise TypeError('Unsupported function call for fields: %s' % (fields,))
raise TypeError(f'Unsupported function call for fields: {fields}')
return tuple(map(conv, x.args))[0]
elif name == 'Name':
if x.id not in names:
if import_data is not None and x.id in import_data[0]:
return get_import_data(x.id, import_data[0][x.id], *import_data[1:])
raise ValueError('Could not find name %s for fields: %s' % (x.id, fields))
raise ValueError(f'Could not find name {x.id} for fields: {fields}')
return names[x.id]
elif name == 'BinOp':
if x.right.__class__.__name__ == 'Str':
@ -188,7 +186,7 @@ def convert_node(fields, x, names={}, import_data=None):
return x.right.value
elif name == 'Attribute':
return conv(getattr(conv(x.value), x.attr))
raise TypeError('Unknown datatype %s for fields: %s' % (x, fields))
raise TypeError(f'Unknown datatype {x} for fields: {fields}')
Alias = namedtuple('Alias', 'name asname')
@ -221,7 +219,7 @@ def get_import_data(name, mod, zf, names):
return convert_node({x}, node.value)
if is_module_import:
return module
raise ValueError('Failed to find name: %r in module: %r' % (name, mod))
raise ValueError(f'Failed to find name: {name!r} in module: {mod!r}')
else:
raise ValueError('Failed to find module: %r' % mod)
@ -457,7 +455,7 @@ def fetch_plugins(old_index):
def plugin_to_index(plugin, count):
title = '<h3><img src="plugin-icon.png"><a href=%s title="Plugin forum thread">%s</a></h3>' % ( # noqa
title = '<h3><img src="plugin-icon.png"><a href={} title="Plugin forum thread">{}</a></h3>'.format( # noqa
quoteattr(plugin['thread_url']), escape(plugin['name']))
released = datetime(*tuple(map(int, re.split(r'\D', plugin['last_modified'])))[:6]).strftime('%e %b, %Y').lstrip()
details = [
@ -478,12 +476,12 @@ def plugin_to_index(plugin, count):
block.append('<li>%s</li>' % li)
block = '<ul>%s</ul>' % ('\n'.join(block))
downloads = ('\xa0<span class="download-count">[%d total downloads]</span>' % count) if count else ''
zipfile = '<div class="end"><a href=%s title="Download plugin" download=%s>Download plugin \u2193</a>%s</div>' % (
zipfile = '<div class="end"><a href={} title="Download plugin" download={}>Download plugin \u2193</a>{}</div>'.format(
quoteattr(plugin['file']), quoteattr(plugin['name'] + '.zip'), downloads)
desc = plugin['description'] or ''
if desc:
desc = '<p>%s</p>' % desc
return '%s\n%s\n%s\n%s\n\n' % (title, desc, block, zipfile)
return f'{title}\n{desc}\n{block}\n{zipfile}\n\n'
def create_index(index, raw_stats):
@ -526,14 +524,14 @@ def create_index(index, raw_stats):
try:
with open('index.html', 'rb') as f:
oraw = f.read()
except EnvironmentError:
except OSError:
oraw = None
if raw != oraw:
atomic_write(raw, 'index.html')
def plugin_stats(x):
name, count = x
return '<tr><td>%s</td><td>%s</td></tr>\n' % (escape(name), count)
return f'<tr><td>{escape(name)}</td><td>{count}</td></tr>\n'
pstats = list(map(plugin_stats, sorted(stats.items(), reverse=True, key=lambda x:x[1])))
stats = '''\
@ -560,7 +558,7 @@ def plugin_stats(x):
try:
with open('stats.html', 'rb') as f:
oraw = f.read()
except EnvironmentError:
except OSError:
oraw = None
if raw != oraw:
atomic_write(raw, 'stats.html')
@ -574,7 +572,7 @@ def singleinstance():
s = _singleinstance = socket.socket(socket.AF_UNIX)
try:
s.bind(b'\0calibre-plugins-mirror-singleinstance')
except socket.error as err:
except OSError as err:
if getattr(err, 'errno', None) == errno.EADDRINUSE:
return False
raise
@ -590,7 +588,7 @@ def update_stats():
try:
with open('stats.json', 'rb') as f:
stats = json.load(f)
except EnvironmentError as err:
except OSError as err:
if err.errno != errno.ENOENT:
raise
if os.geteuid() != 0:
@ -688,7 +686,7 @@ def test_parse(): # {{{
new_entries = tuple(parse_index(raw))
for i, entry in enumerate(old_entries):
if entry != new_entries[i]:
print('The new entry: %s != %s' % (new_entries[i], entry))
print(f'The new entry: {new_entries[i]} != {entry}')
raise SystemExit(1)
pool = ThreadPool(processes=20)
urls = [e.url for e in new_entries]
@ -705,7 +703,7 @@ def test_parse(): # {{{
break
new_url, aname = parse_plugin_zip_url(raw)
if new_url != full_url:
print('new url (%s): %s != %s for plugin at: %s' % (aname, new_url, full_url, url))
print(f'new url ({aname}): {new_url} != {full_url} for plugin at: {url}')
raise SystemExit(1)
# }}}

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
__license__ = 'GPL v3'
@ -225,7 +224,7 @@ def replace_with_symlinks(self, lang_dir):
orig = self.j(self.d(base), r)
try:
sz = os.stat(orig).st_size
except EnvironmentError:
except OSError:
continue
if sz == os.stat(f).st_size and filecmp._do_cmp(f, orig):
os.remove(f)
@ -260,7 +259,7 @@ def build_man_pages(self, dest, compress=False):
os.environ['ALL_USER_MANUAL_LANGUAGES'] = ' '.join(languages)
try:
os.makedirs(dest)
except EnvironmentError:
except OSError:
pass
jobs = []
for l in languages:
@ -268,7 +267,7 @@ def build_man_pages(self, dest, compress=False):
[sys.executable, self.j(base, 'build.py'), '--man-pages', l, dest],
'\n\n**************** Building translations for: %s' % l)
)
self.info('\tCreating man pages in {} for {} languages...'.format(dest, len(jobs)))
self.info(f'\tCreating man pages in {dest} for {len(jobs)} languages...')
subprocess.check_call(jobs[0].cmd)
if not parallel_build(jobs[1:], self.info, verbose=False):
raise SystemExit(1)
@ -307,4 +306,4 @@ def run(self, opts):
subprocess.check_call(
'git tag -s v{0} -m "version-{0}"'.format(__version__).split()
)
subprocess.check_call('git push origin v{0}'.format(__version__).split())
subprocess.check_call(f'git push origin v{__version__}'.split())

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
__license__ = 'GPL v3'
@ -16,17 +15,13 @@
def get_opts_from_parser(parser):
def do_opt(opt):
for x in opt._long_opts:
yield x
for x in opt._short_opts:
yield x
yield from opt._long_opts
yield from opt._short_opts
for o in parser.option_list:
for x in do_opt(o):
yield x
yield from do_opt(o)
for g in parser.option_groups:
for o in g.option_list:
for x in do_opt(o):
yield x
yield from do_opt(o)
class Kakasi(Command): # {{{
@ -145,7 +140,7 @@ def run(self, opts):
try:
with open(self.CA_PATH, 'rb') as f:
raw = f.read()
except EnvironmentError as err:
except OSError as err:
if err.errno != errno.ENOENT:
raise
raw = b''
@ -298,7 +293,7 @@ def run(self, opts):
except Exception:
continue
src = src.replace('def ' + func.__name__, 'def replace')
imports = ['from %s import %s' % (x.__module__, x.__name__) for x in func.imports]
imports = [f'from {x.__module__} import {x.__name__}' for x in func.imports]
if imports:
src = '\n'.join(imports) + '\n\n' + src
function_dict[func.name] = src

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
# License: GPL v3 Copyright: 2019, Eli Schwartz <eschwartz@archlinux.org>
import os

View file

@ -1,5 +1,4 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
# License: GPLv3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>

Some files were not shown because too many files have changed in this diff Show more