jenkins-bot has submitted this change and it was merged. (
https://gerrit.wikimedia.org/r/565784 )
Change subject: [bugfix] Remove isbn library of isbn.py in favour of stdnum
......................................................................
[bugfix] Remove isbn library of isbn.py in favour of stdnum
ISBN range of isbn.py is very outdated and updating it was declined
in favour of using python-stdnum.
isbn.py:
- remove outdated ISBN ranges
- remove ISBN classes and subclasses; this library part has been
dropped in favour of python-stdnum package
- remove getIsbn function which is not used anymore; any call
to the intrinsic isbn library is replaced by a NotImplementedError
exception
- combine multiple exceptions in is_valid function
- use suggest_help to show missing depedencies if isbn packages
aren't installed
cosmetic_changes.py:
- don't attemp to use isbn.py methods; raise NotImplementesError
instead if python-stdnum is not installed
- call fix_ISBN if this library is available; otherwise skip it
isbn_tests.py:
- skip all tests if isbn libraries aren't installed
- remove ISBN10/ISBN13 tests because these classes has been removed
- use wikipedia family instead of test family because test family
is deprecated
Bug: T132919
Bug: T144288
Bug: T241141
Change-Id: Ib68d0c6898088425bad96c7ccfd4187dfd4bbdbf
---
M pywikibot/cosmetic_changes.py
M scripts/isbn.py
M tests/isbn_tests.py
3 files changed, 55 insertions(+), 1,451 deletions(-)
Approvals:
Dvorapa: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/cosmetic_changes.py b/pywikibot/cosmetic_changes.py
index 90847d1..051b06f 100755
--- a/pywikibot/cosmetic_changes.py
+++ b/pywikibot/cosmetic_changes.py
@@ -52,8 +52,8 @@
'your_script_name_2']
"""
#
-# (C) xqt, 2009-2018
-# (C) Pywikibot team, 2006-2019
+# (C) xqt, 2009-2020
+# (C) Pywikibot team, 2006-2020
#
# Distributed under the terms of the MIT license.
#
@@ -61,8 +61,6 @@
import re
-from warnings import warn
-
try:
import stdnum.isbn as stdnum_isbn
except ImportError:
@@ -170,48 +168,20 @@
def _format_isbn_match(match, strict=True):
"""Helper function to validate and format a single matched
ISBN."""
- scripts_isbn = None
-
if not stdnum_isbn:
- # For backwards compatibility, if stdnum.isbn is not available
- # attempt loading scripts.isbn as an alternative implementation.
- try:
- import scripts.isbn as scripts_isbn
- except ImportError:
- raise NotImplementedError(
- 'ISBN functionality not available. Install stdnum package.')
-
- warn('package stdnum.isbn not found; using scripts.isbn',
- ImportWarning)
+ raise NotImplementedError(
+ 'ISBN functionality not available. Install stdnum package.')
isbn = match.group('code')
- if stdnum_isbn:
- try:
- stdnum_isbn.validate(isbn)
- except stdnum_isbn.ValidationError as e:
- if strict:
- raise
- pywikibot.log('ISBN "%s" validation error: %s' % (isbn,
e))
- return isbn
+ try:
+ stdnum_isbn.validate(isbn)
+ except stdnum_isbn.ValidationError as e:
+ if strict:
+ raise
+ pywikibot.log('ISBN "%s" validation error: %s' % (isbn, e))
+ return isbn
- return stdnum_isbn.format(isbn)
- else:
- try:
- scripts_isbn.is_valid(isbn)
- except scripts_isbn.InvalidIsbnException as e:
- if strict:
- raise
- pywikibot.log('ISBN "%s" validation error: %s' % (isbn,
e))
- return isbn
-
- isbn = scripts_isbn.getIsbn(isbn)
- try:
- isbn.format()
- except scripts_isbn.InvalidIsbnException as e:
- if strict:
- raise
- pywikibot.log('ISBN "%s" validation error: %s' % (isbn,
e))
- return isbn.code
+ return stdnum_isbn.format(isbn)
def _reformat_ISBNs(text, strict=True):
@@ -243,7 +213,7 @@
self.title = pageTitle
self.ignore = ignore
- self.common_methods = (
+ self.common_methods = [
self.commonsfiledesc,
self.fixSelfInterwiki,
self.standardizePageFooter,
@@ -265,9 +235,9 @@
self.fixTypo,
self.fixArabicLetters,
- # FIXME: T144288
- # self.fix_ISBN,
- )
+ ]
+ if stdnum_isbn:
+ self.common_methods.append(self.fix_ISBN)
@classmethod
def from_page(cls, page, diff, ignore):
diff --git a/scripts/isbn.py b/scripts/isbn.py
index 223aad1..429574c 100755
--- a/scripts/isbn.py
+++ b/scripts/isbn.py
@@ -47,6 +47,7 @@
import pywikibot
from pywikibot import i18n, pagegenerators, textlib, Bot, WikidataBot
+from pywikibot.tools import has_module
try:
import stdnum.isbn
@@ -60,1298 +61,12 @@
'¶ms;': pagegenerators.parameterHelp,
}
-# Maps each group number to the list of its publisher number ranges. Source:
-#
https://web.archive.org/web/20090823122028/http://www.isbn-international.or…
-ranges = {
- '0': [ # English speaking area
- ('00', '19'),
- ('200', '699'),
- ('7000', '8499'),
- ('85000', '89999'),
- ('900000', '949999'),
- ('9500000', '9999999'),
- ],
- '1': [ # English speaking area
- ('00', '09'),
- ('100', '399'),
- ('4000', '5499'),
- ('55000', '86979'),
- ('869800', '998999'),
- ],
- '2': [ # French speaking area
- ('00', '19'),
- ('200', '349'),
- ('35000', '39999'),
- ('400', '699'),
- ('7000', '8399'),
- ('84000', '89999'),
- ('900000', '949999'),
- ('9500000', '9999999'),
- ],
- '3': [ # German speaking area
- ('00', '02'),
- ('030', '033'),
- ('0340', '0369'),
- ('03700', '03999'),
- ('04', '19'),
- ('200', '699'),
- ('7000', '8499'),
- ('85000', '89999'),
- ('900000', '949999'),
- ('9500000', '9999999'),
- ],
- '4': [ # Japan
- ('00', '19'),
- ('200', '699'),
- ('7000', '8499'),
- ('85000', '89999'),
- ('900000', '949999'),
- ('9500000', '9999999'),
- ],
- '5': [ # Russian Federation
- ('00', '19'),
- ('200', '699'),
- ('7000', '8499'),
- ('85000', '89999'),
- ('900000', '909999'),
- ('91000', '91999'),
- ('9200', '9299'),
- ('93000', '94999'),
- ('9500', '9799'),
- ('98000', '98999'),
- ('9900000', '9909999'),
- ('9910', '9999'),
- ],
- '600': [ # Iran
- ('00', '09'),
- ('100', '499'),
- ('5000', '8999'),
- ('90000', '99999'),
- ],
- '601': [ # Kazakhstan
- ('00', '19'),
- ('200', '699'),
- ('7000', '7999'),
- ('80000', '84999'),
- ('85', '99'),
- ],
- '602': [ # Indonesia
- ('00', '19'),
- ('200', '799'),
- ('8000', '9499'),
- ('95000', '99999'),
- ],
- '603': [ # Saudi Arabia
- ('00', '04'),
- ('500', '799'),
- ('8000', '8999'),
- ('90000', '99999'),
- ],
- '604': [ # Vietnam
- ('0', '4'),
- ('50', '89'),
- ('900', '979'),
- ('9800', '9999'),
- ],
- '605': [ # Turkey
- ('00', '09'),
- ('100', '399'),
- ('4000', '5999'),
- ('60000', '89999'),
- ],
- '7': [ # China, People's Republic
- ('00', '09'),
- ('100', '499'),
- ('5000', '7999'),
- ('80000', '89999'),
- ('900000', '999999'),
- ],
- '80': [ # Czech Republic; Slovakia
- ('00', '19'),
- ('200', '699'),
- ('7000', '8499'),
- ('85000', '89999'),
- ('900000', '999999'),
- ],
- '81': [ # India
- ('00', '19'),
- ('200', '699'),
- ('7000', '8499'),
- ('85000', '89999'),
- ('900000', '999999'),
- ],
- '82': [ # Norway
- ('00', '19'),
- ('200', '699'),
- ('7000', '8999'),
- ('90000', '98999'),
- ('990000', '999999'),
- ],
- '83': [ # Poland
- ('00', '19'),
- ('200', '599'),
- ('60000', '69999'),
- ('7000', '8499'),
- ('85000', '89999'),
- ('900000', '999999'),
- ],
- '84': [ # Spain
- ('00', '19'),
- ('200', '699'),
- ('7000', '8499'),
- ('85000', '89999'),
- ('9000', '9199'),
- ('920000', '923999'),
- ('92400', '92999'),
- ('930000', '949999'),
- ('95000', '96999'),
- ('9700', '9999'),
- ],
- '85': [ # Brazil
- ('00', '19'),
- ('200', '599'),
- ('60000', '69999'),
- ('7000', '8499'),
- ('85000', '89999'),
- ('900000', '979999'),
- ('98000', '99999'),
- ],
- '86': [ # Serbia and Montenegro
- ('00', '29'),
- ('300', '599'),
- ('6000', '7999'),
- ('80000', '89999'),
- ('900000', '999999'),
- ],
- '87': [ # Denmark
- ('00', '29'),
- ('400', '649'),
- ('7000', '7999'),
- ('85000', '94999'),
- ('970000', '999999'),
- ],
- '88': [ # Italian speaking area
- ('00', '19'),
- ('200', '599'),
- ('6000', '8499'),
- ('85000', '89999'),
- ('900000', '949999'),
- ('95000', '99999'),
- ],
- '89': [ # Korea
- ('00', '24'),
- ('250', '549'),
- ('5500', '8499'),
- ('85000', '94999'),
- ('950000', '999999'),
- ],
- '90': [ # Netherlands, Belgium (Flemish)
- ('00', '19'),
- ('200', '499'),
- ('5000', '6999'),
- ('70000', '79999'),
- ('800000', '849999'),
- ('8500', '8999'),
- ('900000', '909999'),
- ('940000', '949999'),
- ],
- '91': [ # Sweden
- ('0', '1'),
- ('20', '49'),
- ('500', '649'),
- ('7000', '7999'),
- ('85000', '94999'),
- ('970000', '999999'),
- ],
- # International Publishers (Unesco, EU), European Community Organizations
- '92': [
- ('0', '5'),
- ('60', '79'),
- ('800', '899'),
- ('9000', '9499'),
- ('95000', '98999'),
- ('990000', '999999'),
- ],
- '93': [ # India - no ranges fixed yet
- ],
- '950': [ # Argentina
- ('00', '49'),
- ('500', '899'),
- ('9000', '9899'),
- ('99000', '99999'),
- ],
- '951': [ # Finland
- ('0', '1'),
- ('20', '54'),
- ('550', '889'),
- ('8900', '9499'),
- ('95000', '99999'),
- ],
- '952': [ # Finland
- ('00', '19'),
- ('200', '499'),
- ('5000', '5999'),
- ('60', '65'),
- ('6600', '6699'),
- ('67000', '69999'),
- ('7000', '7999'),
- ('80', '94'),
- ('9500', '9899'),
- ('99000', '99999'),
- ],
- '953': [ # Croatia
- ('0', '0'),
- ('10', '14'),
- ('150', '549'),
- ('55000', '59999'),
- ('6000', '9499'),
- ('95000', '99999'),
- ],
- '954': [ # Bulgaria
- ('00', '29'),
- ('300', '799'),
- ('8000', '8999'),
- ('90000', '92999'),
- ('9300', '9999'),
- ],
- '955': [ # Sri Lanka
- ('0', '0'),
- ('1000', '1999'),
- ('20', '54'),
- ('550', '799'),
- ('8000', '9499'),
- ('95000', '99999'),
- ],
- '956': [ # Chile
- ('00', '19'),
- ('200', '699'),
- ('7000', '9999'),
- ],
- '957': [ # Taiwan, China
- ('00', '02'),
- ('0300', '0499'),
- ('05', '19'),
- ('2000', '2099'),
- ('21', '27'),
- ('28000', '30999'),
- ('31', '43'),
- ('440', '819'),
- ('8200', '9699'),
- ('97000', '99999'),
- ],
- '958': [ # Colombia
- ('00', '59'),
- ('600', '799'),
- ('8000', '9499'),
- ('95000', '99999'),
- ],
- '959': [ # Cuba
- ('00', '19'),
- ('200', '699'),
- ('7000', '8499'),
- ],
- '960': [ # Greece
- ('00', '19'),
- ('200', '659'),
- ('6600', '6899'),
- ('690', '699'),
- ('7000', '8499'),
- ('85000', '99999'),
- ],
- '961': [ # Slovenia
- ('00', '19'),
- ('200', '599'),
- ('6000', '8999'),
- ('90000', '94999'),
- ],
- '962': [ # Hong Kong
- ('00', '19'),
- ('200', '699'),
- ('7000', '8499'),
- ('85000', '86999'),
- ('8700', '8999'),
- ('900', '999'),
- ],
- '963': [ # Hungary
- ('00', '19'),
- ('200', '699'),
- ('7000', '8499'),
- ('85000', '89999'),
- ('9000', '9999'),
- ],
- '964': [ # Iran
- ('00', '14'),
- ('150', '249'),
- ('2500', '2999'),
- ('300', '549'),
- ('5500', '8999'),
- ('90000', '96999'),
- ('970', '989'),
- ('9900', '9999'),
- ],
- '965': [ # Israel
- ('00', '19'),
- ('200', '599'),
- ('7000', '7999'),
- ('90000', '99999'),
- ],
- '966': [ # Ukraine
- ('00', '19'),
- ('2000', '2999'),
- ('300', '699'),
- ('7000', '8999'),
- ('90000', '99999'),
- ],
- '967': [ # Malaysia
- ('00', '29'),
- ('300', '499'),
- ('5000', '5999'),
- ('60', '89'),
- ('900', '989'),
- ('9900', '9989'),
- ('99900', '99999'),
- ],
- '968': [ # Mexico
- ('01', '39'),
- ('400', '499'),
- ('5000', '7999'),
- ('800', '899'),
- ('9000', '9999'),
- ],
- '969': [ # Pakistan
- ('0', '1'),
- ('20', '39'),
- ('400', '799'),
- ('8000', '9999'),
- ],
- '970': [ # Mexico
- ('01', '59'),
- ('600', '899'),
- ('9000', '9099'),
- ('91000', '96999'),
- ('9700', '9999'),
- ],
- '971': [ # Philippines?
- ('000', '019'),
- ('02', '02'),
- ('0300', '0599'),
- ('06', '09'),
- ('10', '49'),
- ('500', '849'),
- ('8500', '9099'),
- ('91000', '99999'),
- ],
- '972': [ # Portugal
- ('0', '1'),
- ('20', '54'),
- ('550', '799'),
- ('8000', '9499'),
- ('95000', '99999'),
- ],
- '973': [ # Romania
- ('0', '0'),
- ('100', '169'),
- ('1700', '1999'),
- ('20', '54'),
- ('550', '759'),
- ('7600', '8499'),
- ('85000', '88999'),
- ('8900', '9499'),
- ('95000', '99999'),
- ],
- '974': [ # Thailand
- ('00', '19'),
- ('200', '699'),
- ('7000', '8499'),
- ('85000', '89999'),
- ('90000', '94999'),
- ('9500', '9999'),
- ],
- '975': [ # Turkey
- ('00000', '00999'),
- ('01', '24'),
- ('250', '599'),
- ('6000', '9199'),
- ('92000', '98999'),
- ('990', '999'),
- ],
- '976': [ # Caribbean Community
- ('0', '3'),
- ('40', '59'),
- ('600', '799'),
- ('8000', '9499'),
- ('95000', '99999'),
- ],
- '977': [ # Egypt
- ('00', '19'),
- ('200', '499'),
- ('5000', '6999'),
- ('700', '999'),
- ],
- '978': [ # Nigeria
- ('000', '199'),
- ('2000', '2999'),
- ('30000', '79999'),
- ('8000', '8999'),
- ('900', '999'),
- ],
- '979': [ # Indonesia
- ('000', '099'),
- ('1000', '1499'),
- ('15000', '19999'),
- ('20', '29'),
- ('3000', '3999'),
- ('400', '799'),
- ('8000', '9499'),
- ('95000', '99999'),
- ],
- '980': [ # Venezuela
- ('00', '19'),
- ('200', '599'),
- ('6000', '9999'),
- ],
- '981': [ # Singapore
- ('00', '19'),
- ('200', '299'),
- ('3000', '9999'),
- ],
- '982': [ # South Pacific
- ('00', '09'),
- ('100', '699'),
- ('70', '89'),
- ('9000', '9999'),
- ],
- '983': [ # Malaysia
- ('00', '01'),
- ('020', '199'),
- ('2000', '3999'),
- ('40000', '44999'),
- ('45', '49'),
- ('50', '79'),
- ('800', '899'),
- ('9000', '9899'),
- ('99000', '99999'),
- ],
- '984': [ # Bangladesh
- ('00', '39'),
- ('400', '799'),
- ('8000', '8999'),
- ('90000', '99999'),
- ],
- '985': [ # Belarus
- ('00', '39'),
- ('400', '599'),
- ('6000', '8999'),
- ('90000', '99999'),
- ],
- '986': [ # Taiwan, China
- ('00', '11'),
- ('120', '559'),
- ('5600', '7999'),
- ('80000', '99999'),
- ],
- '987': [ # Argentina
- ('00', '09'),
- ('1000', '1999'),
- ('20000', '29999'),
- ('30', '49'),
- ('500', '899'),
- ('9000', '9499'),
- ('95000', '99999'),
- ],
- '988': [ # Hongkong
- ('00', '16'),
- ('17000', '19999'),
- ('200', '799'),
- ('8000', '9699'),
- ('97000', '99999'),
- ],
- '989': [ # Portugal
- ('0', '1'),
- ('20', '54'),
- ('550', '799'),
- ('8000', '9499'),
- ('95000', '99999'),
- ],
- '9937': [ # Nepal
- ('0', '2'),
- ('30', '49'),
- ('500', '799'),
- ('8000', '9999'),
- ],
- '9938': [ # Tunisia
- ('00', '79'),
- ('800', '949'),
- ('9500', '9999'),
- ],
- '9939': [ # Armenia
- ('0', '4'),
- ('50', '79'),
- ('800', '899'),
- ('9000', '9999'),
- ],
- '9940': [ # Montenegro
- ('0', '1'),
- ('20', '49'),
- ('500', '899'),
- ('9000', '9999'),
- ],
- '9941': [ # Georgia
- ('0', '0'),
- ('10', '39'),
- ('400', '899'),
- ('9000', '9999'),
- ],
- '9942': [ # Ecuador
- ('00', '89'),
- ('900', '994'),
- ('9950', '9999'),
- ],
- '9943': [ # Uzbekistan
- ('00', '29'),
- ('300', '399'),
- ('4000', '9999'),
- ],
- '9944': [ # Turkey
- ('0', '2'),
- ('300', '499'),
- ('5000', '5999'),
- ('60', '89'),
- ('900', '999'),
- ],
- '9945': [ # Dominican Republic
- ('00', '00'),
- ('010', '079'),
- ('08', '39'),
- ('400', '569'),
- ('57', '57'),
- ('580', '849'),
- ('8500', '9999'),
- ],
- '9946': [ # Korea, P.D.R.
- ('0', '1'),
- ('20', '39'),
- ('400', '899'),
- ('9000', '9999'),
- ],
- '9947': [ # Algeria
- ('0', '1'),
- ('20', '79'),
- ('800', '999'),
- ],
- '9948': [ # United Arab Emirates
- ('00', '39'),
- ('400', '849'),
- ('8500', '9999'),
- ],
- '9949': [ # Estonia
- ('0', '0'),
- ('10', '39'),
- ('400', '899'),
- ('9000', '9999'),
- ],
- '9950': [ # Palestine
- ('00', '29'),
- ('300', '840'),
- ('8500', '9999'),
- ],
- '9951': [ # Kosova
- ('00', '39'),
- ('400', '849'),
- ('8500', '9999'),
- ],
- '9952': [ # Azerbaijan
- ('0', '1'),
- ('20', '39'),
- ('400', '799'),
- ('8000', '9999'),
- ],
- '9953': [ # Lebanon
- ('0', '0'),
- ('10', '39'),
- ('400', '599'),
- ('60', '89'),
- ('9000', '9999'),
- ],
- '9954': [ # Morocco
- ('0', '1'),
- ('20', '39'),
- ('400', '799'),
- ('8000', '9999'),
- ],
- '9955': [ # Lithuania
- ('00', '39'),
- ('400', '929'),
- ('9300', '9999'),
- ],
- '9956': [ # Cameroon
- ('0', '0'),
- ('10', '39'),
- ('400', '899'),
- ('9000', '9999'),
- ],
- '9957': [ # Jordan
- ('00', '39'),
- ('400', '699'),
- ('70', '84'),
- ('8500', '9999'),
- ],
- '9958': [ # Bosnia and Herzegovina
- ('0', '0'),
- ('10', '49'),
- ('500', '899'),
- ('9000', '9999'),
- ],
- '9959': [ # Libya
- ('0', '1'),
- ('20', '79'),
- ('800', '949'),
- ('9500', '9999'),
- ],
- '9960': [ # Saudi Arabia
- ('00', '59'),
- ('600', '899'),
- ('9000', '9999'),
- ],
- '9961': [ # Algeria
- ('0', '2'),
- ('30', '69'),
- ('700', '949'),
- ('9500', '9999'),
- ],
- '9962': [ # Panama
- ('00', '54'),
- ('5500', '5599'),
- ('56', '59'),
- ('600', '849'),
- ('8500', '9999'),
- ],
- '9963': [ # Cyprus
- ('0', '2'),
- ('30', '54'),
- ('550', '749'),
- ('7500', '9999'),
- ],
- '9964': [ # Ghana
- ('0', '6'),
- ('70', '94'),
- ('950', '999'),
- ],
- '9965': [ # Kazakhstan
- ('00', '39'),
- ('400', '899'),
- ('9000', '9999'),
- ],
- '9966': [ # Kenya
- ('00', '69'),
- ('7000', '7499'),
- ('750', '959'),
- ('9600', '9999'),
- ],
- '9967': [ # Kyrgyzstan
- ('00', '39'),
- ('400', '899'),
- ('9000', '9999'),
- ],
- '9968': [ # Costa Rica
- ('00', '49'),
- ('500', '939'),
- ('9400', '9999'),
- ],
- '9970': [ # Uganda
- ('00', '39'),
- ('400', '899'),
- ('9000', '9999'),
- ],
- '9971': [ # Singapore
- ('0', '5'),
- ('60', '89'),
- ('900', '989'),
- ('9900', '9999'),
- ],
- '9972': [ # Peru
- ('00', '09'),
- ('1', '1'),
- ('200', '249'),
- ('2500', '2999'),
- ('30', '59'),
- ('600', '899'),
- ('9000', '9999'),
- ],
- '9973': [ # Tunisia
- ('0', '05'),
- ('060', '089'),
- ('0900', '0999'),
- ('10', '69'),
- ('700', '969'),
- ('9700', '9999'),
- ],
- '9974': [ # Uruguay
- ('0', '2'),
- ('30', '54'),
- ('550', '749'),
- ('7500', '9499'),
- ('95', '99'),
- ],
- '9975': [ # Moldova
- ('0', '0'),
- ('100', '399'),
- ('4000', '4499'),
- ('45', '89'),
- ('900', '949'),
- ('9500', '9999'),
- ],
- '9976': [ # Tanzania
- ('0', '5'),
- ('60', '89'),
- ('900', '989'),
- ('9990', '9999'),
- ],
- '9977': [ # Costa Rica
- ('00', '89'),
- ('900', '989'),
- ('9900', '9999'),
- ],
- '9978': [ # Ecuador
- ('00', '29'),
- ('300', '399'),
- ('40', '94'),
- ('950', '989'),
- ('9900', '9999'),
- ],
- '9979': [ # Iceland
- ('0', '4'),
- ('50', '64'),
- ('650', '659'),
- ('66', '75'),
- ('760', '899'),
- ('9000', '9999'),
- ],
- '9980': [ # Papua New Guinea
- ('0', '3'),
- ('40', '89'),
- ('900', '989'),
- ('9900', '9999'),
- ],
- '9981': [ # Morocco
- ('00', '09'),
- ('100', '159'),
- ('1600', '1999'),
- ('20', '79'),
- ('800', '949'),
- ('9500', '9999'),
- ],
- '9982': [ # Zambia
- ('00', '79'),
- ('800', '989'),
- ('9900', '9999'),
- ],
- '9983': [ # Gambia
- ('80', '94'),
- ('950', '989'),
- ('9900', '9999'),
- ],
- '9984': [ # Latvia
- ('00', '49'),
- ('500', '899'),
- ('9000', '9999'),
- ],
- '9985': [ # Estonia
- ('0', '4'),
- ('50', '79'),
- ('800', '899'),
- ('9000', '9999'),
- ],
- '9986': [ # Lithuania
- ('00', '39'),
- ('400', '899'),
- ('9000', '9399'),
- ('940', '969'),
- ('97', '99'),
- ],
- '9987': [ # Tanzania
- ('00', '39'),
- ('400', '879'),
- ('8800', '9999'),
- ],
- '9988': [ # Ghana
- ('0', '2'),
- ('30', '54'),
- ('550', '749'),
- ('7500', '9999'),
- ],
- '9989': [ # Macedonia
- ('0', '0'),
- ('100', '199'),
- ('2000', '2999'),
- ('30', '59'),
- ('600', '949'),
- ('9500', '9999'),
- ],
- '99901': [ # Bahrain
- ('00', '49'),
- ('500', '799'),
- ('80', '99'),
- ],
- '99902': [ # Gabon - no ranges fixed yet
- ],
- '99903': [ # Mauritius
- ('0', '1'),
- ('20', '89'),
- ('900', '999'),
- ],
- '99904': [ # Netherlands Antilles; Aruba, Neth. Ant
- ('0', '5'),
- ('60', '89'),
- ('900', '999'),
- ],
- '99905': [ # Bolivia
- ('0', '3'),
- ('40', '79'),
- ('800', '999'),
- ],
- '99906': [ # Kuwait
- ('0', '2'),
- ('30', '59'),
- ('600', '699'),
- ('70', '89'),
- ('9', '9'),
- ],
- '99908': [ # Malawi
- ('0', '0'),
- ('10', '89'),
- ('900', '999'),
- ],
- '99909': [ # Malta
- ('0', '3'),
- ('40', '94'),
- ('950', '999'),
- ],
- '99910': [ # Sierra Leone
- ('0', '2'),
- ('30', '89'),
- ('900', '999'),
- ],
- '99911': [ # Lesotho
- ('00', '59'),
- ('600', '999'),
- ],
- '99912': [ # Botswana
- ('0', '3'),
- ('400', '599'),
- ('60', '89'),
- ('900', '999'),
- ],
- '99913': [ # Andorra
- ('0', '2'),
- ('30', '35'),
- ('600', '604'),
- ],
- '99914': [ # Suriname
- ('0', '4'),
- ('50', '89'),
- ('900', '949'),
- ],
- '99915': [ # Maldives
- ('0', '4'),
- ('50', '79'),
- ('800', '999'),
- ],
- '99916': [ # Namibia
- ('0', '2'),
- ('30', '69'),
- ('700', '999'),
- ],
- '99917': [ # Brunei Darussalam
- ('0', '2'),
- ('30', '89'),
- ('900', '999'),
- ],
- '99918': [ # Faroe Islands
- ('0', '3'),
- ('40', '79'),
- ('800', '999'),
- ],
- '99919': [ # Benin
- ('0', '2'),
- ('40', '69'),
- ('900', '999'),
- ],
- '99920': [ # Andorra
- ('0', '4'),
- ('50', '89'),
- ('900', '999'),
- ],
- '99921': [ # Qatar
- ('0', '1'),
- ('20', '69'),
- ('700', '799'),
- ('8', '8'),
- ('90', '99'),
- ],
- '99922': [ # Guatemala
- ('0', '3'),
- ('40', '69'),
- ('700', '999'),
- ],
- '99923': [ # El Salvador
- ('0', '1'),
- ('20', '79'),
- ('800', '999'),
- ],
- '99924': [ # Nicaragua
- ('0', '2'),
- ('30', '79'),
- ('800', '999'),
- ],
- '99925': [ # Paraguay
- ('0', '3'),
- ('40', '79'),
- ('800', '999'),
- ],
- '99926': [ # Honduras
- ('0', '0'),
- ('10', '59'),
- ('600', '999'),
- ],
- '99927': [ # Albania
- ('0', '2'),
- ('30', '59'),
- ('600', '999'),
- ],
- '99928': [ # Georgia
- ('0', '0'),
- ('10', '79'),
- ('800', '999'),
- ],
- '99929': [ # Mongolia
- ('0', '4'),
- ('50', '79'),
- ('800', '999'),
- ],
- '99930': [ # Armenia
- ('0', '4'),
- ('50', '79'),
- ('800', '999'),
- ],
- '99931': [ # Seychelles
- ('0', '4'),
- ('50', '79'),
- ('800', '999'),
- ],
- '99932': [ # Malta
- ('0', '0'),
- ('10', '59'),
- ('600', '699'),
- ('7', '7'),
- ('80', '99'),
- ],
- '99933': [ # Nepal
- ('0', '2'),
- ('30', '59'),
- ('600', '999'),
- ],
- '99934': [ # Dominican Republic
- ('0', '1'),
- ('20', '79'),
- ('800', '999'),
- ],
- '99935': [ # Haiti
- ('0', '2'),
- ('7', '8'),
- ('30', '59'),
- ('600', '699'),
- ('90', '99'),
- ],
- '99936': [ # Bhutan
- ('0', '0'),
- ('10', '59'),
- ('600', '999'),
- ],
- '99937': [ # Macau
- ('0', '1'),
- ('20', '59'),
- ('600', '999'),
- ],
- '99938': [ # Srpska
- ('0', '1'),
- ('20', '59'),
- ('600', '899'),
- ('90', '99'),
- ],
- '99939': [ # Guatemala
- ('0', '5'),
- ('60', '89'),
- ('900', '999'),
- ],
- '99940': [ # Georgia
- ('0', '0'),
- ('10', '69'),
- ('700', '999'),
- ],
- '99941': [ # Armenia
- ('0', '2'),
- ('30', '79'),
- ('800', '999'),
- ],
- '99942': [ # Sudan
- ('0', '4'),
- ('50', '79'),
- ('800', '999'),
- ],
- '99943': [ # Alsbania
- ('0', '2'),
- ('30', '59'),
- ('600', '999'),
- ],
- '99944': [ # Ethiopia
- ('0', '4'),
- ('50', '79'),
- ('800', '999'),
- ],
- '99945': [ # Namibia
- ('0', '5'),
- ('60', '89'),
- ('900', '999'),
- ],
- '99946': [ # Nepal
- ('0', '2'),
- ('30', '59'),
- ('600', '999'),
- ],
- '99947': [ # Tajikistan
- ('0', '2'),
- ('30', '69'),
- ('700', '999'),
- ],
- '99948': [ # Eritrea
- ('0', '4'),
- ('50', '79'),
- ('800', '999'),
- ],
- '99949': [ # Mauritius
- ('0', '1'),
- ('20', '89'),
- ('900', '999'),
- ],
- '99950': [ # Cambodia
- ('0', '4'),
- ('50', '79'),
- ('800', '999'),
- ],
- '99951': [ # Congo - no ranges fixed yet
- ],
- '99952': [ # Mali
- ('0', '4'),
- ('50', '79'),
- ('800', '999'),
- ],
- '99953': [ # Paraguay
- ('0', '2'),
- ('30', '79'),
- ('800', '999'),
- ],
- '99954': [ # Bolivia
- ('0', '2'),
- ('30', '69'),
- ('700', '999'),
- ],
- '99955': [ # Srpska
- ('0', '1'),
- ('20', '59'),
- ('600', '899'),
- ('90', '99'),
- ],
- '99956': [ # Albania
- ('00', '59'),
- ('600', '999'),
- ],
-}
-
class InvalidIsbnException(pywikibot.Error):
"""Invalid ISBN."""
-class ISBN(object):
-
- """Abstract superclass."""
-
- def format(self):
- """Put hyphens into this ISBN number."""
- result = ''
- rest = ''
- for digit in self.digits():
- rest += str(digit)
- # Determine the prefix (if any)
- for prefix in self.possiblePrefixes():
- if rest.startswith(prefix):
- result += prefix + '-'
- rest = rest[len(prefix):]
- break
-
- # Determine the group
- for groupNumber in ranges.keys():
- if rest.startswith(groupNumber):
- result += groupNumber + '-'
- rest = rest[len(groupNumber):]
- publisherRanges = ranges[groupNumber]
- break
- else:
- raise InvalidIsbnException('ISBN {0}: group number unknown.'
- .format(self.code))
-
- # Determine the publisher
- for (start, end) in publisherRanges:
- length = len(start) # NOTE: start and end always have equal length
- if rest[:length] >= start and rest[:length] <= end:
- result += rest[:length] + '-'
- rest = rest[length:]
- break
- else:
- raise InvalidIsbnException('ISBN {0}: publisher number unknown.'
- .format(self.code))
-
- # The rest is the item number and the 1-digit checksum.
- result += rest[:-1] + '-' + rest[-1]
- self.code = result
-
-
-class ISBN13(ISBN):
-
- """ISBN 13."""
-
- def __init__(self, code, checksumMissing=False):
- """Initializer."""
- self.code = code
- if checksumMissing:
- self.code += str(self.calculateChecksum())
- self.checkValidity()
-
- def possiblePrefixes(self):
- """Return possible prefixes."""
- return ['978', '979']
-
- def digits(self):
- """Return a list of the digits in the ISBN
code."""
- result = []
- for c in self.code:
- if c.isdigit():
- result.append(int(c))
- elif c != '-':
- raise InvalidIsbnException(
- 'The ISBN {0} contains invalid characters.'
- .format(self.code))
- return result
-
- def checkValidity(self):
- """Check validity of ISBN."""
- if len(self.digits()) != 13:
- raise InvalidIsbnException('The ISBN {0} is not 13 digits long.'
- .format(self.code))
- if self.calculateChecksum() != self.digits()[-1]:
- raise InvalidIsbnException('The ISBN checksum of {0} is incorrect.'
- .format(self.code))
-
- def calculateChecksum(self):
- """
- Calculate checksum.
-
- See
https://en.wikipedia.org/wiki/ISBN#Check_digit_in_ISBN_13
- """
- sum = 0
- for i in range(0, 13 - 1, 2):
- sum += self.digits()[i]
- for i in range(1, 13 - 1, 2):
- sum += 3 * self.digits()[i]
- return (10 - (sum % 10)) % 10
-
-
-class ISBN10(ISBN):
-
- """ISBN 10."""
-
- def __init__(self, code):
- """Initializer."""
- self.code = code
- self.checkValidity()
-
- def possiblePrefixes(self):
- """Return possible prefixes."""
- return []
-
- def digits(self):
- """Return a list of the digits and Xs in the ISBN
code."""
- result = []
- for c in self.code:
- if c.isdigit() or c in 'Xx':
- result.append(c)
- elif c != '-':
- raise InvalidIsbnException(
- 'The ISBN {0} contains invalid characters.'
- .format(self.code))
- return result
-
- def checkChecksum(self):
- """Raise an InvalidIsbnException if the ISBN checksum is
incorrect."""
- # See
https://en.wikipedia.org/wiki/ISBN#Check_digit_in_ISBN_10
- sum = 0
- for i in range(0, 9):
- sum += (i + 1) * int(self.digits()[i])
- checksum = sum % 11
- lastDigit = self.digits()[-1]
- if not (checksum == 10 and lastDigit in 'Xx'
- or lastDigit.isdigit() and checksum == int(lastDigit)):
- raise InvalidIsbnException('The ISBN checksum of {0} is incorrect.'
- .format(self.code))
-
- def checkValidity(self):
- """Check validity of ISBN."""
- if len(self.digits()) != 10:
- raise InvalidIsbnException('The ISBN {0} is not 10 digits long.'
- .format(self.code))
- if 'X' in self.digits()[:-1] or 'x' in self.digits()[:-1]:
- raise InvalidIsbnException(
- 'ISBN {0}: X is only allowed at the end of the ISBN.'
- .format(self.code))
- self.checkChecksum()
-
- def toISBN13(self):
- """
- Create a 13-digit ISBN from this 10-digit ISBN.
-
- Adds the GS1 prefix '978' and recalculates the checksum.
- The hyphenation structure is taken from the format of the original
- ISBN number.
-
- @rtype: L{ISBN13}
- """
- code = '978-' + self.code[:-1]
- return ISBN13(code, checksumMissing=True)
-
- def format(self):
- """Format ISBN number."""
- # load overridden superclass method
- ISBN.format(self)
- # capitalize checksum
- if self.code[-1] == 'x':
- self.code = self.code[:-1] + 'X'
-
-
-def getIsbn(code):
- """Return an ISBN object for the code."""
- try:
- i = ISBN13(code)
- except InvalidIsbnException as e13:
- try:
- i = ISBN10(code)
- except InvalidIsbnException as e10:
- raise InvalidIsbnException('ISBN-13: {0} / ISBN-10: {1}'
- .format(e13, e10))
- return i
-
-
def is_valid(isbn):
"""Check whether an ISBN 10 or 13 is valid."""
# isbnlib marks any ISBN10 with lowercase 'X' as invalid
@@ -1363,11 +78,9 @@
else:
try:
stdnum.isbn.validate(isbn)
- except stdnum.isbn.InvalidFormat as e:
- raise InvalidIsbnException(str(e))
- except stdnum.isbn.InvalidChecksum as e:
- raise InvalidIsbnException(str(e))
- except stdnum.isbn.InvalidLength as e:
+ except (stdnum.isbn.InvalidFormat,
+ stdnum.isbn.InvalidChecksum,
+ stdnum.isbn.InvalidLength) as e:
raise InvalidIsbnException(str(e))
return True
@@ -1380,8 +93,8 @@
raise InvalidIsbnException('Invalid ISBN found')
return True
- getIsbn(isbn)
- return True
+ raise NotImplementedError(
+ 'ISBN functionality not available. Install stdnum package.')
def _hyphenateIsbnNumber(match):
@@ -1398,12 +111,7 @@
except NameError:
pass
else:
- i = stdnum.isbn.format(isbn)
- return i
-
- i = getIsbn(isbn)
- i.format()
- return i.code
+ return stdnum.isbn.format(isbn)
hyphenateIsbnNumbers = partial(textlib.reformat_ISBNs,
@@ -1415,26 +123,23 @@
isbn = match.group('code')
isbn = isbn.upper()
try:
+ is_valid(isbn)
+ except InvalidIsbnException:
+ # don't change
+ return isbn
+
+ try:
stdnum.isbn
except NameError:
pass
else:
- try:
- is_valid(isbn)
- except InvalidIsbnException:
- return isbn
- i = stdnum.isbn.to_isbn13(isbn)
- return i
+ return stdnum.isbn.to_isbn13(isbn)
try:
isbnlib
except NameError:
pass
else:
- try:
- is_valid(isbn)
- except InvalidIsbnException:
- return isbn
# remove hyphenation, otherwise isbnlib.to_isbn13() returns None
i = isbnlib.canonical(isbn)
if i == isbn:
@@ -1445,18 +150,6 @@
i13h = hyphenateIsbnNumbers('ISBN ' + i13)
return i13h[5:]
- try:
- is_valid(isbn)
- except InvalidIsbnException:
- # don't change
- return isbn
- i1x = getIsbn(isbn)
- if not isinstance(i1x, ISBN13):
- i13 = i1x.toISBN13()
- else:
- i13 = i1x
- return i13.code
-
def convertIsbn10toIsbn13(text):
"""Helper function to convert ISBN 10 to ISBN 13."""
@@ -1647,14 +340,20 @@
genFactory.handleArg(arg)
gen = genFactory.getCombinedGenerator(preload=True)
- if gen:
- if use_wikibase:
- bot = IsbnWikibaseBot(gen, **options)
- else:
- bot = IsbnBot(gen, **options)
- bot.run()
+
+ deps = []
+ if not (has_module('stdnum', version='1.13')
+ or has_module('isbnlib', version='3.9.10')):
+ deps = ["'python-stdnum >= 1.13' or 'isbnlib >=
3.9.10'"]
+ if pywikibot.bot.suggest_help(missing_generator=not gen,
+ missing_dependencies=deps):
+ return
+
+ if use_wikibase:
+ bot = IsbnWikibaseBot(gen, **options)
else:
- pywikibot.bot.suggest_help(missing_generator=True)
+ bot = IsbnBot(gen, **options)
+ bot.run()
if __name__ == '__main__':
diff --git a/tests/isbn_tests.py b/tests/isbn_tests.py
index ee74120..361f40f 100644
--- a/tests/isbn_tests.py
+++ b/tests/isbn_tests.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
"""Tests for isbn script."""
#
-# (C) Pywikibot team, 2014-2019
+# (C) Pywikibot team, 2014-2020
#
# Distributed under the terms of the MIT license.
#
@@ -16,14 +16,14 @@
from pywikibot import Bot, Claim, ItemPage
from pywikibot.cosmetic_changes import CosmeticChangesToolkit, CANCEL_MATCH
+from pywikibot.tools import has_module
from scripts.isbn import (
- ISBN10, ISBN13, InvalidIsbnException as IsbnExc,
- getIsbn, hyphenateIsbnNumbers, convertIsbn10toIsbn13,
+ InvalidIsbnException as IsbnExc,
+ hyphenateIsbnNumbers, convertIsbn10toIsbn13,
main
)
-from tests import patch, Mock
from tests.aspects import (
unittest, TestCase, DefaultDrySiteTestCase,
WikibaseTestCase, ScriptMainTestCase,
@@ -36,8 +36,6 @@
AnyIsbnValidationException = IsbnExc
-# Suppress ImportWarning: package stdnum.isbn not found; using scripts.isbn
-(a)patch('pywikibot.cosmetic_changes.warn'arn', Mock())
class TestCosmeticChangesISBN(DefaultDrySiteTestCase):
"""Test CosmeticChanges ISBN fix."""
@@ -52,14 +50,6 @@
text = cc.fix_ISBN(' ISBN 9780975229804 ')
self.assertEqual(text, ' ISBN 978-0-9752298-0-4 ')
- @unittest.expectedFailure # T144288
- def test_valid_isbn_failing(self):
- """Test ISBN.
-
- This test fails with current library parts.
- """
- cc = CosmeticChangesToolkit(self.site, namespace=0)
-
text = cc.fix_ISBN(' ISBN 9783955390631 ')
self.assertEqual(text, ' ISBN 978-3-95539-063-1 ')
@@ -98,60 +88,8 @@
net = False
- def test_isbn10(self):
- """Test ISBN10."""
- # Test general features
- isbn = ISBN10('097522980x')
- isbn.format()
- self.assertEqual(isbn.code, '0-9752298-0-X')
- self.assertEqual(isbn.digits(),
- ['0', '9', '7', '5',
'2', '2', '9', '8', '0', 'X'])
-
- # Converting to ISBN13
- isbn13 = isbn.toISBN13()
- self.assertEqual(isbn13.code, '978-0-9752298-0-4')
-
- # Errors
- self.assertRaises(IsbnExc, ISBN10, '0975229LOL') # Invalid characters
- self.assertRaises(IsbnExc, ISBN10, '0975229801') # Invalid checksum
- self.assertRaises(IsbnExc, ISBN10, '09752298') # Invalid length
- self.assertRaises(IsbnExc, ISBN10, '09752X9801') # X in the middle
-
- def test_isbn13_978(self):
- """General test ISBN13 features with prefix
978."""
- isbn = ISBN13('9783161484100')
- isbn.format()
- self.assertEqual(isbn.code, '978-3-16-148410-0')
- self.assertEqual(isbn.digits(),
- [9, 7, 8, 3, 1, 6, 1, 4, 8, 4, 1, 0, 0])
-
- isbn = ISBN13('978809027341', checksumMissing=True)
- self.assertEqual(isbn.code, '9788090273412')
-
- # Errors
- self.assertRaises(IsbnExc, ISBN13, '9783161484LOL') # Invalid chars
- self.assertRaises(IsbnExc, ISBN13, '9783161484105') # Invalid checksum
- self.assertRaises(IsbnExc, ISBN13, '9783161484') # Invalid length
-
- @unittest.expectedFailure # T144288
- def test_isbn13_979(self):
- """Test ISBN13 with prefix 979."""
- isbn = ISBN13('9791091447089')
- isbn.format()
- self.assertEqual(isbn.code, '979-10-91447-08-9')
- self.assertEqual(isbn.digits(),
- [9, 7, 9, 1, 0, 9, 1, 4, 4, 7, 0, 8, 9])
-
def test_general(self):
"""Test things that apply both to ISBN10 and
ISBN13."""
- # getIsbn
- self.assertIsInstance(getIsbn('097522980x'), ISBN10)
- self.assertIsInstance(getIsbn('9783161484100'), ISBN13)
- self.assertRaisesRegex(IsbnExc,
- 'ISBN-13: The ISBN 097522 is not 13 digits '
- 'long. / ISBN-10: The ISBN 097522 is not 10 '
- 'digits long.', getIsbn, '097522')
-
# hyphenateIsbnNumbers
self.assertEqual(hyphenateIsbnNumbers('ISBN 097522980x'),
'ISBN 0-9752298-0-X')
@@ -169,16 +107,6 @@
'ISBN 978-0-7869-3669-4'
)
- # Errors
- isbn = ISBN10('9912098056')
- self.assertRaisesRegex(IsbnExc,
- 'ISBN 9912098056: group number unknown.',
- isbn.format)
- isbn = ISBN10('9095012042')
- self.assertRaisesRegex(IsbnExc,
- 'ISBN 9095012042: publisher number unknown.',
- isbn.format)
-
@unittest.expectedFailure # T144288
def test_general_failing(self):
"""Test things that apply both to ISBN10 and ISBN13.
@@ -197,7 +125,7 @@
"""Test isbnbot with non-write patching (if the testpage
exists)."""
- family = 'test'
+ family = 'wikipedia'
code = 'test'
user = True
@@ -301,5 +229,12 @@
pass
+def setUpModule(): # noqa: N802
+ """Skip tests if isbn libraries are missing."""
+ if not (has_module('stdnum', version='1.13')
+ or has_module('isbnlib', version='3.9.10')):
+ raise unittest.SkipTest('neither python-stdlib nor isbnlib available.')
+
+
if __name__ == '__main__': # pragma: no cover
unittest.main()
--
To view, visit
https://gerrit.wikimedia.org/r/565784
To unsubscribe, or for help writing mail filters, visit
https://gerrit.wikimedia.org/r/settings
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-MessageType: merged
Gerrit-Change-Id: Ib68d0c6898088425bad96c7ccfd4187dfd4bbdbf
Gerrit-Change-Number: 565784
Gerrit-PatchSet: 4
Gerrit-Owner: Xqt <info(a)gno.de>
Gerrit-Reviewer: D3r1ck <alangiderick(a)gmail.com>
Gerrit-Reviewer: D3r1ck01 <xsavitar.wiki(a)aol.com>
Gerrit-Reviewer: Dalba <dalba.wiki(a)gmail.com>
Gerrit-Reviewer: Dvorapa <dvorapa(a)seznam.cz>
Gerrit-Reviewer: Framawiki <framawiki(a)tools.wmflabs.org>
Gerrit-Reviewer: Huji <huji.huji(a)gmail.com>
Gerrit-Reviewer: JJMC89 <JJMC89.Wikimedia(a)gmail.com>
Gerrit-Reviewer: Ladsgroup <Ladsgroup(a)gmail.com>
Gerrit-Reviewer: Legoktm <legoktm(a)member.fsf.org>
Gerrit-Reviewer: Matěj Suchánek <matejsuchanek97(a)gmail.com>
Gerrit-Reviewer: Mpaa <mpaa.wiki(a)gmail.com>
Gerrit-Reviewer: Xqt <info(a)gno.de>
Gerrit-Reviewer: Zhuyifei1999 <zhuyifei1999(a)gmail.com>
Gerrit-Reviewer: jenkins-bot (75)