diff -Nru isbnlib-3.5.6/.appveyor.yml isbnlib-3.9.3/.appveyor.yml
--- isbnlib-3.5.6/.appveyor.yml 1970-01-01 00:00:00.000000000 +0000
+++ isbnlib-3.9.3/.appveyor.yml 2018-10-05 11:18:35.000000000 +0000
@@ -0,0 +1,58 @@
+version: '3.9.3.{build}'
+branches:
+ only:
+ - /v3.9.3/
+environment:
+ matrix:
+ - TOXENV: "py36"
+ TOXPYTHON: "C:\\Python36-x64\\python.exe"
+ PYTHON_HOME: "C:\\Python36-x64"
+ PYTHON_VERSION: "3.6"
+ PYTHON_ARCH: "64"
+
+ - TOXENV: "py35"
+ TOXPYTHON: "C:\\Python35\\python.exe"
+ PYTHON_HOME: "C:\\Python35"
+ PYTHON_VERSION: "3.5"
+ PYTHON_ARCH: "64"
+
+ - TOXENV: "py34"
+ TOXPYTHON: "C:\\Python34-x64\\python.exe"
+ PYTHON_HOME: "C:\\Python34-x64"
+ PYTHON_VERSION: "3.4"
+ PYTHON_ARCH: "32"
+
+ - TOXENV: "py27"
+ TOXPYTHON: "C:\\Python27-x64\\python.exe"
+ PYTHON_HOME: "C:\\Python27-x64"
+ PYTHON_VERSION: "2.7"
+ PYTHON_ARCH: "64"
+
+ - TOXENV: "py27"
+ TOXPYTHON: "C:\\Python27\\python.exe"
+ PYTHON_HOME: "C:\\Python27"
+ PYTHON_VERSION: "2.7"
+ PYTHON_ARCH: "32"
+
+init:
+ - "ECHO %TOXENV%"
+ - "ECHO %TOXPYTHON% %PYTHON_VERSION% %PYTHON_ARCH%"
+
+install:
+ - ps: (new-object net.webclient).DownloadFile('https://bootstrap.pypa.io/get-pip.py', 'C:/get-pip.py')
+ - "%TOXPYTHON% C:/get-pip.py"
+ - "%PYTHON_HOME%/Scripts/pip.exe install -r requirements-appveyor.txt"
+
+build: false # First tests then build (is python not C)
+
+test_script:
+ - "%PYTHON_HOME%\\Scripts\\tox -e %TOXENV%"
+
+# clone_folder: 'c:\\projects\\isbnlib'
+
+# after_test:
+# - "%TOXPYTHON% setup.py bdist_wheel"
+# - ps: "ls dist"
+
+# artifacts:
+# - path: 'dist\\*.whl'
diff -Nru isbnlib-3.5.6/appveyor.yml isbnlib-3.9.3/appveyor.yml
--- isbnlib-3.5.6/appveyor.yml 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/appveyor.yml 1970-01-01 00:00:00.000000000 +0000
@@ -1,52 +0,0 @@
-version: '3.5.6.{build}'
-branches:
- only:
- - /v3.5.6/
-environment:
- matrix:
- - TOXENV: "py27"
- TOXPYTHON: "C:\\Python27\\python.exe"
- PYTHON_HOME: "C:\\Python27"
- PYTHON_VERSION: "2.7"
- PYTHON_ARCH: "32"
-
- - TOXENV: "py34"
- TOXPYTHON: "C:\\Python34-x64\\python.exe"
- PYTHON_HOME: "C:\\Python34-x64"
- PYTHON_VERSION: "3.4"
- PYTHON_ARCH: "64"
-
- - TOXENV: "py27"
- TOXPYTHON: "C:\\Python27-x64\\python.exe"
- PYTHON_HOME: "C:\\Python27-x64"
- PYTHON_VERSION: "2.7"
- PYTHON_ARCH: "64"
-
- - TOXENV: "py33"
- TOXPYTHON: "C:\\Python33\\python.exe"
- PYTHON_HOME: "C:\\Python33"
- PYTHON_VERSION: "3.3"
- PYTHON_ARCH: "32"
-
-init:
- - "ECHO %TOXENV%"
- - "ECHO %TOXPYTHON% %PYTHON_VERSION% %PYTHON_ARCH%"
-
-install:
- - ps: (new-object net.webclient).DownloadFile('https://raw.github.com/pypa/pip/master/contrib/get-pip.py', 'C:/get-pip.py')
- - "%TOXPYTHON% C:/get-pip.py"
- - "%PYTHON_HOME%/Scripts/pip.exe install -r requirements-appveyor.txt"
-
-build: false # First tests then build (is python not C)
-
-test_script:
- - "%PYTHON_HOME%\\Scripts\\tox -e %TOXENV%"
-
-# clone_folder: 'c:\\projects\\isbnlib'
-
-# after_test:
-# - "%TOXPYTHON% setup.py bdist_wheel"
-# - ps: "ls dist"
-
-# artifacts:
-# - path: 'dist\\*.whl'
diff -Nru isbnlib-3.5.6/CHANGES.txt isbnlib-3.9.3/CHANGES.txt
--- isbnlib-3.5.6/CHANGES.txt 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/CHANGES.txt 2018-10-05 11:18:35.000000000 +0000
@@ -17,6 +17,29 @@
v3.5.1, 2015-03-10 -- New CoversCache and better unicode printing in Windows.
v3.5.2, 2015-03-15 -- Fix bug #19, relative paths on coverscache and data range 20150310.
v3.5.3, 2015-03-26 -- Add throttling for web services, data range 20150325 and 'in memory' keys cache.
-v3.5.4, 2015-04-10 -- Issue #20, fix bugs #21 and #22 and data range 20150401.
+v3.5.4, 2015-04-10 -- Issue #20, fix bugs #21 and #22 and data range 20150401.
v3.5.5, 2015-04-22 -- Add logging to vias, fix bug #23, and data range 20150422.
-v3.5.6, 2015-06-03 -- Deprecated 'bouth23' and data range 20150603.
+v3.5.6, 2015-06-03 -- Deprecated 'bouth23' and data range 20150603.
+v3.5.7, 2015-11-22 -- Support for py35 and pypy3 and data range 20151118.
+v3.5.8, 2016-03-07 -- Issue #28 (closing down of xISBN service).
+v3.5.9, 2016-06-17 -- Improved data quality (close #39 and #40) and new cover (close issue #42).
+v3.6.1, 2016-06-21 -- Improved data quality (#39 and #40), new cover (#42) and streamlined.
+v3.6.2, 2016-09-06 -- Updated data.
+v3.6.3, 2016-11-09 -- Updated data.
+v3.6.4, 2016-11-12 -- Fix bug #46.
+v3.6.5, 2016-12-08 -- Updated data.
+v3.6.6, 2017-01-05 -- Fix bug #47.
+v3.6.7, 2017-03-11 -- Updated data.
+v3.6.8, 2017-03-31 -- New functions: check_digit10 and check_digit13.
+v3.7.1, 2017-05-24 -- Fix #43 (bump middle version).
+v3.7.2, 2017-06-19 -- Restore xID (improved data quality close #28).
+v3.7.3, 2018-01-08 -- Updated data.
+v3.7.4, 2018-01-08 -- Add support for CSL-JSON format (close #48).
+v3.8.1, 2018-01-24 -- BREAK: stop support for py26, py33 and isbndb.
+v3.8.2, 2018-01-24 -- Fix bug 'in_virtual'.
+v3.8.3, 2018-01-29 -- Add 'wcat' to editions.
+v3.8.4, 2018-03-06 -- Solve issues with non-ASCII searchs in 'from_words'.
+v3.8.5, 2018-06-14 -- NOT RELEASED.
+v3.9.1, 2018-07-02 -- Issue #51 (closing down of xISBN service).
+v3.9.2, 2018-09-28 -- Updated data.
+v3.9.3, 2018-10-05 -- make it easier to override 'WEBService.data'.
diff -Nru isbnlib-3.5.6/.checkignore isbnlib-3.9.3/.checkignore
--- isbnlib-3.5.6/.checkignore 1970-01-01 00:00:00.000000000 +0000
+++ isbnlib-3.9.3/.checkignore 2018-10-05 11:18:35.000000000 +0000
@@ -0,0 +1,3 @@
+# Ignore folder content
+isbnlib/test/*
+isbnlib/_data/*
diff -Nru isbnlib-3.5.6/CODE_OF_CONDUCT.md isbnlib-3.9.3/CODE_OF_CONDUCT.md
--- isbnlib-3.5.6/CODE_OF_CONDUCT.md 1970-01-01 00:00:00.000000000 +0000
+++ isbnlib-3.9.3/CODE_OF_CONDUCT.md 2018-10-05 11:18:35.000000000 +0000
@@ -0,0 +1,74 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as
+contributors and maintainers pledge to making participation in our project and
+our community a harassment-free experience for everyone, regardless of age, body
+size, disability, ethnicity, gender identity and expression, level of experience,
+nationality, personal appearance, race, religion, or sexual identity and
+orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment
+include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or
+ advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic
+ address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or
+reject comments, commits, code, wiki edits, issues, and other contributions
+that are not aligned to this Code of Conduct, or to ban temporarily or
+permanently any contributor for other behaviors that they deem inappropriate,
+threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community. Examples of
+representing a project or community include using an official project e-mail
+address, posting via an official social media account, or acting as an appointed
+representative at an online or offline event. Representation of a project may be
+further defined and clarified by project maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported by contacting the project team at [xlcnd@outlook.com]. All
+complaints will be reviewed and investigated and will result in a response that
+is deemed necessary and appropriate to the circumstances. The project team is
+obligated to maintain confidentiality with regard to the reporter of an incident.
+Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good
+faith may face temporary or permanent repercussions as determined by other
+members of the project's leadership.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
+available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
+
+[homepage]: https://www.contributor-covenant.org
+
diff -Nru isbnlib-3.5.6/CONTRIBUTING.md isbnlib-3.9.3/CONTRIBUTING.md
--- isbnlib-3.5.6/CONTRIBUTING.md 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/CONTRIBUTING.md 2018-10-05 11:18:35.000000000 +0000
@@ -17,7 +17,7 @@
3. **Fork** the repository on GitHub and **clone it locally**
([help](https://help.github.com/articles/fork-a-repo)).
4. `pip install -r requirements-dev.txt` (at your local directory).
-5. Do your code... (**remember the code must run on python 2.6, 2.7, 3.3, 3.4, pypy
+5. Do your code... (**remember the code must run on python 2.7, 3.4, 3.5, 3.6
and be OS independent** It is easier if you start to write in python 3 and then
adapt for python 2) (you will find [Travis](https://travis-ci.org/xlcnd/isbnlib) very handy for
testing with this requirement!)
@@ -36,7 +36,7 @@
## Style
Your code **must** be [PEP8](http://legacy.python.org/dev/peps/pep-0008/) compliant
-and be concise as possible (check it with
+and be concise as possible (use `yapf` then check it with
`flake8` and `pylint`).
Use doc strings ([PEP257](http://legacy.python.org/dev/peps/pep-0257/))
diff -Nru isbnlib-3.5.6/COPYRIGHT.txt isbnlib-3.9.3/COPYRIGHT.txt
--- isbnlib-3.5.6/COPYRIGHT.txt 1970-01-01 00:00:00.000000000 +0000
+++ isbnlib-3.9.3/COPYRIGHT.txt 2018-10-05 11:18:35.000000000 +0000
@@ -0,0 +1,16 @@
+
+isbnlib - tools for extracting, cleaning and transforming ISBNs
+Copyright (C) 2014-2018 Alexandre Lima Conde
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program. If not, see .
diff -Nru isbnlib-3.5.6/.coveragerc isbnlib-3.9.3/.coveragerc
--- isbnlib-3.5.6/.coveragerc 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/.coveragerc 2018-10-05 11:18:35.000000000 +0000
@@ -39,3 +39,5 @@
if __name__ == .__main__.:
ignore_errors = True
+
+fail_under = 90
diff -Nru isbnlib-3.5.6/debian/changelog isbnlib-3.9.3/debian/changelog
--- isbnlib-3.5.6/debian/changelog 2015-06-24 18:52:05.000000000 +0000
+++ isbnlib-3.9.3/debian/changelog 2018-10-21 10:19:21.000000000 +0000
@@ -1,3 +1,9 @@
+isbnlib (3.9.3-1) unstable; urgency=low
+
+ * New upstream package
+
+ -- Aigars Mahinovs Sun, 21 Oct 2018 13:19:21 +0300
+
isbnlib (3.5.6-1) unstable; urgency=low
* Initial package upload
diff -Nru isbnlib-3.5.6/debian/control isbnlib-3.9.3/debian/control
--- isbnlib-3.5.6/debian/control 2015-06-24 18:58:53.000000000 +0000
+++ isbnlib-3.9.3/debian/control 2018-10-21 10:19:21.000000000 +0000
@@ -3,7 +3,7 @@
Section: python
Priority: optional
Build-Depends: python-setuptools (>= 0.6b3), python3-setuptools, python-all (>= 2.6.6-3), python3-all, debhelper (>= 9), dh-python, python-nose, python3-nose
-Standards-Version: 3.9.6
+Standards-Version: 4.2.1
Package: python-isbnlib
Architecture: all
diff -Nru isbnlib-3.5.6/debian/watch isbnlib-3.9.3/debian/watch
--- isbnlib-3.5.6/debian/watch 1970-01-01 00:00:00.000000000 +0000
+++ isbnlib-3.9.3/debian/watch 2018-10-21 10:19:21.000000000 +0000
@@ -0,0 +1,4 @@
+version=4
+
+opts=filenamemangle=s/.+\/v?(\d\S*)\.tar\.gz/isbnlib-$1\.tar\.gz/ \
+ https://github.com/xlcnd/isbnlib/tags .*/v?(\d\S*)\.tar\.gz
diff -Nru isbnlib-3.5.6/docs/code.rst isbnlib-3.9.3/docs/code.rst
--- isbnlib-3.5.6/docs/code.rst 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/docs/code.rst 2018-10-05 11:18:35.000000000 +0000
@@ -14,35 +14,20 @@
Status
------
-.. image:: https://pypip.in/d/isbnlib/badge.png
- :target: https://pypi.python.org/pypi/isbnlib/
- :alt: Downloads
-
-.. image:: https://pypip.in/v/isbnlib/badge.png
- :target: https://pypi.python.org/pypi/isbnlib/
- :alt: Latest Version
-
-.. image:: https://pypip.in/format/isbnlib/badge.png
- :target: https://pypi.python.org/pypi/isbnlib/
- :alt: Download format
-
-.. image:: https://pypip.in/license/isbnlib/badge.png
- :target: https://pypi.python.org/pypi/isbnlib/
- :alt: License
-
-.. image:: https://coveralls.io/repos/xlcnd/isbnlib/badge.svg?branch=v3.5.6
- :target: https://coveralls.io/r/xlcnd/isbnlib?branch=v3.5.6
- :alt: Coverage
-.. image:: https://sourcegraph.com/api/repos/github.com/xlcnd/isbnlib/badges/status.svg
+.. image:: https://img.shields.io/badge/Sourcegraph-Status-blue.svg
:target: https://sourcegraph.com/github.com/xlcnd/isbnlib
:alt: Graph
-.. image:: https://travis-ci.org/xlcnd/isbnlib.svg?branch=v3.5.6
+.. image:: https://coveralls.io/repos/github/xlcnd/isbnlib/badge.svg?branch=v3.9.3
+ :target: https://coveralls.io/github/xlcnd/isbnlib?branch=v3.9.3
+ :alt: Coverage Status
+
+.. image:: https://travis-ci.org/xlcnd/isbnlib.svg?branch=v3.9.3
:target: https://travis-ci.org/xlcnd/isbnlib
:alt: Built Status
-.. image:: https://ci.appveyor.com/api/projects/status/github/xlcnd/isbnlib?branch=v3.5.6&svg=true
+.. image:: https://ci.appveyor.com/api/projects/status/github/xlcnd/isbnlib?branch=v3.9.3&svg=true
:target: https://ci.appveyor.com/project/xlcnd/isbnlib
:alt: Windows Built Status
@@ -54,7 +39,7 @@
-----------------
``isbnlib`` has a very small code base, so it is a good project to begin your
-adventure in open-source...
+adventure in open-source...
Main Steps
@@ -82,7 +67,7 @@
If you don't have experience in these issues, don't be put off by these requirements,
see them as a learning opportunity. Thanks!
- For full instructions read the CONTRIBUTING_ doc.
+ For full instructions read the CONTRIBUTING_ doc.
.. _sourcegraph: https://sourcegraph.com/github.com/xlcnd/isbnlib
diff -Nru isbnlib-3.5.6/docs/conf.py isbnlib-3.9.3/docs/conf.py
--- isbnlib-3.5.6/docs/conf.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/docs/conf.py 2018-10-05 11:18:35.000000000 +0000
@@ -45,7 +45,7 @@
# General information about the project.
project = u'isbnlib'
-copyright = u'2014, Alexandre Conde'
+copyright = u'2014-2018, Alexandre Conde'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
@@ -54,7 +54,7 @@
# The short X.Y version.
version = '3.5'
# The full version, including alpha/beta/rc tags.
-release = '3.5.6'
+release = '3.9.3'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@@ -94,7 +94,6 @@
# If true, keep warnings as "system message" paragraphs in the built documents.
#keep_warnings = False
-
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
@@ -179,26 +178,23 @@
# Output file base name for HTML help builder.
htmlhelp_basename = 'isbnlibdoc'
-
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
-# The paper size ('letterpaper' or 'a4paper').
-#'papersize': 'letterpaper',
-
-# The font size ('10pt', '11pt' or '12pt').
-#'pointsize': '10pt',
-
-# Additional stuff for the LaTeX preamble.
-#'preamble': '',
+ # The paper size ('letterpaper' or 'a4paper').
+ #'papersize': 'letterpaper',
+ # The font size ('10pt', '11pt' or '12pt').
+ #'pointsize': '10pt',
+ # Additional stuff for the LaTeX preamble.
+ #'preamble': '',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
- ('index', 'isbnlib.tex', u'isbnlib Documentation',
- u'Alexandre Conde', 'manual'),
+ ('index', 'isbnlib.tex', u'isbnlib Documentation', u'Alexandre Conde',
+ 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
@@ -221,39 +217,31 @@
# If false, no module index is generated.
#latex_domain_indices = True
-
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
-man_pages = [
- ('index', 'isbnlib', u'isbnlib Documentation',
- [u'Alexandre Conde'], 1)
-]
+man_pages = [('index', 'isbnlib', u'isbnlib Documentation',
+ [u'Alexandre Conde'], 1)]
# If true, show URL addresses after external links.
#man_show_urls = False
-
# -- Options for Texinfo output -------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
- ('index', 'isbnlib', u'isbnlib Documentation',
- u'Alexandre Conde', 'isbnlib', 'One line description of project.',
- 'Miscellaneous'),
+ ('index', 'isbnlib', u'isbnlib Documentation', u'Alexandre Conde',
+ 'isbnlib', 'One line description of project.', 'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
-
# If false, no module index is generated.
#texinfo_domain_indices = True
-
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
-
# If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False
diff -Nru isbnlib-3.5.6/docs/devs.rst isbnlib-3.9.3/docs/devs.rst
--- isbnlib-3.5.6/docs/devs.rst 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/docs/devs.rst 2018-10-05 11:18:35.000000000 +0000
@@ -10,7 +10,7 @@
This library works mainly with 'striped' ISBNs (only numbers and X) like '0826497527'. You can
strip an ISBN's like string by using ``canonical(isbnlike)``. You can
'mask' the ISBN by using ``mask(isbn)``. So in the examples below, when you see 'isbn'
- in the argument, it is a 'striped' ISBN, when the argument is an 'isbnlike' it is a string
+ in the argument, it is a 'striped' ISBN, when the argument is an 'isbnlike' it is a string
like ``ISBN 979-10-90636-07-1`` or even something dirty like ``asdf 979-10-90636-07-1 bla bla``.
Two important concepts: **valid ISBN** should be an ISBN that was built according with the rules,
@@ -25,7 +25,7 @@
If possible, work with ISBNs in the isbn-13 format (since 2007, only are issued ISBNs in the isbn-13
format). You can always convert isbn-10 to isbn-13, but **not** the reverse.
- Read more about ISBN at isbn-international.org_.
+ Read more about ISBN at isbn-international.org_.
@@ -35,85 +35,83 @@
In the namespace ``isbnlib`` you have access to the core methods:
``is_isbn10(isbn10like)``
- Validates as ISBN-10.
+ Validates as ISBN-10.
``is_isbn13(isbn13like)``
- Validates as ISBN-13.
+ Validates as ISBN-13.
``to_isbn10(isbn13)``
- Transforms an isbn-13 to isbn-10.
+ Transforms an isbn-13 to isbn-10.
``to_isbn13(isbn10)``
- Transforms an isbn-10 to isbn-13.
+ Transforms an isbn-10 to isbn-13.
``canonical(isbnlike)``
- Keeps only numbers and X. You will get strings like `9780321534965`.
+ Keeps only numbers and X. You will get strings like `9780321534965`.
``clean(isbnlike)``
- Cleans ISBN (only legal characters).
+ Cleans ISBN (only legal characters).
``notisbn(isbnlike, level='strict')``
- Check with the goal to invalidate isbn-like.
+ Check with the goal to invalidate isbn-like.
``get_isbnlike(text, level='normal')``
- Extracts all substrings that seem like ISBNs (very useful for scraping).
+ Extracts all substrings that seem like ISBNs (very useful for scraping).
``get_canonical_isbn(isbnlike, output='bouth')``
- Extracts ISBNs and transform them to the canonical form.
+ Extracts ISBNs and transform them to the canonical form.
``EAN13(isbnlike)``
- Transforms an `isbnlike` string into an EAN13 number (validated canonical ISBN-13).
+ Transforms an `isbnlike` string into an EAN13 number (validated canonical ISBN-13).
``info(isbn)``
- Gets the language or country assigned to this ISBN.
+ Gets the language or country assigned to this ISBN.
``mask(isbn, separator='-')``
- `Mask` (hyphenate) a canonical ISBN.
+ `Mask` (hyphenate) a canonical ISBN.
``meta(isbn, service='default', cache='default')``
Gives you the main metadata associated with the ISBN. As `service` parameter you can use:
- ``'wcat'`` uses **worldcat.org**
- (**no key is needed**), ``'goob'`` uses the **Google Books service** (**no key is needed**),
- ``'isbndb'`` uses the **isbndb.com** service (**an api key is needed**),
- ``'openl'`` uses the **OpenLibrary.org** api (**no key is needed**), ``merge`` uses
- a merged record of ``wcat`` and ``goob`` records (**no key is needed**) and
- **is the default option**.
- You can get an API key for the *isbndb.com service* here_. You can enter API keys
- with ``isbnlib.config.add_apikey(service, apikey)``.
- The output can be formatted as ``bibtex``, ``msword``, ``endnote``, ``refworks``,
+ ``'goob'`` uses the **Google Books service** (**no key is needed**) and
+ **is the default option**,
+ ``'openl'`` uses the **OpenLibrary.org** api (**no key is needed**).
+ You can enter API keys
+ with ``config.add_apikey(service, apikey)`` (see example below).
+ The output can be formatted as ``bibtex``, ``csl`` (CSL-JSON), ``msword``, ``endnote``, ``refworks``,
``opf`` or ``json`` (BibJSON) bibliographic formats with ``isbnlib.registry.bibformatters``.
- ``cache`` only allows two values: 'default' or None. You can change the kind of cache by using
+ ``cache`` only allows two values: 'default' or None. You can change the kind of cache by using
``isbnlib.registry.set_cache`` (see below).
+ Now, you can extend the functionality of this function by adding pluggins, more metadata
+ providers or new bibliographic formatters (check_ for available pluggins).
-``editions(isbn, service='wcat')``
+``editions(isbn, service='merge')``
Returns the list of ISBNs of editions related with this ISBN. By default
- uses 'wcat', but other providers are avilable: 'thingl' (uses the
- service ThingISBN from **LibraryThing**), 'merge' (merges 'wcat' with 'thingl')
- and 'any' (first tries 'wcat', if no data, tries 'thingl').
+ uses 'merge' (merges 'openl' and 'thingl'), but other providers are available:
+ 'openl' users **Open Library**, 'thingl' (uses the service ThingISBN from **LibraryThing**)
+ and 'any' (first tries 'openl', if no data, then 'thingl').
``isbn_from_words(words)``
- Returns the most probable ISBN from a list of words (for your geographic area).
+ Returns the most probable ISBN from a list of words (for your geographic area).
``goom(words)``
- Returns a list of references from **Google Books multiple references**.
+ Returns a list of references from **Google Books multiple references**.
``doi(isbn)``
- Returns a DOI's ISBN-A from a ISBN-13.
+ Returns a DOI's ISBN-A from a ISBN-13.
``doi2tex(DOI)``
- Returns metadata formated as BibTeX for a given DOI.
+ Returns metadata formated as BibTeX for a given DOI.
``ren(filename)``
- Renames a file using metadata from an ISBN in his filename.
+ Renames a file using metadata from an ISBN in his filename.
``desc(isbn)``
- Returns a small description of the book.
- *Almost all data available are for US books!*
+ Returns a small description of the book.
+ *Almost all data available are for US books!*
``cover(isbn)``
- Downloads an image of the cover of the book or, with
- `cover(isbn, mode='url')`, returns an url of the image.
- *Almost all data available are for US books!*
+ Returns a dictionary with the url for cover.
+ *Almost all data available are for US books!*
See files test_core_ and test_ext_ for **a lot of examples**.
@@ -142,18 +140,14 @@
* ``vias`` exposes several functions to put calls to services, just by passing the name and
a pointer to the service's ``query`` function.
- ``vias.parallel`` allows to put threaded calls. You can use ``vias.serial``
+ ``vias.parallel`` allows to put threaded calls. You can use ``vias.serial``
to make serial calls and
``vias.multi`` to use several cores. The default is ``vias.serial``, but
you can change that in the conf file.
-* ``bouth23`` (**DEPRECATED**) a small module to make it possible the code to run
- in **bouth** python 2 and python 3. **It will disappear in the next major version!**.
- See python-future.org_ for a built-in alternative to ``bouth23``.
-
-The exceptions raised by these methods can all be catched using ``ISBNLibDevException``.
-You **should't raise** this exception in your code, only raise the specific exceptions
+The exceptions raised by these methods can all be catched using ``ISBNLibDevException``.
+You **should't raise** this exception in your code, only raise the specific exceptions
exposed in ``isbnlib.dev`` whose name end in Error.
@@ -161,25 +155,74 @@
are only used in ``isbntools`` (*an app and framework* that uses ``isbnlib``).
-With ``isbnlib.registry`` you can change the metadata service to be used by default (``setdefaultservice``),
+With ``isbnlib.registry`` you can change the metadata service to be used by default (``setdefaultservice``),
add a new service (``add_service``), access bibliographic formatters for metadata (``bibformatters``),
-set the default formatter (``setdefaultbibformatter``), add new formatters (``add_bibformatter``) and
+set the default formatter (``setdefaultbibformatter``), add new formatters (``add_bibformatter``) and
set a new cache (``set_cache``) (e.g. to switch off the chache ``set_cache(None)``).
The cache only works for calls through ``isbnlib.meta``. These changes only work for the 'current session',
so should be done always before calling other methods.
-Finally, from ``isbnlib.config`` you can read and set configuration options:
-change timeouts with ``setsocketstimeout`` and ``setthreadstimeout``,
+Finally, from ``isbnlib.config`` you can read and set configuration options:
+change timeouts with ``seturlopentimeout`` and ``setthreadstimeout``,
access api keys with ``apikeys`` and add new one with ``add_apikey`` and
access and set generic and user-defined options with ``options`` and ``set_option``.
+Let us concretize the last point with a small example.
+
+Suppose you want a small script to get metadata using ``Open Library`` formated in BibTeX.
+
+A minimal script would be:
+
+
+.. code-block:: python
+
+ from isbnlib import meta
+ from isbnlib.registry import bibformatters
+
+ SERVICE = 'openl'
+
+ # now you can use the service
+ isbn = '9780446310789'
+ bibtex = bibformatters['bibtex']
+ print(bibtex(meta(isbn, SERVICE)))
+
All these classes follow a simple design pattern and, if you follow it, will be
very easy to integrate your classes with the rest of the lib.
+Plugins
+-------
+
+You can extend the functionality of the library by adding pluggins (for now, just
+new metadata providers or new bibliographic formatters).
+
+Start with this template_ and follow the instructions there. For inspiration take a look
+at goob_.
+
+After install, your pluggin will blend transparently in ``isbnlib``.
+
+Remember that plugins **must** support python 2.7 and python 3.4+ (see python-future.org_).
+
+For available pluggins check_ here.
+
+
+
+Extra Functionality
+-------------------
+
+To get extra functionality, search_ pypi for packages starting with ``isbnlib``
+**or** type at a terminal:
+
+.. code-block:: console
+
+ $ pip search isbnlib
+
+
+for a nice formated report!
+
Merge Metadata
@@ -190,16 +233,16 @@
*polling & merge* of several providers **and** a **lot** of cleaning and standardization
for fields like ``Authors`` and ``Publisher``.
A *simple merge* provider is now the default in ``isbnlib.meta``.
-It gives priority to ``wcat`` but overwrites the ``Authors`` field with the value from ``goob``.
-Uses the ``merge`` method of ``Metadata`` and *serial* calls to services
-by default (faster for fast Internet connections).
-
-You can change that by using ``vias``'s other methods
+It gives priority to ``wcat`` but overwrites the ``Authors``, ``Publisher`` and ``Year``
+fields with values from ``goob`` (if available) or ``openl``.
+Uses the ``merge`` method of ``Metadata`` and *parallel* calls to services.
+
+You can change that by using ``vias``'s other methods
(e.g. ``isbnlib.config.set_option('VIAS_MERGE', 'multi')``.
You can write your own *merging scheme* by creating a new provider (see_ ``merge`` for an example).
- **Take Note**: These classes are optimized for one-calls to services and not for batch calls.
+.. note:: These classes are optimized for one-calls to services and not for batch calls.
A full featured app!
@@ -213,9 +256,8 @@
**You can browse the code, in a very structured way, at** sourcegraph_ or GitHub_.
-.. _wcat: https://github.com/xlcnd/isbnlib/blob/master/isbnlib/_wcat.py
-.. _isbndb: https://github.com/xlcnd/isbnlib/blob/master/isbnlib/_isbndb.py
+
.. _see: https://github.com/xlcnd/isbnlib/blob/master/isbnlib/_merge.py
@@ -232,3 +274,11 @@
.. _isbn-international.org: https://www.isbn-international.org/content/what-isbn
.. _python-future.org: http://python-future.org/compatible_idioms.html
+
+.. _check: https://pypi.python.org/pypi?%3Aaction=search&term=isbnlib_&submit=search
+
+.. _template: https://github.com/xlcnd/isbnlib/blob/dev/PLUGIN.zip
+
+.. _goob: https://github.com/xlcnd/isbnlib/blob/dev/isbnlib/_goob.py
+
+.. _search: https://pypi.python.org/pypi?%3Aaction=search&term=isbnlib&submit=search
diff -Nru isbnlib-3.5.6/docs/info.rst isbnlib-3.9.3/docs/info.rst
--- isbnlib-3.5.6/docs/info.rst 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/docs/info.rst 2018-10-05 11:18:35.000000000 +0000
@@ -3,13 +3,23 @@
Info
====
+``isbnlib`` is a (pure) python library that provides several
+useful methods and functions to validate, clean, transform, hyphenate and
+get metadata for ISBN strings. Its origin was as the core of isbntools_.
+This short version, is suitable to be include as a dependency in other projects.
+Has a straightforward setup and a very easy programmatic api.
+
+Runs on py27, py34, py35, py36 and py37.
+
+
+Usage
+-----
Typical usage (as library):
.. code-block:: python
- #!/usr/bin/env python
import isbnlib
...
@@ -53,6 +63,30 @@
Have fun!
-.. _here: http://isbndb.com/api/v2/docs
+
+
+Projects using *isbnlib*
+------------------------
+
+**isbntools** https://github.com/xlcnd/isbntools
+
+**Spreads** https://github.com/DIYBookScanner/spreads
+
+**BiblioManager** https://github.com/Phyks/BMC/
+
+**libBMC** https://github.com/Phyks/libbmc/
+
+**Alessandria** https://gitlab.com/openlabmatera/alessandria
+
+**Comic Collector** https://github.com/wengole/comiccollector
+
+**Abelujo** http://www.abelujo.cc/
+
+**BibLib** https://pypi.python.org/pypi/biblib
+
+
+
.. _pdfminer: https://pypi.python.org/pypi/pdfminer
+
+.. _isbntools: https://pypi.python.org/pypi/isbntools
diff -Nru isbnlib-3.5.6/docs/install.rst isbnlib-3.9.3/docs/install.rst
--- isbnlib-3.5.6/docs/install.rst 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/docs/install.rst 2018-10-05 11:18:35.000000000 +0000
@@ -21,8 +21,15 @@
.. code-block:: bash
- $ pip install isbnlib-3.5.6.tar.gz
+ $ pip install isbnlib-3.9.3.tar.gz
(first you have to download the file!)
+If you use linux systems, you can install using your distribution package
+manager (all major distributions have packages ``python-isbnlib``
+and ``python3-isbnlib``), however (usually) are **very old and don't work well anymore**!
+
+
+
+
diff -Nru isbnlib-3.5.6/.editorconfig isbnlib-3.9.3/.editorconfig
--- isbnlib-3.5.6/.editorconfig 1970-01-01 00:00:00.000000000 +0000
+++ isbnlib-3.9.3/.editorconfig 2018-10-05 11:18:35.000000000 +0000
@@ -0,0 +1,25 @@
+# EditorConfig.org
+
+root = true
+
+[*]
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.{py,md,rst,txt,conf,cfg}]
+charset = utf-8
+
+[*.py]
+indent_style = space
+indent_size = 4
+
+[*.{md,rst}]
+trim_trailing_whitespace = false
+
+[{appveyor.yml,.travis.yml}]
+indent_style = space
+indent_size = 2
+
+[Makefile]
+indent_style = tab
diff -Nru isbnlib-3.5.6/.flake8 isbnlib-3.9.3/.flake8
--- isbnlib-3.5.6/.flake8 1970-01-01 00:00:00.000000000 +0000
+++ isbnlib-3.9.3/.flake8 2018-10-05 11:18:35.000000000 +0000
@@ -0,0 +1,3 @@
+ignore=N806,I100,I101,I201,N802,C901,E722,E741
+exclude=*/test/*,*/_data/*
+max-complexity=13
diff -Nru isbnlib-3.5.6/.github/CODEOWNERS isbnlib-3.9.3/.github/CODEOWNERS
--- isbnlib-3.5.6/.github/CODEOWNERS 1970-01-01 00:00:00.000000000 +0000
+++ isbnlib-3.9.3/.github/CODEOWNERS 2018-10-05 11:18:35.000000000 +0000
@@ -0,0 +1,2 @@
+isbnlib/* @xlcnd
+docs/* @xlcnd
diff -Nru isbnlib-3.5.6/.github/PULL_REQUEST_TEMPLATE.md isbnlib-3.9.3/.github/PULL_REQUEST_TEMPLATE.md
--- isbnlib-3.5.6/.github/PULL_REQUEST_TEMPLATE.md 1970-01-01 00:00:00.000000000 +0000
+++ isbnlib-3.9.3/.github/PULL_REQUEST_TEMPLATE.md 2018-10-05 11:18:35.000000000 +0000
@@ -0,0 +1,16 @@
+**IMPORTANT**
+
+Make your pull request against the ``dev`` branch, please!
+
+
+
+Changes proposed in this pull request:
+
+-
+
+-
+
+-
+
+
+@xlcnd
diff -Nru isbnlib-3.5.6/.gitignore isbnlib-3.9.3/.gitignore
--- isbnlib-3.5.6/.gitignore 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/.gitignore 2018-10-05 11:18:35.000000000 +0000
@@ -23,12 +23,14 @@
*.log
*.sh
.coverage
+.bandit
.metacache
*tasks
LAB/
apps/
spin/
LAB_*
+*LAB*
CHECKLIST
TODO
*release*
diff -Nru isbnlib-3.5.6/.hound.yml isbnlib-3.9.3/.hound.yml
--- isbnlib-3.5.6/.hound.yml 1970-01-01 00:00:00.000000000 +0000
+++ isbnlib-3.9.3/.hound.yml 2018-10-05 11:18:35.000000000 +0000
@@ -0,0 +1,5 @@
+python:
+ enabled: true
+ config_file: .flake8
+
+fail_on_violations: true
diff -Nru isbnlib-3.5.6/isbnlib/config.py isbnlib-3.9.3/isbnlib/config.py
--- isbnlib-3.5.6/isbnlib/config.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/config.py 2018-10-05 11:18:35.000000000 +0000
@@ -3,28 +3,20 @@
# --> Import only external modules! <--
-
-import socket
-
# Timeouts
-SOCKETS_TIMEOUT = 12 # seconds
-THREADS_TIMEOUT = 11 # seconds
+URLOPEN_TIMEOUT = 10 # seconds
+THREADS_TIMEOUT = 12 # seconds
-def setsocketstimeout(seconds):
- """Set the value of SOCKETS_TIMEOUT (in seconds)."""
- global SOCKETS_TIMEOUT
- SOCKETS_TIMEOUT = seconds
- return socket.setdefaulttimeout(SOCKETS_TIMEOUT)
-
-# socket timeout is not exposed at urllib2 level so I had to import the
-# module and set a default value for all the sockets (timeout in seconds)
-# however this should be done at top level due to strong side effects...
-setsocketstimeout(SOCKETS_TIMEOUT)
+# URLOPEN_TIMEOUT is used by webservice
+def seturlopentimeout(seconds): # pragma: no cover
+ """Set the value of URLOPEN_TIMEOUT (in seconds)."""
+ global URLOPEN_TIMEOUT
+ URLOPEN_TIMEOUT = seconds
# THREADS_TIMEOUT is a parameter used downstream by Thread calls (see vias.py)
-def setthreadstimeout(seconds): # pragma: no cover
+def setthreadstimeout(seconds): # pragma: no cover
"""Set the value of THREADS_TIMEOUT (in seconds)."""
global THREADS_TIMEOUT
THREADS_TIMEOUT = seconds
@@ -35,17 +27,14 @@
def add_apikey(service, apikey): # pragma: no cover
- """Add API keys.
-
- add_apikey('isbndb', 'JuHytr6') [is fake!]
- """
+ """Add API keys."""
apikeys[service] = apikey
# Generic Options
-options = {'VIAS_MERGE': 'serial'}
+options = {'VIAS_MERGE': 'parallel'}
-def set_option(option, value): # pragma: no cover
+def set_option(option, value): # pragma: no cover
"""Set the value for option."""
options[option] = value
diff -Nru isbnlib-3.5.6/isbnlib/_core.py isbnlib-3.9.3/isbnlib/_core.py
--- isbnlib-3.5.6/isbnlib/_core.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/_core.py 2018-10-05 11:18:35.000000000 +0000
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
# isbnlib - tools for extracting, cleaning and transforming ISBNs
-# Copyright (C) 2014 Alexandre Lima Conde
+# Copyright (C) 2014-2018 Alexandre Lima Conde
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -15,8 +15,6 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-
-
"""isbnlib main file.
Tools for extracting, cleaning, transforming and validating ISBN ids.
@@ -27,7 +25,6 @@
LOGGER = logging.getLogger(__name__)
-
RE_ISBN10 = re.compile(r'ISBN\x20(?=.{13}$)\d{1,5}([- ])\d{1,7}'
r'\1\d{1,6}\1(\d|X)$|[- 0-9X]{10,16}')
RE_ISBN13 = re.compile(r'97[89]{1}(?:-?\d){10,16}|97[89]{1}[- 0-9]{10,16}')
@@ -39,25 +36,24 @@
r'[- ]?[0-9]+[- ]?[0-9]+[- ]?[0-9X]$',
re.I | re.M | re.S)
RE_NORMAL = re.compile(r'97[89]{1}(?:-?\d){10}|\d{9}[0-9X]{1}|'
- r'[-0-9X]{10,16}',
- re.I | re.M | re.S)
+ r'[-0-9X]{10,16}', re.I | re.M | re.S)
RE_LOOSE = re.compile(r'[- 0-9X]{10,19}', re.I | re.M | re.S)
ISBN13_PREFIX = '978'
LEGAL = '0123456789xXisbnISBN- '
-def _check_digit10(firstninedigits):
+def check_digit10(firstninedigits):
"""Check sum ISBN-10."""
# minimum checks
if len(firstninedigits) != 9:
return None
try:
int(firstninedigits)
- except: # pragma: no cover
+ except Exception: # pragma: no cover
return None
# checksum
- val = sum((i + 2) * int(x) for
- i, x in enumerate(reversed(firstninedigits)))
+ val = sum(
+ (i + 2) * int(x) for i, x in enumerate(reversed(firstninedigits)))
remainder = int(val % 11)
if remainder == 0:
tenthdigit = 0
@@ -68,18 +64,18 @@
return str(tenthdigit)
-def _check_digit13(firsttwelvedigits):
+def check_digit13(firsttwelvedigits):
"""Check sum ISBN-13."""
# minimum checks
if len(firsttwelvedigits) != 12:
return None
try:
int(firsttwelvedigits)
- except: # pragma: no cover
+ except Exception: # pragma: no cover
return None
# checksum
- val = sum((i % 2 * 2 + 1) * int(x) for
- i, x in enumerate(firsttwelvedigits))
+ val = sum(
+ (i % 2 * 2 + 1) * int(x) for i, x in enumerate(firsttwelvedigits))
thirteenthdigit = 10 - int(val % 10)
if thirteenthdigit == 10:
thirteenthdigit = '0'
@@ -100,20 +96,20 @@
"""Validate as ISBN-10."""
isbn10 = canonical(isbn10)
if len(isbn10) != 10:
- return False # pragma: no cover
+ return False # pragma: no cover
else:
- return False if _check_digit10(isbn10[:-1]) != isbn10[-1] else True
+ return False if check_digit10(isbn10[:-1]) != isbn10[-1] else True
def is_isbn13(isbn13):
"""Validate as ISBN-13."""
isbn13 = canonical(isbn13)
if len(isbn13) != 13:
- return False # pragma: no cover
+ return False # pragma: no cover
else:
if isbn13[0:3] not in ('978', '979'):
return False
- return False if _check_digit13(isbn13[:-1]) != isbn13[-1] else True
+ return False if check_digit13(isbn13[:-1]) != isbn13[-1] else True
def to_isbn10(isbn13):
@@ -125,7 +121,7 @@
if not is_isbn13(isbn13):
return None
isbn10 = isbn13[3:]
- check = _check_digit10(isbn10[:-1])
+ check = check_digit10(isbn10[:-1])
# Change check digit
return isbn10[:-1] + check if check else None
@@ -138,7 +134,7 @@
if not is_isbn10(isbn10):
return None
isbn13 = ISBN13_PREFIX + isbn10[:-1]
- check = _check_digit13(isbn13)
+ check = check_digit13(isbn13)
return isbn13 + check if check else None
@@ -167,7 +163,7 @@
"""
if level not in ('strict', 'loose'): # pragma: no cover
LOGGER.error('level as no option %s', level)
- return
+ return None
isbnlike = canonical(isbnlike)
if len(isbnlike) not in (10, 13):
return True
@@ -196,7 +192,7 @@
isbnlike = RE_LOOSE
else:
LOGGER.error('level as no option %s', level)
- return
+ return None
return isbnlike.findall(text)
@@ -211,7 +207,7 @@
"""
if output not in ('bouth', 'isbn10', 'isbn13'): # pragma: no cover
LOGGER.error('output as no option %s', output)
- return
+ return None
regex = RE_NORMAL
@@ -226,10 +222,10 @@
if len(chars) == 9:
# Compute the ISBN-10 checksum digit
- check = _check_digit10(buf)
+ check = check_digit10(buf)
else:
# Compute the ISBN-13 checksum digit
- check = _check_digit13(buf)
+ check = check_digit13(buf)
# If checksum OK return a `canonical` ISBN
if str(check) == last:
@@ -238,6 +234,7 @@
if output == 'isbn10':
return cisbn if len(cisbn) == 10 else to_isbn10(cisbn)
return to_isbn13(cisbn) if len(cisbn) == 10 else cisbn
+ return None
def ean13(isbnlike):
@@ -247,6 +244,9 @@
return ib if is_isbn13(ib) else None
elif len(ib) == 10:
return to_isbn13(ib) if is_isbn10(ib) else None
+ return None
+
# Alias
EAN13 = ean13
+GTIN13 = ean13
diff -Nru isbnlib-3.5.6/isbnlib/_cover.py isbnlib-3.9.3/isbnlib/_cover.py
--- isbnlib-3.5.6/isbnlib/_cover.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/_cover.py 2018-10-05 11:18:35.000000000 +0000
@@ -1,125 +1,39 @@
# -*- coding: utf-8 -*-
-"""Get the cover of the book."""
+"""Get image links of the book's cover."""
import logging
-try: # pragma: no cover
- # PY3
- from urllib.error import HTTPError, URLError
- from urllib.request import Request, urlopen
-except ImportError: # pragma: no cover
- # PY2
- from urllib2 import Request, urlopen, HTTPError, URLError
-
-from json import loads
-
-from .dev._exceptions import ISBNLibHTTPError, ISBNLibURLError
-from .dev.webservice import query
+from .dev.webquery import query as wquery
+LOGGER = logging.getLogger(__name__)
-COVERZOOM = 2
-NOIMGSIZE = (15666, 16641, 2690)
UA = "isbnlib (gzip)"
-
-LOGGER = logging.getLogger(__name__)
+SERVICE_URL = 'https://www.googleapis.com/books/v1/volumes?q=isbn+{isbn}'\
+ '&fields=items/volumeInfo(imageLinks)&maxResults=1'
-def bookid(isbn):
- """Return the Google's id associated with each ISBN."""
+def cover(isbn):
+ """Main entry point for cover."""
from .registry import metadata_cache # <-- dynamic
- # check the cache fist
+ # check the cache first
cache = metadata_cache
- if cache is not None: # pragma: no cover
- key = 'gid' + isbn
- try: # pragma: no cover
+ if cache: # pragma: no cover
+ key = 'img-url-go-' + isbn
+ try: # pragma: no cover
if cache[key]:
return cache[key]
else:
- raise # <-- IMPORTANT: usually the caches don't return error!
- except: # pragma: no cover
+ raise KeyError # <-- IMPORTANT: caches don't return error!
+ except KeyError: # pragma: no cover
pass
- url = "https://www.googleapis.com/books/v1/volumes?q="\
- "isbn+{isbn}&fields=items/id&maxResults=1".format(isbn=isbn)
- content = query(url, user_agent=UA)
+ # request to the web service
+ data = wquery(SERVICE_URL.format(isbn=isbn), user_agent=UA)
try:
- content = loads(content)
- gid = content['items'][0]['id']
- if gid and cache is not None:
- cache[key] = gid
- return gid
- except: # pragma: no cover
- return
-
-
-def _download(url, tofile=None):
- """Download image."""
- headers = {'User-Agent': UA, 'Pragma': 'no-cache'}
- request = Request(url, headers=headers)
- try:
- response = urlopen(request)
- LOGGER.debug('Request headers:\n%s', request.header_items())
- except HTTPError as e: # pragma: no cover
- LOGGER.critical('ISBNLibHTTPError for %s with code %s [%s]',
- url, e.code, e.msg)
- if e.code == 403:
- # Google uses this code when the image is not
- # available for any size (should use 404),
- # but also when you are blacklisted by the service
- LOGGER.debug('Cover not available or you are making many requests')
- return True # <-- no more attempts to download
- if e.code in (401, 429):
- raise ISBNLibHTTPError('%s Are you are making many requests?'
- % e.code)
- if e.code in (502, 504):
- raise ISBNLibHTTPError('%s Service temporarily unavailable!'
- % e.code)
- raise ISBNLibHTTPError('(%s) %s' % (e.code, e.msg))
- except URLError as e: # pragma: no cover
- LOGGER.critical('ISBNLibURLError for %s with reason %s',
- url, e.reason)
- raise ISBNLibURLError(e.reason)
- content = response.read()
- noimageavailable = len(content) in NOIMGSIZE
- if noimageavailable: # pragma: no cover
- return False
- if tofile:
- try: # pragma: no cover
- # PY2
- content_type = response.info().getheader('Content-Type')
- except: # pragma: no cover
- # PY3
- content_type = response.getheader('Content-Type')
- _, ext = content_type.split('/')
- tofile = tofile.split('.')[0] + '.' + ext.split('-')[-1]
- with open(tofile, 'wb') as f:
- f.write(content)
- else: # pragma: no cover
- print(content)
- return tofile
-
-
-def _google_cover(gid, isbn, zoom=COVERZOOM, mode='prt'):
- """Download the cover from Google."""
- tpl = "http://books.google.com/books/content?id={gid}&printsec=frontcover"\
- "&img=1&zoom={zoom}&edge=curl&source=gbs_api"
- url = tpl.format(gid=gid, zoom=zoom)
- if mode == 'url': # pragma: no cover
- return (url, None)
- coverfile = _download(url, tofile=isbn)
- while not coverfile: # pragma: no cover
- # try a smaller resolution
- zoom -= 1
- if zoom > 0:
- url = tpl.format(gid=gid, zoom=zoom)
- else:
- return (None, None)
- coverfile = _download(url, tofile=isbn)
- return (url, coverfile) if coverfile and coverfile is not True\
- else (url, None)
-
-
-def cover(isbn, size=COVERZOOM, mode='prt'):
- """Main entry point for cover."""
- gid = bookid(isbn)
- return _google_cover(gid, isbn, zoom=size, mode=mode) if gid\
- else (None, None)
+ lnks = data['items'][0]['volumeInfo']['imageLinks']
+ # put in cache
+ if cache and lnks: # pragma: no cover
+ cache[key] = lnks
+ return lnks
+ except (KeyError, IndexError): # pragma: no cover
+ LOGGER.debug('No cover img data for %s', isbn)
+ return None
diff -Nru isbnlib-3.5.6/isbnlib/_data/data4info.py isbnlib-3.9.3/isbnlib/_data/data4info.py
--- isbnlib-3.5.6/isbnlib/_data/data4info.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/_data/data4info.py 2018-10-05 11:18:35.000000000 +0000
@@ -1,8 +1,295 @@
+# -*- coding: utf-8 -*-
# flake8: noqa
-# GeneratedWith: mk_data4info.py (isbntools)
-# MessageSource: http://www.isbn-international.org/agency?rmxml=1
-# MessageDate: Wed, 3 Jun 2015 11:50:18 CEST
-# MessageSerialNumber: 69eba68e-f50d-4193-9a48-c9f378be91f0
-d = {'978-99970': 'Haiti', '978-7': "China, People's Republic", '978-4': 'Japan', '978-5': 'former U.S.S.R', '978-2': 'French language', '978-3': 'German language', '978-0': 'English language', '978-1': 'English language', '978-9968': 'Costa Rica', '978-9961': 'Algeria', '978-9960': 'Saudi Arabia', '978-9963': 'Cyprus', '978-9962': 'Panama', '978-9965': 'Kazakhstan', '978-9964': 'Ghana', '978-9967': 'Kyrgyz Republic', '978-9966': 'Kenya', '978-967': 'Malaysia', '978-966': 'Ukraine', '978-965': 'Israel', '978-964': 'Iran', '978-963': 'Hungary', '978-962': 'Hong Kong, China', '978-961': 'Slovenia', '978-960': 'Greece', '978-9985': 'Estonia', '978-969': 'Pakistan', '978-968': 'Mexico', '978-9984': 'Latvia', '978-99971': 'Myanmar', '978-9983': 'Gambia', '978-99972': 'Faroe Islands', '978-99973': 'Mongolia', '978-99909': 'Malta', '978-99908': 'Malawi', '978-99905': 'Bolivia', '978-99904': 'Cura\xe7ao', '978-99906': 'Kuwait', '978-99901': 'Bahrain', '978-99903': 'Mauritius', '978-99902': 'Reserved Agency', '978-99976': 'Srpska, Republic of', '978-99977': 'Rwanda', '978-974': 'Thailand', '978-975': 'Turkey', '978-976': 'Caribbean Community', '978-977': 'Egypt', '978-970': 'Mexico', '978-971': 'Philippines', '978-972': 'Portugal', '978-973': 'Romania', '978-978': 'Nigeria', '978-979': 'Indonesia', '978-99918': 'Faroe Islands', '978-99919': 'Benin', '978-99916': 'Namibia', '978-99917': 'Brunei Darussalam', '978-99914': 'Suriname', '978-99915': 'Maldives', '978-99912': 'Botswana', '978-99913': 'Andorra', '978-99910': 'Sierra Leone', '978-99911': 'Lesotho', '979-11': 'Korea, Republic', '978-90': 'Netherlands', '978-91': 'Sweden', '978-92': 'International NGO Publishers and EU Organizations', '978-93': 'India', '978-94': 'Netherlands', '978-9982': 'Zambia', '978-9981': 'Morocco', '978-9980': 'Papua New Guinea', '978-9989': 'Macedonia', '978-9988': 'Ghana', '978-99923': 'El Salvador', '978-99922': 'Guatemala', '978-99921': 'Qatar', '978-99920': 'Andorra', '978-99927': 'Albania', '978-99926': 'Honduras', '978-99925': 'Paraguay', '978-99924': 'Nicaragua', '978-99929': 'Mongolia', '978-99928': 'Georgia', '978-9932': "Lao People's Democratic Republic", '978-9933': 'Syria', '978-9930': 'Costa Rica', '978-9931': 'Algeria', '978-9936': 'Afghanistan', '978-9937': 'Nepal', '978-9934': 'Latvia', '978-9935': 'Iceland', '979-12': 'Italy', '978-9938': 'Tunisia', '978-9939': 'Armenia', '978-958': 'Colombia', '978-959': 'Cuba', '978-956': 'Chile', '978-957': 'Taiwan', '978-954': 'Bulgaria', '978-955': 'Sri Lanka', '978-952': 'Finland', '978-953': 'Croatia', '978-950': 'Argentina', '978-951': 'Finland', '978-89': 'Korea, Republic', '978-88': 'Italy', '978-87': 'Denmark', '978-86': 'former Yugoslavia', '978-85': 'Brazil', '978-84': 'Spain', '978-83': 'Poland', '978-82': 'Norway', '978-81': 'India', '978-80': 'former Czechoslovakia', '978-99934': 'Dominican Republic', '978-99935': 'Haiti', '978-99936': 'Bhutan', '978-99937': 'Macau', '978-99930': 'Armenia', '978-99931': 'Seychelles', '978-99932': 'Malta', '978-99933': 'Nepal', '978-620': 'Mauritius', '978-621': 'Philippines', '978-99938': 'Srpska, Republic of', '978-99939': 'Guatemala', '978-9925': 'Cyprus', '978-9924': 'Cambodia', '978-9927': 'Qatar', '978-9926': 'Bosnia and Herzegovina', '978-9929': 'Guatemala', '978-9928': 'Albania', '979-10': 'France', '978-9986': 'Lithuania', '978-9987': 'Tanzania', '978-99941': 'Armenia', '978-99940': 'Georgia', '978-99943': 'Albania', '978-99942': 'Sudan', '978-99945': 'Namibia', '978-99944': 'Ethiopia', '978-99947': 'Tajikistan', '978-99946': 'Nepal', '978-99949': 'Mauritius', '978-99948': 'Eritrea', '978-9950': 'Palestine', '978-9951': 'Kosova', '978-9952': 'Azerbaijan', '978-9953': 'Lebanon', '978-9954': 'Morocco', '978-9955': 'Lithuania', '978-9956': 'Cameroon', '978-9957': 'Jordan', '978-9958': 'Bosnia and Herzegovina', '978-9959': 'Libya', '978-989': 'Portugal', '978-988': 'Hong Kong, China', '978-985': 'Belarus', '978-984': 'Bangladesh', '978-987': 'Argentina', '978-986': 'Taiwan', '978-981': 'Singapore', '978-980': 'Venezuela', '978-983': 'Malaysia', '978-982': 'South Pacific', '978-99952': 'Mali', '978-99953': 'Paraguay', '978-99950': 'Cambodia', '978-99951': 'Reserved Agency', '978-99956': 'Albania', '978-99957': 'Malta', '978-99954': 'Bolivia', '978-99955': 'Srpska, Republic of', '978-99958': 'Bahrain', '978-99959': 'Luxembourg', '978-9943': 'Uzbekistan', '978-9942': 'Ecuador', '978-9941': 'Georgia', '978-9940': 'Montenegro', '978-9947': 'Algeria', '978-9946': 'Korea, P.D.R.', '978-9945': 'Dominican Republic', '978-9944': 'Turkey', '978-9949': 'Estonia', '978-9948': 'United Arab Emirates', '978-615': 'Hungary', '978-614': 'Lebanon', '978-617': 'Ukraine', '978-616': 'Thailand', '978-611': 'Thailand', '978-613': 'Mauritius', '978-612': 'Peru', '978-619': 'Bulgaria', '978-618': 'Greece', '978-99974': 'Bolivia', '978-99967': 'Paraguay', '978-99966': 'Kuwait', '978-99965': 'Macau', '978-99964': 'Nicaragua', '978-99963': 'Cambodia', '978-99962': 'Mongolia', '978-99961': 'El Salvador', '978-99960': 'Malawi', '978-99969': 'Oman', '978-99968': 'Botswana', '978-9976': 'Tanzania', '978-9977': 'Costa Rica', '978-9974': 'Uruguay', '978-9975': 'Moldova', '978-9972': 'Peru', '978-9973': 'Tunisia', '978-9970': 'Uganda', '978-9971': 'Singapore', '978-99975': 'Tajikistan', '978-9978': 'Ecuador', '978-9979': 'Iceland', '978-602': 'Indonesia', '978-603': 'Saudi Arabia', '978-600': 'Iran', '978-601': 'Kazakhstan', '978-606': 'Romania', '978-607': 'Mexico', '978-604': 'Vietnam', '978-605': 'Turkey', '978-608': 'Macedonia', '978-609': 'Lithuania'}
-identifiers = (('978-0', '978-1', '978-2', '978-3', '978-4', '978-5', '978-7'), ('978-80', '978-81', '978-82', '978-83', '978-84', '978-85', '978-86', '978-87', '978-88', '978-89', '978-90', '978-91', '978-92', '978-93', '978-94', '979-10', '979-11', '979-12'), ('978-600', '978-601', '978-602', '978-603', '978-604', '978-605', '978-606', '978-607', '978-608', '978-609', '978-611', '978-612', '978-613', '978-614', '978-615', '978-616', '978-617', '978-618', '978-619', '978-620', '978-621', '978-950', '978-951', '978-952', '978-953', '978-954', '978-955', '978-956', '978-957', '978-958', '978-959', '978-960', '978-961', '978-962', '978-963', '978-964', '978-965', '978-966', '978-967', '978-968', '978-969', '978-970', '978-971', '978-972', '978-973', '978-974', '978-975', '978-976', '978-977', '978-978', '978-979', '978-980', '978-981', '978-982', '978-983', '978-984', '978-985', '978-986', '978-987', '978-988', '978-989'), ('978-9924', '978-9925', '978-9926', '978-9927', '978-9928', '978-9929', '978-9930', '978-9931', '978-9932', '978-9933', '978-9934', '978-9935', '978-9936', '978-9937', '978-9938', '978-9939', '978-9940', '978-9941', '978-9942', '978-9943', '978-9944', '978-9945', '978-9946', '978-9947', '978-9948', '978-9949', '978-9950', '978-9951', '978-9952', '978-9953', '978-9954', '978-9955', '978-9956', '978-9957', '978-9958', '978-9959', '978-9960', '978-9961', '978-9962', '978-9963', '978-9964', '978-9965', '978-9966', '978-9967', '978-9968', '978-9970', '978-9971', '978-9972', '978-9973', '978-9974', '978-9975', '978-9976', '978-9977', '978-9978', '978-9979', '978-9980', '978-9981', '978-9982', '978-9983', '978-9984', '978-9985', '978-9986', '978-9987', '978-9988', '978-9989'), ('978-99901', '978-99902', '978-99903', '978-99904', '978-99905', '978-99906', '978-99908', '978-99909', '978-99910', '978-99911', '978-99912', '978-99913', '978-99914', '978-99915', '978-99916', '978-99917', '978-99918', '978-99919', '978-99920', '978-99921', '978-99922', '978-99923', '978-99924', '978-99925', '978-99926', '978-99927', '978-99928', '978-99929', '978-99930', '978-99931', '978-99932', '978-99933', '978-99934', '978-99935', '978-99936', '978-99937', '978-99938', '978-99939', '978-99940', '978-99941', '978-99942', '978-99943', '978-99944', '978-99945', '978-99946', '978-99947', '978-99948', '978-99949', '978-99950', '978-99951', '978-99952', '978-99953', '978-99954', '978-99955', '978-99956', '978-99957', '978-99958', '978-99959', '978-99960', '978-99961', '978-99962', '978-99963', '978-99964', '978-99965', '978-99966', '978-99967', '978-99968', '978-99969', '978-99970', '978-99971', '978-99972', '978-99973', '978-99974', '978-99975', '978-99976', '978-99977'))
-RDDATE='2015060310:50:18WEST'
+d = {
+ '978-0': 'English language',
+ '978-1': 'English language',
+ '978-2': 'French language',
+ '978-3': 'German language',
+ '978-4': 'Japan',
+ '978-5': 'former U.S.S.R',
+ '978-600': 'Iran',
+ '978-601': 'Kazakhstan',
+ '978-602': 'Indonesia',
+ '978-603': 'Saudi Arabia',
+ '978-604': 'Vietnam',
+ '978-605': 'Turkey',
+ '978-606': 'Romania',
+ '978-607': 'Mexico',
+ '978-608': 'Macedonia',
+ '978-609': 'Lithuania',
+ '978-611': 'Thailand',
+ '978-612': 'Peru',
+ '978-613': 'Mauritius',
+ '978-614': 'Lebanon',
+ '978-615': 'Hungary',
+ '978-616': 'Thailand',
+ '978-617': 'Ukraine',
+ '978-618': 'Greece',
+ '978-619': 'Bulgaria',
+ '978-620': 'Mauritius',
+ '978-621': 'Philippines',
+ '978-622': 'Iran',
+ '978-623': 'Indonesia',
+ '978-65': 'Brazil',
+ '978-7': "China, People's Republic",
+ '978-80': 'former Czechoslovakia',
+ '978-81': 'India',
+ '978-82': 'Norway',
+ '978-83': 'Poland',
+ '978-84': 'Spain',
+ '978-85': 'Brazil',
+ '978-86': 'former Yugoslavia',
+ '978-87': 'Denmark',
+ '978-88': 'Italy',
+ '978-89': 'Korea, Republic',
+ '978-90': 'Netherlands',
+ '978-91': 'Sweden',
+ '978-92': 'International NGO Publishers and EU Organizations',
+ '978-93': 'India',
+ '978-94': 'Netherlands',
+ '978-950': 'Argentina',
+ '978-951': 'Finland',
+ '978-952': 'Finland',
+ '978-953': 'Croatia',
+ '978-954': 'Bulgaria',
+ '978-955': 'Sri Lanka',
+ '978-956': 'Chile',
+ '978-957': 'Taiwan',
+ '978-958': 'Colombia',
+ '978-959': 'Cuba',
+ '978-960': 'Greece',
+ '978-961': 'Slovenia',
+ '978-962': 'Hong Kong, China',
+ '978-963': 'Hungary',
+ '978-964': 'Iran',
+ '978-965': 'Israel',
+ '978-966': 'Ukraine',
+ '978-967': 'Malaysia',
+ '978-968': 'Mexico',
+ '978-969': 'Pakistan',
+ '978-970': 'Mexico',
+ '978-971': 'Philippines',
+ '978-972': 'Portugal',
+ '978-973': 'Romania',
+ '978-974': 'Thailand',
+ '978-975': 'Turkey',
+ '978-976': 'Caribbean Community',
+ '978-977': 'Egypt',
+ '978-978': 'Nigeria',
+ '978-979': 'Indonesia',
+ '978-980': 'Venezuela',
+ '978-981': 'Singapore',
+ '978-982': 'South Pacific',
+ '978-983': 'Malaysia',
+ '978-984': 'Bangladesh',
+ '978-985': 'Belarus',
+ '978-986': 'Taiwan',
+ '978-987': 'Argentina',
+ '978-988': 'Hong Kong, China',
+ '978-989': 'Portugal',
+ '978-9920': 'Morocco',
+ '978-9921': 'Kuwait',
+ '978-9922': 'Iraq',
+ '978-9923': 'Jordan',
+ '978-9924': 'Cambodia',
+ '978-9925': 'Cyprus',
+ '978-9926': 'Bosnia and Herzegovina',
+ '978-9927': 'Qatar',
+ '978-9928': 'Albania',
+ '978-9929': 'Guatemala',
+ '978-9930': 'Costa Rica',
+ '978-9931': 'Algeria',
+ '978-9932': "Lao People's Democratic Republic",
+ '978-9933': 'Syria',
+ '978-9934': 'Latvia',
+ '978-9935': 'Iceland',
+ '978-9936': 'Afghanistan',
+ '978-9937': 'Nepal',
+ '978-9938': 'Tunisia',
+ '978-9939': 'Armenia',
+ '978-9940': 'Montenegro',
+ '978-9941': 'Georgia',
+ '978-9942': 'Ecuador',
+ '978-9943': 'Uzbekistan',
+ '978-9944': 'Turkey',
+ '978-9945': 'Dominican Republic',
+ '978-9946': 'Korea, P.D.R.',
+ '978-9947': 'Algeria',
+ '978-9948': 'United Arab Emirates',
+ '978-9949': 'Estonia',
+ '978-9950': 'Palestine',
+ '978-9951': 'Kosova',
+ '978-9952': 'Azerbaijan',
+ '978-9953': 'Lebanon',
+ '978-9954': 'Morocco',
+ '978-9955': 'Lithuania',
+ '978-9956': 'Cameroon',
+ '978-9957': 'Jordan',
+ '978-9958': 'Bosnia and Herzegovina',
+ '978-9959': 'Libya',
+ '978-9960': 'Saudi Arabia',
+ '978-9961': 'Algeria',
+ '978-9962': 'Panama',
+ '978-9963': 'Cyprus',
+ '978-9964': 'Ghana',
+ '978-9965': 'Kazakhstan',
+ '978-9966': 'Kenya',
+ '978-9967': 'Kyrgyz Republic',
+ '978-9968': 'Costa Rica',
+ '978-9970': 'Uganda',
+ '978-9971': 'Singapore',
+ '978-9972': 'Peru',
+ '978-9973': 'Tunisia',
+ '978-9974': 'Uruguay',
+ '978-9975': 'Moldova',
+ '978-9976': 'Tanzania',
+ '978-9977': 'Costa Rica',
+ '978-9978': 'Ecuador',
+ '978-9979': 'Iceland',
+ '978-9980': 'Papua New Guinea',
+ '978-9981': 'Morocco',
+ '978-9982': 'Zambia',
+ '978-9983': 'Gambia',
+ '978-9984': 'Latvia',
+ '978-9985': 'Estonia',
+ '978-9986': 'Lithuania',
+ '978-9987': 'Tanzania',
+ '978-9988': 'Ghana',
+ '978-9989': 'Macedonia',
+ '978-99901': 'Bahrain',
+ '978-99902': 'Reserved Agency',
+ '978-99903': 'Mauritius',
+ '978-99904': 'Curaçao',
+ '978-99905': 'Bolivia',
+ '978-99906': 'Kuwait',
+ '978-99908': 'Malawi',
+ '978-99909': 'Malta',
+ '978-99910': 'Sierra Leone',
+ '978-99911': 'Lesotho',
+ '978-99912': 'Botswana',
+ '978-99913': 'Andorra',
+ '978-99914': 'International NGO Publishers',
+ '978-99915': 'Maldives',
+ '978-99916': 'Namibia',
+ '978-99917': 'Brunei Darussalam',
+ '978-99918': 'Faroe Islands',
+ '978-99919': 'Benin',
+ '978-99920': 'Andorra',
+ '978-99921': 'Qatar',
+ '978-99922': 'Guatemala',
+ '978-99923': 'El Salvador',
+ '978-99924': 'Nicaragua',
+ '978-99925': 'Paraguay',
+ '978-99926': 'Honduras',
+ '978-99927': 'Albania',
+ '978-99928': 'Georgia',
+ '978-99929': 'Mongolia',
+ '978-99930': 'Armenia',
+ '978-99931': 'Seychelles',
+ '978-99932': 'Malta',
+ '978-99933': 'Nepal',
+ '978-99934': 'Dominican Republic',
+ '978-99935': 'Haiti',
+ '978-99936': 'Bhutan',
+ '978-99937': 'Macau',
+ '978-99938': 'Srpska, Republic of',
+ '978-99939': 'Guatemala',
+ '978-99940': 'Georgia',
+ '978-99941': 'Armenia',
+ '978-99942': 'Sudan',
+ '978-99943': 'Albania',
+ '978-99944': 'Ethiopia',
+ '978-99945': 'Namibia',
+ '978-99946': 'Nepal',
+ '978-99947': 'Tajikistan',
+ '978-99948': 'Eritrea',
+ '978-99949': 'Mauritius',
+ '978-99950': 'Cambodia',
+ '978-99951': 'Reserved Agency',
+ '978-99952': 'Mali',
+ '978-99953': 'Paraguay',
+ '978-99954': 'Bolivia',
+ '978-99955': 'Srpska, Republic of',
+ '978-99956': 'Albania',
+ '978-99957': 'Malta',
+ '978-99958': 'Bahrain',
+ '978-99959': 'Luxembourg',
+ '978-99960': 'Malawi',
+ '978-99961': 'El Salvador',
+ '978-99962': 'Mongolia',
+ '978-99963': 'Cambodia',
+ '978-99964': 'Nicaragua',
+ '978-99965': 'Macau',
+ '978-99966': 'Kuwait',
+ '978-99967': 'Paraguay',
+ '978-99968': 'Botswana',
+ '978-99969': 'Oman',
+ '978-99970': 'Haiti',
+ '978-99971': 'Myanmar',
+ '978-99972': 'Faroe Islands',
+ '978-99973': 'Mongolia',
+ '978-99974': 'Bolivia',
+ '978-99975': 'Tajikistan',
+ '978-99976': 'Srpska, Republic of',
+ '978-99977': 'Rwanda',
+ '978-99978': 'Mongolia',
+ '978-99979': 'Honduras',
+ '978-99980': 'Bhutan',
+ '978-99981': 'Macau',
+ '979-10': 'France',
+ '979-11': 'Korea, Republic',
+ '979-12': 'Italy'
+}
+identifiers = (('978-0', '978-1', '978-2', '978-3', '978-4', '978-5',
+ '978-7'), ('978-65', '978-80', '978-81', '978-82', '978-83',
+ '978-84', '978-85', '978-86', '978-87', '978-88',
+ '978-89', '978-90', '978-91', '978-92', '978-93',
+ '978-94', '979-10', '979-11', '979-12'),
+ ('978-600', '978-601', '978-602', '978-603', '978-604',
+ '978-605', '978-606', '978-607', '978-608', '978-609',
+ '978-611', '978-612', '978-613', '978-614', '978-615',
+ '978-616', '978-617', '978-618', '978-619', '978-620',
+ '978-621', '978-622', '978-623', '978-950', '978-951',
+ '978-952', '978-953', '978-954', '978-955', '978-956',
+ '978-957', '978-958', '978-959', '978-960', '978-961',
+ '978-962', '978-963', '978-964', '978-965', '978-966',
+ '978-967', '978-968', '978-969', '978-970', '978-971',
+ '978-972', '978-973', '978-974', '978-975', '978-976',
+ '978-977', '978-978', '978-979', '978-980', '978-981',
+ '978-982', '978-983', '978-984', '978-985', '978-986',
+ '978-987', '978-988', '978-989'),
+ ('978-9920', '978-9921', '978-9922', '978-9923', '978-9924',
+ '978-9925', '978-9926', '978-9927', '978-9928', '978-9929',
+ '978-9930', '978-9931', '978-9932', '978-9933', '978-9934',
+ '978-9935', '978-9936', '978-9937', '978-9938', '978-9939',
+ '978-9940', '978-9941', '978-9942', '978-9943', '978-9944',
+ '978-9945', '978-9946', '978-9947', '978-9948', '978-9949',
+ '978-9950', '978-9951', '978-9952', '978-9953', '978-9954',
+ '978-9955', '978-9956', '978-9957', '978-9958', '978-9959',
+ '978-9960', '978-9961', '978-9962', '978-9963', '978-9964',
+ '978-9965', '978-9966', '978-9967', '978-9968', '978-9970',
+ '978-9971', '978-9972', '978-9973', '978-9974', '978-9975',
+ '978-9976', '978-9977', '978-9978', '978-9979', '978-9980',
+ '978-9981', '978-9982', '978-9983', '978-9984', '978-9985',
+ '978-9986', '978-9987', '978-9988', '978-9989'),
+ ('978-99901', '978-99902', '978-99903', '978-99904',
+ '978-99905', '978-99906', '978-99908', '978-99909',
+ '978-99910', '978-99911', '978-99912', '978-99913',
+ '978-99914', '978-99915', '978-99916', '978-99917',
+ '978-99918', '978-99919', '978-99920', '978-99921',
+ '978-99922', '978-99923', '978-99924', '978-99925',
+ '978-99926', '978-99927', '978-99928', '978-99929',
+ '978-99930', '978-99931', '978-99932', '978-99933',
+ '978-99934', '978-99935', '978-99936', '978-99937',
+ '978-99938', '978-99939', '978-99940', '978-99941',
+ '978-99942', '978-99943', '978-99944', '978-99945',
+ '978-99946', '978-99947', '978-99948', '978-99949',
+ '978-99950', '978-99951', '978-99952', '978-99953',
+ '978-99954', '978-99955', '978-99956', '978-99957',
+ '978-99958', '978-99959', '978-99960', '978-99961',
+ '978-99962', '978-99963', '978-99964', '978-99965',
+ '978-99966', '978-99967', '978-99968', '978-99969',
+ '978-99970', '978-99971', '978-99972', '978-99973',
+ '978-99974', '978-99975', '978-99976', '978-99977',
+ '978-99978', '978-99979', '978-99980', '978-99981'))
+RDDATE = '20181004'
diff -Nru isbnlib-3.5.6/isbnlib/_data/data4mask.py isbnlib-3.9.3/isbnlib/_data/data4mask.py
--- isbnlib-3.5.6/isbnlib/_data/data4mask.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/_data/data4mask.py 2018-10-05 11:18:35.000000000 +0000
@@ -1,7 +1,4 @@
+# -*- coding: utf-8 -*-
# flake8: noqa
-# GeneratedWith: mk_data4mask.py (isbntools)
-# MessageSource: http://www.isbn-international.org/agency?rmxml=1
-# MessageDate: Wed, 3 Jun 2015 11:50:18 CEST
-# MessageSerialNumber: 69eba68e-f50d-4193-9a48-c9f378be91f0
-ranges = {'978-99970': ((0, 4999999, 1), (5000000, 8999999, 2), (9000000, 9999999, 3)), '978-7': ((0, 999999, 2), (1000000, 4999999, 3), (5000000, 7999999, 4), (8000000, 8999999, 5), (9000000, 9999999, 6)), '978-4': ((0, 1999999, 2), (2000000, 6999999, 3), (7000000, 8499999, 4), (8500000, 8999999, 5), (9000000, 9499999, 6), (9500000, 9999999, 7)), '978-5': ((0, 49999, 5), (50000, 99999, 4), (100000, 1999999, 2), (2000000, 4209999, 3), (4210000, 4299999, 4), (4300000, 4309999, 3), (4310000, 4399999, 4), (4400000, 4409999, 3), (4410000, 4499999, 4), (4500000, 6999999, 3), (7000000, 8499999, 4), (8500000, 8999999, 5), (9000000, 9099999, 6), (9100000, 9199999, 5), (9200000, 9299999, 4), (9300000, 9499999, 5), (9500000, 9500999, 7), (9501000, 9799999, 4), (9800000, 9899999, 5), (9900000, 9909999, 7), (9910000, 9999999, 4)), '978-2': ((0, 1999999, 2), (2000000, 3499999, 3), (3500000, 3999999, 5), (4000000, 6999999, 3), (7000000, 8399999, 4), (8400000, 8999999, 5), (9000000, 9499999, 6), (9500000, 9999999, 7)), '978-3': ((0, 299999, 2), (300000, 339999, 3), (340000, 369999, 4), (370000, 399999, 5), (400000, 1999999, 2), (2000000, 6999999, 3), (7000000, 8499999, 4), (8500000, 8999999, 5), (9000000, 9499999, 6), (9500000, 9539999, 7), (9540000, 9699999, 5), (9700000, 9899999, 7), (9900000, 9949999, 5), (9950000, 9999999, 5)), '978-0': ((0, 1999999, 2), (2000000, 6999999, 3), (7000000, 8499999, 4), (8500000, 8999999, 5), (9000000, 9499999, 6), (9500000, 9999999, 7)), '978-1': ((0, 999999, 2), (1000000, 3999999, 3), (4000000, 5499999, 4), (5500000, 8697999, 5), (8698000, 9989999, 6), (9990000, 9999999, 7)), '978-9968': ((0, 4999999, 2), (5000000, 9399999, 3), (9400000, 9999999, 4)), '978-9961': ((0, 2999999, 1), (3000000, 6999999, 2), (7000000, 9499999, 3), (9500000, 9999999, 4)), '978-9960': ((0, 5999999, 2), (6000000, 8999999, 3), (9000000, 9999999, 4)), '978-9963': ((0, 1999999, 1), (2000000, 2499999, 4), (2500000, 2799999, 3), (2800000, 2999999, 4), (3000000, 5499999, 2), (5500000, 7349999, 3), (7350000, 7499999, 4), (7500000, 9999999, 4)), '978-9962': ((0, 5499999, 2), (5500000, 5599999, 4), (5600000, 5999999, 2), (6000000, 8499999, 3), (8500000, 9999999, 4)), '978-9965': ((0, 3999999, 2), (4000000, 8999999, 3), (9000000, 9999999, 4)), '978-9964': ((0, 6999999, 1), (7000000, 9499999, 2), (9500000, 9999999, 3)), '978-9967': ((0, 3999999, 2), (4000000, 8999999, 3), (9000000, 9999999, 4)), '978-9966': ((0, 1499999, 3), (1500000, 1999999, 4), (2000000, 6999999, 2), (7000000, 7499999, 4), (7500000, 9599999, 3), (9600000, 9999999, 4)), '978-967': ((0, 99999, 2), (100000, 999999, 4), (1000000, 1999999, 5), (2000000, 2999999, 0), (3000000, 4999999, 3), (5000000, 5999999, 4), (6000000, 8999999, 2), (9000000, 9899999, 3), (9900000, 9989999, 4), (9990000, 9999999, 5)), '978-966': ((0, 1299999, 2), (1300000, 1399999, 3), (1400000, 1499999, 2), (1500000, 1699999, 4), (1700000, 1999999, 3), (2000000, 2789999, 4), (2790000, 2899999, 3), (2900000, 2999999, 4), (3000000, 6999999, 3), (7000000, 8999999, 4), (9000000, 9099999, 5), (9100000, 9499999, 3), (9500000, 9799999, 5), (9800000, 9999999, 3)), '978-965': ((0, 1999999, 2), (2000000, 5999999, 3), (6000000, 6999999, 0), (7000000, 7999999, 4), (8000000, 8999999, 0), (9000000, 9999999, 5)), '978-964': ((0, 1499999, 2), (1500000, 2499999, 3), (2500000, 2999999, 4), (3000000, 5499999, 3), (5500000, 8999999, 4), (9000000, 9699999, 5), (9700000, 9899999, 3), (9900000, 9999999, 4)), '978-963': ((0, 1999999, 2), (2000000, 6999999, 3), (7000000, 8499999, 4), (8500000, 8999999, 5), (9000000, 9999999, 4)), '978-962': ((0, 1999999, 2), (2000000, 6999999, 3), (7000000, 8499999, 4), (8500000, 8699999, 5), (8700000, 8999999, 4), (9000000, 9999999, 3)), '978-961': ((0, 1999999, 2), (2000000, 5999999, 3), (6000000, 8999999, 4), (9000000, 9499999, 5), (9500000, 9999999, 0)), '978-960': ((0, 1999999, 2), (2000000, 6599999, 3), (6600000, 6899999, 4), (6900000, 6999999, 3), (7000000, 8499999, 4), (8500000, 9299999, 5), (9300000, 9399999, 2), (9400000, 9799999, 4), (9800000, 9999999, 5)), '978-9985': ((0, 4999999, 1), (5000000, 7999999, 2), (8000000, 8999999, 3), (9000000, 9999999, 4)), '978-969': ((0, 1999999, 1), (2000000, 2299999, 2), (2300000, 2399999, 5), (2400000, 3999999, 2), (4000000, 7499999, 3), (7500000, 9999999, 4)), '978-968': ((100000, 3999999, 2), (4000000, 4999999, 3), (5000000, 7999999, 4), (8000000, 8999999, 3), (9000000, 9999999, 4)), '978-93': ((0, 999999, 2), (1000000, 4999999, 3), (5000000, 7999999, 4), (8000000, 9499999, 5), (9500000, 9999999, 6)), '978-99971': ((0, 5999999, 1), (6000000, 8499999, 2), (8500000, 9999999, 3)), '978-94': ((0, 5999999, 3), (6000000, 8999999, 4), (9000000, 9999999, 5)), '978-99972': ((0, 4999999, 1), (5000000, 8999999, 2), (9000000, 9999999, 3)), '978-99973': ((0, 3999999, 1), (4000000, 7999999, 2), (8000000, 9999999, 3)), '978-99909': ((0, 3999999, 1), (4000000, 9499999, 2), (9500000, 9999999, 3)), '978-99908': ((0, 999999, 1), (1000000, 8999999, 2), (9000000, 9999999, 3)), '978-99905': ((0, 3999999, 1), (4000000, 7999999, 2), (8000000, 9999999, 3)), '978-99904': ((0, 5999999, 1), (6000000, 8999999, 2), (9000000, 9999999, 3)), '978-99906': ((0, 2999999, 1), (3000000, 5999999, 2), (6000000, 6999999, 3), (7000000, 8999999, 2), (9000000, 9499999, 2), (9500000, 9999999, 3)), '978-99901': ((0, 4999999, 2), (5000000, 7999999, 3), (8000000, 9999999, 2)), '978-99903': ((0, 1999999, 1), (2000000, 8999999, 2), (9000000, 9999999, 3)), '978-99902': ((0, 9999999, 0),), '978-99976': ((0, 1999999, 1), (2000000, 5999999, 2), (6000000, 7999999, 3), (8000000, 9999999, 0)), '978-99977': ((0, 1999999, 1), (2000000, 3999999, 0), (4000000, 6999999, 2), (7000000, 7999999, 3), (8000000, 9999999, 0)), '978-974': ((0, 1999999, 2), (2000000, 6999999, 3), (7000000, 8499999, 4), (8500000, 8999999, 5), (9000000, 9499999, 5), (9500000, 9999999, 4)), '978-975': ((0, 199999, 5), (200000, 2499999, 2), (2500000, 5999999, 3), (6000000, 9199999, 4), (9200000, 9899999, 5), (9900000, 9999999, 3)), '978-976': ((0, 3999999, 1), (4000000, 5999999, 2), (6000000, 7999999, 3), (8000000, 9499999, 4), (9500000, 9999999, 5)), '978-977': ((0, 1999999, 2), (2000000, 4999999, 3), (5000000, 6999999, 4), (7000000, 8499999, 3), (8500000, 8999999, 5), (9000000, 9999999, 2)), '978-970': ((100000, 5999999, 2), (6000000, 8999999, 3), (9000000, 9099999, 4), (9100000, 9699999, 5), (9700000, 9999999, 4)), '978-971': ((0, 159999, 3), (160000, 199999, 4), (200000, 299999, 2), (300000, 599999, 4), (600000, 4999999, 2), (5000000, 8499999, 3), (8500000, 9099999, 4), (9100000, 9599999, 5), (9600000, 9699999, 4), (9700000, 9899999, 2), (9900000, 9999999, 4)), '978-972': ((0, 1999999, 1), (2000000, 5499999, 2), (5500000, 7999999, 3), (8000000, 9499999, 4), (9500000, 9999999, 5)), '978-973': ((0, 999999, 1), (1000000, 1699999, 3), (1700000, 1999999, 4), (2000000, 5499999, 2), (5500000, 7599999, 3), (7600000, 8499999, 4), (8500000, 8899999, 5), (8900000, 9499999, 4), (9500000, 9999999, 5)), '978-978': ((0, 1999999, 3), (2000000, 2999999, 4), (3000000, 7999999, 5), (8000000, 8999999, 4), (9000000, 9999999, 3)), '978-979': ((0, 999999, 3), (1000000, 1499999, 4), (1500000, 1999999, 5), (2000000, 2999999, 2), (3000000, 3999999, 4), (4000000, 7999999, 3), (8000000, 9499999, 4), (9500000, 9999999, 5)), '978-9959': ((0, 1999999, 1), (2000000, 7999999, 2), (8000000, 9499999, 3), (9500000, 9699999, 4), (9700000, 9799999, 3), (9800000, 9999999, 2)), '978-99918': ((0, 3999999, 1), (4000000, 7999999, 2), (8000000, 9999999, 3)), '978-99919': ((0, 2999999, 1), (3000000, 3999999, 3), (4000000, 6999999, 2), (7000000, 7999999, 2), (8000000, 8499999, 3), (8500000, 8999999, 3), (9000000, 9999999, 3)), '978-99916': ((0, 2999999, 1), (3000000, 6999999, 2), (7000000, 9999999, 3)), '978-99917': ((0, 2999999, 1), (3000000, 8999999, 2), (9000000, 9999999, 3)), '978-99914': ((0, 4999999, 1), (5000000, 8999999, 2), (9000000, 9999999, 3)), '978-99915': ((0, 4999999, 1), (5000000, 7999999, 2), (8000000, 9999999, 3)), '978-99912': ((0, 3999999, 1), (4000000, 5999999, 3), (6000000, 8999999, 2), (9000000, 9999999, 3)), '978-99913': ((0, 2999999, 1), (3000000, 3599999, 2), (3600000, 5999999, 0), (6000000, 6049999, 3), (6050000, 9999999, 0)), '978-99910': ((0, 2999999, 1), (3000000, 8999999, 2), (9000000, 9999999, 3)), '978-99911': ((0, 5999999, 2), (6000000, 9999999, 3)), '978-9928': ((0, 999999, 2), (1000000, 3999999, 3), (4000000, 4999999, 4), (5000000, 9999999, 0)), '978-90': ((0, 1999999, 2), (2000000, 4999999, 3), (5000000, 6999999, 4), (7000000, 7999999, 5), (8000000, 8499999, 6), (8500000, 8999999, 4), (9000000, 9099999, 2), (9100000, 9399999, 0), (9400000, 9499999, 2), (9500000, 9999999, 0)), '978-91': ((0, 1999999, 1), (2000000, 4999999, 2), (5000000, 6499999, 3), (6500000, 6999999, 0), (7000000, 7999999, 4), (8000000, 8499999, 0), (8500000, 9499999, 5), (9500000, 9699999, 0), (9700000, 9999999, 6)), '978-92': ((0, 5999999, 1), (6000000, 7999999, 2), (8000000, 8999999, 3), (9000000, 9499999, 4), (9500000, 9899999, 5), (9900000, 9999999, 6)), '978-9984': ((0, 4999999, 2), (5000000, 8999999, 3), (9000000, 9999999, 4)), '978-9983': ((0, 7999999, 0), (8000000, 9499999, 2), (9500000, 9899999, 3), (9900000, 9999999, 4)), '978-9982': ((0, 7999999, 2), (8000000, 9899999, 3), (9900000, 9999999, 4)), '978-9981': ((0, 999999, 2), (1000000, 1599999, 3), (1600000, 1999999, 4), (2000000, 7999999, 2), (8000000, 9499999, 3), (9500000, 9999999, 4)), '978-9980': ((0, 3999999, 1), (4000000, 8999999, 2), (9000000, 9899999, 3), (9900000, 9999999, 4)), '978-9989': ((0, 999999, 1), (1000000, 1999999, 3), (2000000, 2999999, 4), (3000000, 5999999, 2), (6000000, 9499999, 3), (9500000, 9999999, 4)), '978-9988': ((0, 2999999, 1), (3000000, 5499999, 2), (5500000, 7499999, 3), (7500000, 9999999, 4)), '978-99923': ((0, 1999999, 1), (2000000, 7999999, 2), (8000000, 9999999, 3)), '978-99922': ((0, 3999999, 1), (4000000, 6999999, 2), (7000000, 9999999, 3)), '978-99921': ((0, 1999999, 1), (2000000, 6999999, 2), (7000000, 7999999, 3), (8000000, 8999999, 1), (9000000, 9999999, 2)), '978-99920': ((0, 4999999, 1), (5000000, 8999999, 2), (9000000, 9999999, 3)), '978-99927': ((0, 2999999, 1), (3000000, 5999999, 2), (6000000, 9999999, 3)), '978-99926': ((0, 999999, 1), (1000000, 5999999, 2), (6000000, 8699999, 3), (8700000, 8999999, 2), (9000000, 9999999, 2)), '978-99925': ((0, 3999999, 1), (4000000, 7999999, 2), (8000000, 9999999, 3)), '978-99924': ((0, 1999999, 1), (2000000, 7999999, 2), (8000000, 9999999, 3)), '978-99929': ((0, 4999999, 1), (5000000, 7999999, 2), (8000000, 9999999, 3)), '978-99928': ((0, 999999, 1), (1000000, 7999999, 2), (8000000, 9999999, 3)), '978-9932': ((0, 3999999, 2), (4000000, 8499999, 3), (8500000, 9999999, 4)), '978-9933': ((0, 999999, 1), (1000000, 3999999, 2), (4000000, 8999999, 3), (9000000, 9999999, 4)), '978-9930': ((0, 4999999, 2), (5000000, 9399999, 3), (9400000, 9999999, 4)), '978-9931': ((0, 2999999, 2), (3000000, 8999999, 3), (9000000, 9999999, 4)), '978-9936': ((0, 1999999, 1), (2000000, 3999999, 2), (4000000, 7999999, 3), (8000000, 9999999, 4)), '978-9937': ((0, 2999999, 1), (3000000, 4999999, 2), (5000000, 7999999, 3), (8000000, 9999999, 4)), '978-9934': ((0, 999999, 1), (1000000, 4999999, 2), (5000000, 7999999, 3), (8000000, 9999999, 4)), '978-9935': ((0, 999999, 1), (1000000, 3999999, 2), (4000000, 8999999, 3), (9000000, 9999999, 4)), '979-12': ((0, 1999999, 0), (2000000, 2009999, 3), (2010000, 9999999, 0)), '979-11': ((0, 2499999, 2), (2500000, 5499999, 3), (5500000, 8499999, 4), (8500000, 9499999, 5), (9500000, 9999999, 6)), '978-9939': ((0, 4999999, 1), (5000000, 7999999, 2), (8000000, 8999999, 3), (9000000, 9999999, 4)), '978-958': ((0, 5699999, 2), (5700000, 5999999, 5), (6000000, 7999999, 3), (8000000, 9499999, 4), (9500000, 9999999, 5)), '978-959': ((0, 1999999, 2), (2000000, 6999999, 3), (7000000, 8499999, 4), (8500000, 9999999, 5)), '978-956': ((0, 1999999, 2), (2000000, 6999999, 3), (7000000, 9999999, 4)), '978-957': ((0, 299999, 2), (300000, 499999, 4), (500000, 1999999, 2), (2000000, 2099999, 4), (2100000, 2799999, 2), (2800000, 3099999, 5), (3100000, 4399999, 2), (4400000, 8199999, 3), (8200000, 9699999, 4), (9700000, 9999999, 5)), '978-954': ((0, 2899999, 2), (2900000, 2999999, 4), (3000000, 7999999, 3), (8000000, 8999999, 4), (9000000, 9299999, 5), (9300000, 9999999, 4)), '978-955': ((0, 1999999, 4), (2000000, 4099999, 2), (4100000, 4399999, 5), (4400000, 4499999, 5), (4500000, 4999999, 4), (5000000, 5499999, 5), (5500000, 7499999, 3), (7500000, 7999999, 4), (8000000, 9499999, 4), (9500000, 9999999, 5)), '978-952': ((0, 1999999, 2), (2000000, 4999999, 3), (5000000, 5999999, 4), (6000000, 6599999, 2), (6600000, 6699999, 4), (6700000, 6999999, 5), (7000000, 7999999, 4), (8000000, 9499999, 2), (9500000, 9899999, 4), (9900000, 9999999, 5)), '978-953': ((0, 999999, 1), (1000000, 1499999, 2), (1500000, 5099999, 3), (5100000, 5499999, 2), (5500000, 5999999, 5), (6000000, 9499999, 4), (9500000, 9999999, 5)), '978-950': ((0, 4999999, 2), (5000000, 8999999, 3), (9000000, 9899999, 4), (9900000, 9999999, 5)), '978-951': ((0, 1999999, 1), (2000000, 5499999, 2), (5500000, 8899999, 3), (8900000, 9499999, 4), (9500000, 9999999, 5)), '978-89': ((0, 2499999, 2), (2500000, 5499999, 3), (5500000, 8499999, 4), (8500000, 9499999, 5), (9500000, 9699999, 6), (9700000, 9899999, 5), (9900000, 9999999, 3)), '978-88': ((0, 1999999, 2), (2000000, 5999999, 3), (6000000, 8499999, 4), (8500000, 8999999, 5), (9000000, 9099999, 6), (9100000, 9299999, 3), (9300000, 9399999, 4), (9400000, 9499999, 6), (9500000, 9999999, 5)), '978-87': ((0, 2999999, 2), (3000000, 3999999, 0), (4000000, 6499999, 3), (6500000, 6999999, 0), (7000000, 7999999, 4), (8000000, 8499999, 0), (8500000, 9499999, 5), (9500000, 9699999, 0), (9700000, 9999999, 6)), '978-86': ((0, 2999999, 2), (3000000, 5999999, 3), (6000000, 7999999, 4), (8000000, 8999999, 5), (9000000, 9999999, 6)), '978-85': ((0, 1999999, 2), (2000000, 5499999, 3), (5500000, 5999999, 4), (6000000, 6999999, 5), (7000000, 8499999, 4), (8500000, 8999999, 5), (9000000, 9599999, 6), (9600000, 9799999, 2), (9800000, 9999999, 5)), '978-84': ((0, 1399999, 2), (1400000, 1499999, 3), (1500000, 1999999, 5), (2000000, 6999999, 3), (7000000, 8499999, 4), (8500000, 8999999, 5), (9000000, 9199999, 4), (9200000, 9239999, 6), (9240000, 9299999, 5), (9300000, 9499999, 6), (9500000, 9699999, 5), (9700000, 9999999, 4)), '978-83': ((0, 1999999, 2), (2000000, 5999999, 3), (6000000, 6999999, 5), (7000000, 8499999, 4), (8500000, 8999999, 5), (9000000, 9999999, 6)), '978-82': ((0, 1999999, 2), (2000000, 6899999, 3), (6900000, 6999999, 6), (7000000, 8999999, 4), (9000000, 9899999, 5), (9900000, 9999999, 6)), '978-81': ((0, 1999999, 2), (2000000, 6999999, 3), (7000000, 8499999, 4), (8500000, 8999999, 5), (9000000, 9999999, 6)), '978-80': ((0, 1999999, 2), (2000000, 6999999, 3), (7000000, 8499999, 4), (8500000, 8999999, 5), (9000000, 9999999, 6)), '978-99934': ((0, 1999999, 1), (2000000, 7999999, 2), (8000000, 9999999, 3)), '978-99935': ((0, 2999999, 1), (3000000, 5999999, 2), (6000000, 6999999, 3), (7000000, 8999999, 1), (9000000, 9999999, 2)), '978-99936': ((0, 999999, 1), (1000000, 5999999, 2), (6000000, 9999999, 3)), '978-99937': ((0, 1999999, 1), (2000000, 5999999, 2), (6000000, 9999999, 3)), '978-99930': ((0, 4999999, 1), (5000000, 7999999, 2), (8000000, 9999999, 3)), '978-99931': ((0, 4999999, 1), (5000000, 7999999, 2), (8000000, 9999999, 3)), '978-99932': ((0, 999999, 1), (1000000, 5999999, 2), (6000000, 6999999, 3), (7000000, 7999999, 1), (8000000, 9999999, 2)), '978-99933': ((0, 2999999, 1), (3000000, 5999999, 2), (6000000, 9999999, 3)), '978-620': ((0, 9999999, 1),), '978-621': ((0, 2999999, 2), (3000000, 3999999, 0), (4000000, 5999999, 3), (6000000, 7999999, 0), (8000000, 8999999, 4), (9000000, 9499999, 0), (9500000, 9999999, 5)), '978-99938': ((0, 1999999, 1), (2000000, 5999999, 2), (6000000, 8999999, 3), (9000000, 9999999, 2)), '978-99939': ((0, 5999999, 1), (6000000, 8999999, 2), (9000000, 9999999, 3)), '978-9925': ((0, 2999999, 1), (3000000, 5499999, 2), (5500000, 7349999, 3), (7350000, 9999999, 4)), '978-9924': ((0, 2999999, 0), (3000000, 3999999, 2), (4000000, 4999999, 0), (5000000, 6499999, 3), (6500000, 8999999, 0), (9000000, 9999999, 4)), '978-9927': ((0, 999999, 2), (1000000, 3999999, 3), (4000000, 4999999, 4), (5000000, 9999999, 0)), '978-9926': ((0, 1999999, 1), (2000000, 3999999, 2), (4000000, 7999999, 3), (8000000, 9999999, 4)), '978-9929': ((0, 3999999, 1), (4000000, 5499999, 2), (5500000, 7999999, 3), (8000000, 9999999, 4)), '978-9938': ((0, 7999999, 2), (8000000, 9499999, 3), (9500000, 9999999, 4)), '979-10': ((0, 1999999, 2), (2000000, 6999999, 3), (7000000, 8999999, 4), (9000000, 9759999, 5), (9760000, 9999999, 6)), '978-9987': ((0, 3999999, 2), (4000000, 8799999, 3), (8800000, 9999999, 4)), '978-99941': ((0, 2999999, 1), (3000000, 7999999, 2), (8000000, 9999999, 3)), '978-99940': ((0, 999999, 1), (1000000, 6999999, 2), (7000000, 9999999, 3)), '978-99943': ((0, 2999999, 1), (3000000, 5999999, 2), (6000000, 9999999, 3)), '978-99942': ((0, 4999999, 1), (5000000, 7999999, 2), (8000000, 9999999, 3)), '978-99945': ((0, 5999999, 1), (6000000, 8999999, 2), (9000000, 9999999, 3)), '978-99944': ((0, 4999999, 1), (5000000, 7999999, 2), (8000000, 9999999, 3)), '978-99947': ((0, 2999999, 1), (3000000, 6999999, 2), (7000000, 9999999, 3)), '978-99946': ((0, 2999999, 1), (3000000, 5999999, 2), (6000000, 9999999, 3)), '978-99949': ((0, 1999999, 1), (2000000, 8999999, 2), (9000000, 9999999, 3)), '978-99948': ((0, 4999999, 1), (5000000, 7999999, 2), (8000000, 9999999, 3)), '978-9950': ((0, 2999999, 2), (3000000, 8499999, 3), (8500000, 9999999, 4)), '978-9951': ((0, 3999999, 2), (4000000, 8499999, 3), (8500000, 9999999, 4)), '978-9952': ((0, 1999999, 1), (2000000, 3999999, 2), (4000000, 7999999, 3), (8000000, 9999999, 4)), '978-9953': ((0, 999999, 1), (1000000, 3999999, 2), (4000000, 5999999, 3), (6000000, 8999999, 2), (9000000, 9999999, 4)), '978-9954': ((0, 1999999, 1), (2000000, 3999999, 2), (4000000, 7999999, 3), (8000000, 9999999, 4)), '978-9955': ((0, 3999999, 2), (4000000, 9299999, 3), (9300000, 9999999, 4)), '978-9956': ((0, 999999, 1), (1000000, 3999999, 2), (4000000, 8999999, 3), (9000000, 9999999, 4)), '978-9957': ((0, 3999999, 2), (4000000, 6999999, 3), (7000000, 8499999, 2), (8500000, 8799999, 4), (8800000, 9999999, 2)), '978-9958': ((0, 199999, 2), (200000, 299999, 3), (300000, 399999, 4), (400000, 899999, 3), (900000, 999999, 4), (1000000, 1899999, 2), (1900000, 1999999, 4), (2000000, 4999999, 2), (5000000, 8999999, 3), (9000000, 9999999, 4)), '978-9986': ((0, 3999999, 2), (4000000, 8999999, 3), (9000000, 9399999, 4), (9400000, 9699999, 3), (9700000, 9999999, 2)), '978-989': ((0, 1999999, 1), (2000000, 5499999, 2), (5500000, 7999999, 3), (8000000, 9499999, 4), (9500000, 9999999, 5)), '978-988': ((0, 1199999, 2), (1200000, 1499999, 5), (1500000, 1699999, 5), (1700000, 1999999, 5), (2000000, 7999999, 3), (8000000, 9699999, 4), (9700000, 9999999, 5)), '978-985': ((0, 3999999, 2), (4000000, 5999999, 3), (6000000, 8999999, 4), (9000000, 9999999, 5)), '978-984': ((0, 3999999, 2), (4000000, 7999999, 3), (8000000, 8999999, 4), (9000000, 9999999, 5)), '978-987': ((0, 999999, 2), (1000000, 1999999, 4), (2000000, 2999999, 5), (3000000, 3599999, 2), (3600000, 3999999, 4), (4000000, 4199999, 4), (4200000, 4399999, 2), (4400000, 4499999, 4), (4500000, 4899999, 5), (4900000, 4999999, 4), (5000000, 8999999, 3), (9000000, 9499999, 4), (9500000, 9999999, 5)), '978-986': ((0, 1199999, 2), (1200000, 5599999, 3), (5600000, 7999999, 4), (8000000, 9999999, 5)), '978-981': ((0, 1199999, 2), (1200000, 1699999, 2), (1700000, 1999999, 5), (2000000, 2899999, 3), (2900000, 2999999, 3), (3000000, 3099999, 4), (3100000, 3999999, 3), (4000000, 9999999, 4)), '978-980': ((0, 1999999, 2), (2000000, 5999999, 3), (6000000, 9999999, 4)), '978-983': ((0, 199999, 2), (200000, 1999999, 3), (2000000, 3999999, 4), (4000000, 4499999, 5), (4500000, 4999999, 2), (5000000, 7999999, 2), (8000000, 8999999, 3), (9000000, 9899999, 4), (9900000, 9999999, 5)), '978-982': ((0, 999999, 2), (1000000, 6999999, 3), (7000000, 8999999, 2), (9000000, 9799999, 4), (9800000, 9999999, 5)), '978-99952': ((0, 4999999, 1), (5000000, 7999999, 2), (8000000, 9999999, 3)), '978-99953': ((0, 2999999, 1), (3000000, 7999999, 2), (8000000, 9399999, 3), (9400000, 9999999, 2)), '978-99950': ((0, 4999999, 1), (5000000, 7999999, 2), (8000000, 9999999, 3)), '978-99951': ((0, 9999999, 0),), '978-99956': ((0, 5999999, 2), (6000000, 8599999, 3), (8600000, 9999999, 2)), '978-99957': ((0, 1999999, 1), (2000000, 7999999, 2), (8000000, 9999999, 3)), '978-99954': ((0, 2999999, 1), (3000000, 6999999, 2), (7000000, 8799999, 3), (8800000, 9999999, 2)), '978-99955': ((0, 1999999, 1), (2000000, 5999999, 2), (6000000, 7999999, 3), (8000000, 9999999, 2)), '978-99958': ((0, 4999999, 1), (5000000, 9399999, 2), (9400000, 9499999, 3), (9500000, 9999999, 3)), '978-99959': ((0, 2999999, 1), (3000000, 5999999, 2), (6000000, 9999999, 3)), '978-9943': ((0, 2999999, 2), (3000000, 3999999, 3), (4000000, 9749999, 4), (9750000, 9999999, 3)), '978-9942': ((0, 8499999, 2), (8500000, 8999999, 4), (9000000, 9849999, 3), (9850000, 9999999, 4)), '978-9941': ((0, 999999, 1), (1000000, 3999999, 2), (4000000, 8999999, 3), (9000000, 9999999, 4)), '978-9940': ((0, 1999999, 1), (2000000, 4999999, 2), (5000000, 8999999, 3), (9000000, 9999999, 4)), '978-9947': ((0, 1999999, 1), (2000000, 7999999, 2), (8000000, 9999999, 3)), '978-9946': ((0, 1999999, 1), (2000000, 3999999, 2), (4000000, 8999999, 3), (9000000, 9999999, 4)), '978-9945': ((0, 99999, 2), (100000, 799999, 3), (800000, 3999999, 2), (4000000, 5699999, 3), (5700000, 5799999, 2), (5800000, 8499999, 3), (8500000, 9999999, 4)), '978-9944': ((0, 999999, 4), (1000000, 4999999, 3), (5000000, 5999999, 4), (6000000, 6999999, 2), (7000000, 7999999, 3), (8000000, 8999999, 2), (9000000, 9999999, 3)), '978-9949': ((0, 999999, 1), (1000000, 3999999, 2), (4000000, 7499999, 3), (7500000, 8999999, 2), (9000000, 9999999, 4)), '978-9948': ((0, 3999999, 2), (4000000, 8499999, 3), (8500000, 9999999, 4)), '978-615': ((0, 999999, 2), (1000000, 4999999, 3), (5000000, 7999999, 4), (8000000, 8999999, 5), (9000000, 9999999, 0)), '978-614': ((0, 3999999, 2), (4000000, 7999999, 3), (8000000, 9499999, 4), (9500000, 9999999, 5)), '978-617': ((0, 4999999, 2), (5000000, 6999999, 3), (7000000, 8999999, 4), (9000000, 9999999, 5)), '978-616': ((0, 1999999, 2), (2000000, 6999999, 3), (7000000, 8999999, 4), (9000000, 9999999, 5)), '978-611': ((0, 9999999, 0),), '978-613': ((0, 9999999, 1),), '978-612': ((0, 2999999, 2), (3000000, 3999999, 3), (4000000, 4499999, 4), (4500000, 4999999, 5), (5000000, 9999999, 2)), '978-619': ((0, 1499999, 2), (1500000, 6999999, 3), (7000000, 8999999, 4), (9000000, 9999999, 5)), '978-618': ((0, 1999999, 2), (2000000, 4999999, 3), (5000000, 7999999, 4), (8000000, 9999999, 5)), '978-99974': ((0, 3999999, 0), (4000000, 7999999, 2), (8000000, 9999999, 3)), '978-99967': ((0, 1999999, 1), (2000000, 5999999, 2), (6000000, 8999999, 3), (9000000, 9999999, 0)), '978-99966': ((0, 2999999, 1), (3000000, 6999999, 2), (7000000, 7999999, 3), (8000000, 9499999, 2), (9500000, 9999999, 0)), '978-99965': ((0, 3999999, 1), (4000000, 6999999, 2), (7000000, 9999999, 3)), '978-99964': ((0, 1999999, 1), (2000000, 7999999, 2), (8000000, 9999999, 3)), '978-99963': ((0, 4999999, 2), (5000000, 9199999, 3), (9200000, 9999999, 2)), '978-99962': ((0, 4999999, 1), (5000000, 7999999, 2), (8000000, 9999999, 3)), '978-99961': ((0, 3999999, 1), (4000000, 8999999, 2), (9000000, 9999999, 3)), '978-99960': ((0, 999999, 1), (1000000, 9499999, 2), (9500000, 9999999, 3)), '978-99969': ((0, 4999999, 1), (5000000, 7999999, 2), (8000000, 9999999, 3)), '978-99968': ((0, 3999999, 1), (4000000, 5999999, 3), (6000000, 8999999, 2), (9000000, 9999999, 3)), '978-9976': ((0, 5999999, 1), (6000000, 8999999, 2), (9000000, 9899999, 3), (9900000, 9999999, 4)), '978-9977': ((0, 8999999, 2), (9000000, 9899999, 3), (9900000, 9999999, 4)), '978-9974': ((0, 2999999, 1), (3000000, 5499999, 2), (5500000, 7499999, 3), (7500000, 9499999, 4), (9500000, 9999999, 2)), '978-9975': ((0, 999999, 1), (1000000, 2999999, 3), (3000000, 3999999, 4), (4000000, 4499999, 4), (4500000, 8999999, 2), (9000000, 9499999, 3), (9500000, 9999999, 4)), '978-9972': ((0, 999999, 2), (1000000, 1999999, 1), (2000000, 2499999, 3), (2500000, 2999999, 4), (3000000, 5999999, 2), (6000000, 8999999, 3), (9000000, 9999999, 4)), '978-9973': ((0, 599999, 2), (600000, 899999, 3), (900000, 999999, 4), (1000000, 6999999, 2), (7000000, 9699999, 3), (9700000, 9999999, 4)), '978-9970': ((0, 3999999, 2), (4000000, 8999999, 3), (9000000, 9999999, 4)), '978-9971': ((0, 5999999, 1), (6000000, 8999999, 2), (9000000, 9899999, 3), (9900000, 9999999, 4)), '978-99975': ((0, 3999999, 1), (4000000, 7999999, 2), (8000000, 9999999, 3)), '978-9978': ((0, 2999999, 2), (3000000, 3999999, 3), (4000000, 9499999, 2), (9500000, 9899999, 3), (9900000, 9999999, 4)), '978-9979': ((0, 4999999, 1), (5000000, 6499999, 2), (6500000, 6599999, 3), (6600000, 7599999, 2), (7600000, 8999999, 3), (9000000, 9999999, 4)), '978-602': ((0, 799999, 2), (800000, 899999, 4), (900000, 1099999, 4), (1100000, 1199999, 4), (1200000, 1399999, 4), (1400000, 1499999, 5), (1500000, 1699999, 4), (1700000, 1799999, 5), (1800000, 1899999, 5), (1900000, 1999999, 5), (2000000, 6999999, 3), (7000000, 7499999, 5), (7500000, 7999999, 4), (8000000, 9499999, 4), (9500000, 9999999, 5)), '978-603': ((0, 499999, 2), (500000, 4999999, 2), (5000000, 7999999, 3), (8000000, 8999999, 4), (9000000, 9999999, 5)), '978-600': ((0, 999999, 2), (1000000, 4999999, 3), (5000000, 8999999, 4), (9000000, 9999999, 5)), '978-601': ((0, 1999999, 2), (2000000, 6999999, 3), (7000000, 7999999, 4), (8000000, 8499999, 5), (8500000, 9999999, 2)), '978-606': ((0, 999999, 1), (1000000, 4999999, 2), (5000000, 7999999, 3), (8000000, 9199999, 4), (9200000, 9999999, 5)), '978-607': ((0, 3999999, 2), (4000000, 7499999, 3), (7500000, 9499999, 4), (9500000, 9999999, 5)), '978-604': ((0, 4999999, 1), (5000000, 8999999, 2), (9000000, 9799999, 3), (9800000, 9999999, 4)), '978-605': ((0, 99999, 0), (100000, 299999, 2), (300000, 399999, 3), (400000, 999999, 2), (1000000, 3999999, 3), (4000000, 5999999, 4), (6000000, 8999999, 5), (9000000, 9999999, 4)), '978-608': ((0, 999999, 1), (1000000, 1999999, 2), (2000000, 4499999, 3), (4500000, 6499999, 4), (6500000, 6999999, 5), (7000000, 9999999, 1)), '978-609': ((0, 3999999, 2), (4000000, 7999999, 3), (8000000, 9499999, 4), (9500000, 9999999, 5))}
-RDDATE='2015060310:50:18WEST'
+ranges = {'978-0': ((0, 1999999, 2), (2000000, 2279999, 3), (2280000, 2289999, 4), (2290000, 3689999, 3), (3690000, 3699999, 4), (3700000, 6389999, 3), (6390000, 6398999, 4), (6399000, 6399999, 7), (6400000, 6479999, 3), (6480000, 6489999, 7), (6490000, 6549999, 3), (6550000, 6559999, 4), (6560000, 6999999, 3), (7000000, 8499999, 4), (8500000, 8999999, 5), (9000000, 9499999, 6), (9500000, 9999999, 7)), '978-1': ((0, 999999, 2), (1000000, 3999999, 3), (4000000, 5499999, 4), (5500000, 7169999, 5), (7170000, 7319999, 4), (7320000, 7399999, 7), (7400000, 7749999, 5), (7750000, 7753999, 7), (7754000, 7899999, 5), (7900000, 7999999, 4), (8000000, 8697999, 5), (8698000, 9163999, 6), (9164000, 9165059, 7), (9165060, 9729999, 6), (9730000, 9877999, 4), (9878000, 9989999, 6), (9990000, 9999999, 7)), '978-2': ((0, 1999999, 2), (2000000, 3499999, 3), (3500000, 3999999, 5), (4000000, 4899999, 3), (4900000, 4949999, 6), (4950000, 6999999, 3), (7000000, 8399999, 4), (8400000, 8999999, 5), (9000000, 9197999, 6), (9198000, 9198099, 5), (9198100, 9199429, 6), (9199430, 9199689, 7), (9199690, 9499999, 6), (9500000, 9999999, 7)), '978-3': ((0, 299999, 2), (300000, 339999, 3), (340000, 369999, 4), (370000, 399999, 5), (400000, 1999999, 2), (2000000, 6999999, 3), (7000000, 8499999, 4), (8500000, 8999999, 5), (9000000, 9499999, 6), (9500000, 9539999, 7), (9540000, 9699999, 5), (9700000, 9899999, 7), (9900000, 9949999, 5), (9950000, 9999999, 5)), '978-4': ((0, 1999999, 2), (2000000, 6999999, 3), (7000000, 8499999, 4), (8500000, 8999999, 5), (9000000, 9499999, 6), (9500000, 9999999, 7)), '978-5': ((0, 49999, 5), (50000, 99999, 4), (100000, 1999999, 2), (2000000, 4209999, 3), (4210000, 4299999, 4), (4300000, 4309999, 3), (4310000, 4399999, 4), (4400000, 4409999, 3), (4410000, 4499999, 4), (4500000, 6039999, 3), (6040000, 6049999, 7), (6050000, 6999999, 3), (7000000, 8499999, 4), (8500000, 8999999, 5), (9000000, 9099999, 6), (9100000, 9199999, 5), (9200000, 9299999, 4), (9300000, 9499999, 5), (9500000, 9500999, 7), (9501000, 9799999, 4), (9800000, 9899999, 5), (9900000, 9909999, 7), (9910000, 9999999, 4)), '978-600': ((0, 999999, 2), (1000000, 4999999, 3), (5000000, 8999999, 4), (9000000, 9867999, 5), (9868000, 9929999, 4), (9930000, 9959999, 3), (9960000, 9999999, 5)), '978-601': ((0, 1999999, 2), (2000000, 6999999, 3), (7000000, 7999999, 4), (8000000, 8499999, 5), (8500000, 9999999, 2)), '978-602': ((0, 699999, 2), (700000, 1399999, 4), (1400000, 1499999, 5), (1500000, 1699999, 4), (1700000, 1999999, 5), (2000000, 4999999, 3), (5000000, 5399999, 5), (5400000, 5999999, 4), (6000000, 6199999, 5), (6200000, 6999999, 4), (7000000, 7499999, 5), (7500000, 9499999, 4), (9500000, 9999999, 5)), '978-603': ((0, 499999, 2), (500000, 4999999, 2), (5000000, 7999999, 3), (8000000, 8999999, 4), (9000000, 9999999, 5)), '978-604': ((0, 4999999, 1), (5000000, 8999999, 2), (9000000, 9799999, 3), (9800000, 9999999, 4)), '978-605': ((0, 99999, 0), (100000, 299999, 2), (300000, 399999, 3), (400000, 999999, 2), (1000000, 1999999, 3), (2000000, 2399999, 4), (2400000, 3999999, 3), (4000000, 5999999, 4), (6000000, 7499999, 5), (7500000, 7999999, 4), (8000000, 8999999, 5), (9000000, 9999999, 4)), '978-606': ((0, 999999, 3), (1000000, 4999999, 2), (5000000, 7999999, 3), (8000000, 9099999, 4), (9100000, 9199999, 3), (9200000, 9749999, 5), (9750000, 9999999, 3)), '978-607': ((0, 3999999, 2), (4000000, 7499999, 3), (7500000, 9499999, 4), (9500000, 9999999, 5)), '978-608': ((0, 999999, 1), (1000000, 1999999, 2), (2000000, 4499999, 3), (4500000, 6499999, 4), (6500000, 6999999, 5), (7000000, 9999999, 1)), '978-609': ((0, 3999999, 2), (4000000, 7999999, 3), (8000000, 9499999, 4), (9500000, 9999999, 5)), '978-611': ((0, 9999999, 0),), '978-612': ((0, 2999999, 2), (3000000, 3999999, 3), (4000000, 4499999, 4), (4500000, 4999999, 5), (5000000, 9999999, 2)), '978-613': ((0, 9999999, 1),), '978-614': ((0, 3999999, 2), (4000000, 7999999, 3), (8000000, 9499999, 4), (9500000, 9999999, 5)), '978-615': ((0, 999999, 2), (1000000, 4999999, 3), (5000000, 7999999, 4), (8000000, 8999999, 5), (9000000, 9999999, 0)), '978-616': ((0, 1999999, 2), (2000000, 6999999, 3), (7000000, 8999999, 4), (9000000, 9999999, 5)), '978-617': ((0, 4999999, 2), (5000000, 6999999, 3), (7000000, 8999999, 4), (9000000, 9999999, 5)), '978-618': ((0, 1999999, 2), (2000000, 4999999, 3), (5000000, 7999999, 4), (8000000, 9999999, 5)), '978-619': ((0, 1499999, 2), (1500000, 6999999, 3), (7000000, 8999999, 4), (9000000, 9999999, 5)), '978-620': ((0, 9999999, 1),), '978-621': ((0, 2999999, 2), (3000000, 3999999, 0), (4000000, 5999999, 3), (6000000, 7999999, 0), (8000000, 8999999, 4), (9000000, 9499999, 0), (9500000, 9999999, 5)), '978-622': ((0, 399999, 2), (400000, 1999999, 0), (2000000, 2199999, 3), (2200000, 5999999, 0), (6000000, 6399999, 4), (6400000, 9899999, 0), (9900000, 9999999, 5)), '978-623': ((0, 999999, 2), (1000000, 1999999, 0), (2000000, 2999999, 3), (3000000, 6999999, 0), (7000000, 7999999, 4), (8000000, 9999999, 0)), '978-65': ((0, 4999999, 0), (5000000, 5004999, 4), (5005000, 7999999, 0), (8000000, 8019999, 5), (8020000, 8999999, 0), (9000000, 9000999, 6), (9001000, 9999999, 0)), '978-7': ((0, 999999, 2), (1000000, 4999999, 3), (5000000, 7999999, 4), (8000000, 8999999, 5), (9000000, 9999999, 6)), '978-80': ((0, 1999999, 2), (2000000, 6999999, 3), (7000000, 8499999, 4), (8500000, 8999999, 5), (9000000, 9989999, 6), (9990000, 9999999, 5)), '978-81': ((0, 1999999, 2), (2000000, 6999999, 3), (7000000, 8499999, 4), (8500000, 8999999, 5), (9000000, 9999999, 6)), '978-82': ((0, 1999999, 2), (2000000, 6899999, 3), (6900000, 6999999, 6), (7000000, 8999999, 4), (9000000, 9899999, 5), (9900000, 9999999, 6)), '978-83': ((0, 1999999, 2), (2000000, 5999999, 3), (6000000, 6999999, 5), (7000000, 8499999, 4), (8500000, 8999999, 5), (9000000, 9999999, 6)), '978-84': ((0, 1199999, 2), (1200000, 1299999, 6), (1300000, 1399999, 4), (1400000, 1499999, 3), (1500000, 1999999, 5), (2000000, 6999999, 3), (7000000, 8499999, 4), (8500000, 8999999, 5), (9000000, 9199999, 4), (9200000, 9239999, 6), (9240000, 9299999, 5), (9300000, 9499999, 6), (9500000, 9699999, 5), (9700000, 9999999, 4)), '978-85': ((0, 1999999, 2), (2000000, 4549999, 3), (4550000, 4552999, 6), (4553000, 4559999, 5), (4560000, 5289999, 3), (5290000, 5319999, 5), (5320000, 5339999, 4), (5340000, 5399999, 3), (5400000, 5402999, 5), (5403000, 5403999, 5), (5404000, 5404999, 6), (5405000, 5408999, 5), (5409000, 5409999, 6), (5410000, 5439999, 5), (5440000, 5479999, 4), (5480000, 5499999, 5), (5500000, 5999999, 4), (6000000, 6999999, 5), (7000000, 8499999, 4), (8500000, 8999999, 5), (9000000, 9249999, 6), (9250000, 9449999, 5), (9450000, 9599999, 4), (9600000, 9799999, 2), (9800000, 9999999, 5)), '978-86': ((0, 2999999, 2), (3000000, 5999999, 3), (6000000, 7999999, 4), (8000000, 8999999, 5), (9000000, 9999999, 6)), '978-87': ((0, 2999999, 2), (3000000, 3999999, 0), (4000000, 6499999, 3), (6500000, 6999999, 0), (7000000, 7999999, 4), (8000000, 8499999, 0), (8500000, 9499999, 5), (9500000, 9699999, 0), (9700000, 9999999, 6)), '978-88': ((0, 1999999, 2), (2000000, 3189999, 3), (3190000, 3229999, 5), (3230000, 3269999, 3), (3270000, 3389999, 4), (3390000, 5489999, 3), (5490000, 5549999, 4), (5550000, 5999999, 3), (6000000, 8499999, 4), (8500000, 8999999, 5), (9000000, 9099999, 6), (9100000, 9299999, 3), (9300000, 9399999, 4), (9400000, 9479999, 6), (9480000, 9499999, 5), (9500000, 9999999, 5)), '978-89': ((0, 2499999, 2), (2500000, 5499999, 3), (5500000, 8499999, 4), (8500000, 9499999, 5), (9500000, 9699999, 6), (9700000, 9899999, 5), (9900000, 9999999, 3)), '978-90': ((0, 1999999, 2), (2000000, 4999999, 3), (5000000, 6999999, 4), (7000000, 7999999, 5), (8000000, 8499999, 6), (8500000, 8999999, 4), (9000000, 9099999, 2), (9100000, 9399999, 0), (9400000, 9499999, 2), (9500000, 9999999, 0)), '978-91': ((0, 1999999, 1), (2000000, 4999999, 2), (5000000, 6499999, 3), (6500000, 6999999, 0), (7000000, 7999999, 4), (8000000, 8499999, 0), (8500000, 9499999, 5), (9500000, 9699999, 0), (9700000, 9999999, 6)), '978-92': ((0, 5999999, 1), (6000000, 7999999, 2), (8000000, 8999999, 3), (9000000, 9499999, 4), (9500000, 9899999, 5), (9900000, 9999999, 6)), '978-93': ((0, 999999, 2), (1000000, 4999999, 3), (5000000, 7999999, 4), (8000000, 9499999, 5), (9500000, 9999999, 6)), '978-94': ((0, 5999999, 3), (6000000, 8999999, 4), (9000000, 9999999, 5)), '978-950': ((0, 4999999, 2), (5000000, 8999999, 3), (9000000, 9899999, 4), (9900000, 9999999, 5)), '978-951': ((0, 1999999, 1), (2000000, 5499999, 2), (5500000, 8899999, 3), (8900000, 9499999, 4), (9500000, 9999999, 5)), '978-952': ((0, 1999999, 2), (2000000, 4999999, 3), (5000000, 5999999, 4), (6000000, 6599999, 2), (6600000, 6699999, 4), (6700000, 6999999, 5), (7000000, 7999999, 4), (8000000, 9499999, 2), (9500000, 9899999, 4), (9900000, 9999999, 5)), '978-953': ((0, 999999, 1), (1000000, 1499999, 2), (1500000, 4799999, 3), (4800000, 4999999, 5), (5000000, 5009999, 3), (5010000, 5099999, 5), (5100000, 5499999, 2), (5500000, 5999999, 5), (6000000, 9499999, 4), (9500000, 9999999, 5)), '978-954': ((0, 2899999, 2), (2900000, 2999999, 4), (3000000, 7999999, 3), (8000000, 8999999, 4), (9000000, 9299999, 5), (9300000, 9999999, 4)), '978-955': ((0, 1999999, 4), (2000000, 3399999, 2), (3400000, 3499999, 4), (3500000, 3549999, 4), (3550000, 3599999, 5), (3600000, 3799999, 4), (3800000, 3899999, 5), (3900000, 4099999, 4), (4100000, 4499999, 5), (4500000, 4999999, 4), (5000000, 5499999, 5), (5500000, 7129999, 3), (7130000, 7149999, 5), (7150000, 9499999, 4), (9500000, 9999999, 5)), '978-956': ((0, 899999, 2), (900000, 999999, 5), (1000000, 1999999, 2), (2000000, 5999999, 3), (6000000, 6999999, 4), (7000000, 9999999, 4)), '978-957': ((0, 299999, 2), (300000, 499999, 4), (500000, 1999999, 2), (2000000, 2099999, 4), (2100000, 2799999, 2), (2800000, 3099999, 5), (3100000, 4399999, 2), (4400000, 8199999, 3), (8200000, 9699999, 4), (9700000, 9999999, 5)), '978-958': ((0, 5399999, 2), (5400000, 5599999, 4), (5600000, 5699999, 5), (5700000, 5999999, 5), (6000000, 7999999, 3), (8000000, 9499999, 4), (9500000, 9999999, 5)), '978-959': ((0, 1999999, 2), (2000000, 6999999, 3), (7000000, 8499999, 4), (8500000, 9999999, 5)), '978-960': ((0, 1999999, 2), (2000000, 6599999, 3), (6600000, 6899999, 4), (6900000, 6999999, 3), (7000000, 8499999, 4), (8500000, 9299999, 5), (9300000, 9399999, 2), (9400000, 9799999, 4), (9800000, 9999999, 5)), '978-961': ((0, 1999999, 2), (2000000, 5999999, 3), (6000000, 8999999, 4), (9000000, 9499999, 5), (9500000, 9999999, 0)), '978-962': ((0, 1999999, 2), (2000000, 6999999, 3), (7000000, 8499999, 4), (8500000, 8699999, 5), (8700000, 8999999, 4), (9000000, 9999999, 3)), '978-963': ((0, 1999999, 2), (2000000, 6999999, 3), (7000000, 8499999, 4), (8500000, 8999999, 5), (9000000, 9999999, 4)), '978-964': ((0, 1499999, 2), (1500000, 2499999, 3), (2500000, 2999999, 4), (3000000, 5499999, 3), (5500000, 8999999, 4), (9000000, 9699999, 5), (9700000, 9899999, 3), (9900000, 9999999, 4)), '978-965': ((0, 1999999, 2), (2000000, 5999999, 3), (6000000, 6999999, 0), (7000000, 7999999, 4), (8000000, 8999999, 0), (9000000, 9999999, 5)), '978-966': ((0, 1299999, 2), (1300000, 1399999, 3), (1400000, 1499999, 2), (1500000, 1699999, 4), (1700000, 1999999, 3), (2000000, 2789999, 4), (2790000, 2899999, 3), (2900000, 2999999, 4), (3000000, 6999999, 3), (7000000, 8999999, 4), (9000000, 9099999, 5), (9100000, 9499999, 3), (9500000, 9799999, 5), (9800000, 9999999, 3)), '978-967': ((0, 99999, 2), (100000, 999999, 4), (1000000, 1999999, 5), (2000000, 2499999, 4), (2500000, 2999999, 0), (3000000, 4999999, 3), (5000000, 5999999, 4), (6000000, 8999999, 2), (9000000, 9899999, 3), (9900000, 9989999, 4), (9990000, 9999999, 5)), '978-968': ((100000, 3999999, 2), (4000000, 4999999, 3), (5000000, 7999999, 4), (8000000, 8999999, 3), (9000000, 9999999, 4)), '978-969': ((0, 1999999, 1), (2000000, 2299999, 2), (2300000, 2399999, 5), (2400000, 3999999, 2), (4000000, 7499999, 3), (7500000, 9999999, 4)), '978-970': ((100000, 5999999, 2), (6000000, 8999999, 3), (9000000, 9099999, 4), (9100000, 9699999, 5), (9700000, 9999999, 4)), '978-971': ((0, 159999, 3), (160000, 199999, 4), (200000, 299999, 2), (300000, 599999, 4), (600000, 4999999, 2), (5000000, 8499999, 3), (8500000, 9099999, 4), (9100000, 9599999, 5), (9600000, 9699999, 4), (9700000, 9899999, 2), (9900000, 9999999, 4)), '978-972': ((0, 1999999, 1), (2000000, 5499999, 2), (5500000, 7999999, 3), (8000000, 9499999, 4), (9500000, 9999999, 5)), '978-973': ((0, 999999, 1), (1000000, 1699999, 3), (1700000, 1999999, 4), (2000000, 5499999, 2), (5500000, 7599999, 3), (7600000, 8499999, 4), (8500000, 8899999, 5), (8900000, 9499999, 4), (9500000, 9999999, 5)), '978-974': ((0, 1999999, 2), (2000000, 6999999, 3), (7000000, 8499999, 4), (8500000, 8999999, 5), (9000000, 9499999, 5), (9500000, 9999999, 4)), '978-975': ((0, 199999, 5), (200000, 2399999, 2), (2400000, 2499999, 4), (2500000, 5999999, 3), (6000000, 9199999, 4), (9200000, 9899999, 5), (9900000, 9999999, 3)), '978-976': ((0, 3999999, 1), (4000000, 5999999, 2), (6000000, 7999999, 3), (8000000, 9499999, 4), (9500000, 9999999, 5)), '978-977': ((0, 1999999, 2), (2000000, 4999999, 3), (5000000, 6999999, 4), (7000000, 8499999, 3), (8500000, 8999999, 5), (9000000, 9899999, 2), (9900000, 9999999, 3)), '978-978': ((0, 1999999, 3), (2000000, 2999999, 4), (3000000, 7999999, 5), (8000000, 8999999, 4), (9000000, 9999999, 3)), '978-979': ((0, 999999, 3), (1000000, 1499999, 4), (1500000, 1999999, 5), (2000000, 2999999, 2), (3000000, 3999999, 4), (4000000, 7999999, 3), (8000000, 9499999, 4), (9500000, 9999999, 5)), '978-980': ((0, 1999999, 2), (2000000, 5999999, 3), (6000000, 9999999, 4)), '978-981': ((0, 1699999, 2), (1700000, 1999999, 5), (2000000, 2999999, 3), (3000000, 3099999, 4), (3100000, 3999999, 3), (4000000, 9999999, 4)), '978-982': ((0, 999999, 2), (1000000, 6999999, 3), (7000000, 8999999, 2), (9000000, 9799999, 4), (9800000, 9999999, 5)), '978-983': ((0, 199999, 2), (200000, 1999999, 3), (2000000, 3999999, 4), (4000000, 4499999, 5), (4500000, 4999999, 2), (5000000, 7999999, 2), (8000000, 8999999, 3), (9000000, 9899999, 4), (9900000, 9999999, 5)), '978-984': ((0, 3999999, 2), (4000000, 7999999, 3), (8000000, 8999999, 4), (9000000, 9999999, 5)), '978-985': ((0, 3999999, 2), (4000000, 5999999, 3), (6000000, 8799999, 4), (8800000, 8999999, 3), (9000000, 9999999, 5)), '978-986': ((0, 1199999, 2), (1200000, 5599999, 3), (5600000, 7999999, 4), (8000000, 9999999, 5)), '978-987': ((0, 999999, 2), (1000000, 1999999, 4), (2000000, 2999999, 5), (3000000, 3599999, 2), (3600000, 3999999, 4), (4000000, 4199999, 4), (4200000, 4399999, 2), (4400000, 4499999, 4), (4500000, 4899999, 5), (4900000, 4999999, 4), (5000000, 8999999, 3), (9000000, 9499999, 4), (9500000, 9999999, 5)), '978-988': ((0, 1199999, 2), (1200000, 1499999, 5), (1500000, 1699999, 5), (1700000, 1999999, 5), (2000000, 7699999, 3), (7700000, 7999999, 5), (8000000, 9699999, 4), (9700000, 9999999, 5)), '978-989': ((0, 1999999, 1), (2000000, 5399999, 2), (5400000, 5499999, 5), (5500000, 7999999, 3), (8000000, 9499999, 4), (9500000, 9999999, 5)), '978-9920': ((0, 3499999, 0), (3500000, 3999999, 2), (4000000, 6999999, 0), (7000000, 7999999, 3), (8000000, 9499999, 0), (9500000, 9999999, 4)), '978-9921': ((0, 999999, 1), (1000000, 2999999, 0), (3000000, 3999999, 2), (4000000, 6999999, 0), (7000000, 8999999, 3), (9000000, 9699999, 0), (9700000, 9999999, 4)), '978-9922': ((0, 1999999, 0), (2000000, 2999999, 2), (3000000, 5999999, 0), (6000000, 7999999, 3), (8000000, 8999999, 0), (9000000, 9999999, 4)), '978-9923': ((0, 999999, 1), (1000000, 4999999, 2), (5000000, 6999999, 0), (7000000, 8999999, 3), (9000000, 9699999, 0), (9700000, 9999999, 4)), '978-9924': ((0, 2999999, 0), (3000000, 3999999, 2), (4000000, 4999999, 0), (5000000, 6499999, 3), (6500000, 8999999, 0), (9000000, 9999999, 4)), '978-9925': ((0, 2999999, 1), (3000000, 5499999, 2), (5500000, 7349999, 3), (7350000, 9999999, 4)), '978-9926': ((0, 1999999, 1), (2000000, 3999999, 2), (4000000, 7999999, 3), (8000000, 9999999, 4)), '978-9927': ((0, 999999, 2), (1000000, 3999999, 3), (4000000, 4999999, 4), (5000000, 9999999, 0)), '978-9928': ((0, 999999, 2), (1000000, 3999999, 3), (4000000, 4999999, 4), (5000000, 9999999, 0)), '978-9929': ((0, 3999999, 1), (4000000, 5499999, 2), (5500000, 7999999, 3), (8000000, 9999999, 4)), '978-9930': ((0, 4999999, 2), (5000000, 9399999, 3), (9400000, 9999999, 4)), '978-9931': ((0, 2999999, 2), (3000000, 8999999, 3), (9000000, 9999999, 4)), '978-9932': ((0, 3999999, 2), (4000000, 8499999, 3), (8500000, 9999999, 4)), '978-9933': ((0, 999999, 1), (1000000, 3999999, 2), (4000000, 8999999, 3), (9000000, 9999999, 4)), '978-9934': ((0, 999999, 1), (1000000, 4999999, 2), (5000000, 7999999, 3), (8000000, 9999999, 4)), '978-9935': ((0, 999999, 1), (1000000, 3999999, 2), (4000000, 8999999, 3), (9000000, 9999999, 4)), '978-9936': ((0, 1999999, 1), (2000000, 3999999, 2), (4000000, 7999999, 3), (8000000, 9999999, 4)), '978-9937': ((0, 2999999, 1), (3000000, 4999999, 2), (5000000, 7999999, 3), (8000000, 9999999, 4)), '978-9938': ((0, 7999999, 2), (8000000, 9499999, 3), (9500000, 9999999, 4)), '978-9939': ((0, 4999999, 1), (5000000, 7999999, 2), (8000000, 8999999, 3), (9000000, 9999999, 4)), '978-9940': ((0, 1999999, 1), (2000000, 4999999, 2), (5000000, 8999999, 3), (9000000, 9999999, 4)), '978-9941': ((0, 999999, 1), (1000000, 3999999, 2), (4000000, 7999999, 3), (8000000, 8999999, 1), (9000000, 9999999, 4)), '978-9942': ((0, 7499999, 2), (7500000, 8499999, 3), (8500000, 8999999, 4), (9000000, 9849999, 3), (9850000, 9999999, 4)), '978-9943': ((0, 2999999, 2), (3000000, 3999999, 3), (4000000, 9749999, 4), (9750000, 9999999, 3)), '978-9944': ((0, 999999, 4), (1000000, 4999999, 3), (5000000, 5999999, 4), (6000000, 6999999, 2), (7000000, 7999999, 3), (8000000, 8999999, 2), (9000000, 9999999, 3)), '978-9945': ((0, 99999, 2), (100000, 799999, 3), (800000, 3999999, 2), (4000000, 5699999, 3), (5700000, 5799999, 2), (5800000, 8499999, 3), (8500000, 9999999, 4)), '978-9946': ((0, 1999999, 1), (2000000, 3999999, 2), (4000000, 8999999, 3), (9000000, 9999999, 4)), '978-9947': ((0, 1999999, 1), (2000000, 7999999, 2), (8000000, 9999999, 3)), '978-9948': ((0, 3999999, 2), (4000000, 8499999, 3), (8500000, 9999999, 4)), '978-9949': ((0, 499999, 2), (500000, 999999, 0), (1000000, 3999999, 2), (4000000, 6999999, 3), (7000000, 7199999, 2), (7200000, 7499999, 4), (7500000, 8999999, 2), (9000000, 9999999, 4)), '978-9950': ((0, 2999999, 2), (3000000, 8499999, 3), (8500000, 9999999, 4)), '978-9951': ((0, 3999999, 2), (4000000, 8499999, 3), (8500000, 9999999, 4)), '978-9952': ((0, 1999999, 1), (2000000, 3999999, 2), (4000000, 7999999, 3), (8000000, 9999999, 4)), '978-9953': ((0, 999999, 1), (1000000, 3999999, 2), (4000000, 5999999, 3), (6000000, 8999999, 2), (9000000, 9299999, 4), (9300000, 9699999, 2), (9700000, 9999999, 3)), '978-9954': ((0, 1999999, 1), (2000000, 3999999, 2), (4000000, 7999999, 3), (8000000, 9899999, 4), (9900000, 9999999, 2)), '978-9955': ((0, 3999999, 2), (4000000, 9299999, 3), (9300000, 9999999, 4)), '978-9956': ((0, 999999, 1), (1000000, 3999999, 2), (4000000, 8999999, 3), (9000000, 9999999, 4)), '978-9957': ((0, 3999999, 2), (4000000, 6499999, 3), (6500000, 6799999, 2), (6800000, 6999999, 3), (7000000, 8499999, 2), (8500000, 8799999, 4), (8800000, 9999999, 2)), '978-9958': ((0, 199999, 2), (200000, 299999, 3), (300000, 399999, 4), (400000, 899999, 3), (900000, 999999, 4), (1000000, 1899999, 2), (1900000, 1999999, 4), (2000000, 4999999, 2), (5000000, 8999999, 3), (9000000, 9999999, 4)), '978-9959': ((0, 1999999, 1), (2000000, 7999999, 2), (8000000, 9499999, 3), (9500000, 9699999, 4), (9700000, 9799999, 3), (9800000, 9999999, 2)), '978-9960': ((0, 5999999, 2), (6000000, 8999999, 3), (9000000, 9999999, 4)), '978-9961': ((0, 2999999, 1), (3000000, 6999999, 2), (7000000, 9499999, 3), (9500000, 9999999, 4)), '978-9962': ((0, 5499999, 2), (5500000, 5599999, 4), (5600000, 5999999, 2), (6000000, 8499999, 3), (8500000, 9999999, 4)), '978-9963': ((0, 1999999, 1), (2000000, 2499999, 4), (2500000, 2799999, 3), (2800000, 2999999, 4), (3000000, 5499999, 2), (5500000, 7349999, 3), (7350000, 7499999, 4), (7500000, 9999999, 4)), '978-9964': ((0, 6999999, 1), (7000000, 9499999, 2), (9500000, 9999999, 3)), '978-9965': ((0, 3999999, 2), (4000000, 8999999, 3), (9000000, 9999999, 4)), '978-9966': ((0, 1499999, 3), (1500000, 1999999, 4), (2000000, 6999999, 2), (7000000, 7499999, 4), (7500000, 9599999, 3), (9600000, 9999999, 4)), '978-9967': ((0, 3999999, 2), (4000000, 8999999, 3), (9000000, 9999999, 4)), '978-9968': ((0, 4999999, 2), (5000000, 9399999, 3), (9400000, 9999999, 4)), '978-9970': ((0, 3999999, 2), (4000000, 8999999, 3), (9000000, 9999999, 4)), '978-9971': ((0, 5999999, 1), (6000000, 8999999, 2), (9000000, 9899999, 3), (9900000, 9999999, 4)), '978-9972': ((0, 999999, 2), (1000000, 1999999, 1), (2000000, 2499999, 3), (2500000, 2999999, 4), (3000000, 5999999, 2), (6000000, 8999999, 3), (9000000, 9999999, 4)), '978-9973': ((0, 599999, 2), (600000, 899999, 3), (900000, 999999, 4), (1000000, 6999999, 2), (7000000, 9699999, 3), (9700000, 9999999, 4)), '978-9974': ((0, 2999999, 1), (3000000, 5499999, 2), (5500000, 7499999, 3), (7500000, 8799999, 4), (8800000, 9099999, 3), (9100000, 9499999, 2), (9500000, 9999999, 2)), '978-9975': ((0, 999999, 1), (1000000, 2999999, 3), (3000000, 3999999, 4), (4000000, 4499999, 4), (4500000, 8999999, 2), (9000000, 9499999, 3), (9500000, 9999999, 4)), '978-9976': ((0, 4999999, 1), (5000000, 5899999, 4), (5900000, 8999999, 2), (9000000, 9899999, 3), (9900000, 9999999, 4)), '978-9977': ((0, 8999999, 2), (9000000, 9899999, 3), (9900000, 9999999, 4)), '978-9978': ((0, 2999999, 2), (3000000, 3999999, 3), (4000000, 9499999, 2), (9500000, 9899999, 3), (9900000, 9999999, 4)), '978-9979': ((0, 4999999, 1), (5000000, 6499999, 2), (6500000, 6599999, 3), (6600000, 7599999, 2), (7600000, 8999999, 3), (9000000, 9999999, 4)), '978-9980': ((0, 3999999, 1), (4000000, 8999999, 2), (9000000, 9899999, 3), (9900000, 9999999, 4)), '978-9981': ((0, 999999, 2), (1000000, 1599999, 3), (1600000, 1999999, 4), (2000000, 7999999, 2), (8000000, 9499999, 3), (9500000, 9999999, 4)), '978-9982': ((0, 7999999, 2), (8000000, 9899999, 3), (9900000, 9999999, 4)), '978-9983': ((0, 7999999, 0), (8000000, 9499999, 2), (9500000, 9899999, 3), (9900000, 9999999, 4)), '978-9984': ((0, 4999999, 2), (5000000, 8999999, 3), (9000000, 9999999, 4)), '978-9985': ((0, 4999999, 1), (5000000, 7999999, 2), (8000000, 8999999, 3), (9000000, 9999999, 4)), '978-9986': ((0, 3999999, 2), (4000000, 8999999, 3), (9000000, 9399999, 4), (9400000, 9699999, 3), (9700000, 9999999, 2)), '978-9987': ((0, 3999999, 2), (4000000, 8799999, 3), (8800000, 9999999, 4)), '978-9988': ((0, 2999999, 1), (3000000, 5499999, 2), (5500000, 7499999, 3), (7500000, 9999999, 4)), '978-9989': ((0, 999999, 1), (1000000, 1999999, 3), (2000000, 2999999, 4), (3000000, 5999999, 2), (6000000, 9499999, 3), (9500000, 9999999, 4)), '978-99901': ((0, 4999999, 2), (5000000, 7999999, 3), (8000000, 9999999, 2)), '978-99902': ((0, 9999999, 0),), '978-99903': ((0, 1999999, 1), (2000000, 8999999, 2), (9000000, 9999999, 3)), '978-99904': ((0, 5999999, 1), (6000000, 8999999, 2), (9000000, 9999999, 3)), '978-99905': ((0, 3999999, 1), (4000000, 7999999, 2), (8000000, 9999999, 3)), '978-99906': ((0, 2999999, 1), (3000000, 5999999, 2), (6000000, 6999999, 3), (7000000, 8999999, 2), (9000000, 9499999, 2), (9500000, 9999999, 3)), '978-99908': ((0, 999999, 1), (1000000, 8999999, 2), (9000000, 9999999, 3)), '978-99909': ((0, 3999999, 1), (4000000, 9499999, 2), (9500000, 9999999, 3)), '978-99910': ((0, 2999999, 1), (3000000, 8999999, 2), (9000000, 9999999, 3)), '978-99911': ((0, 5999999, 2), (6000000, 9999999, 3)), '978-99912': ((0, 3999999, 1), (4000000, 5999999, 3), (6000000, 8999999, 2), (9000000, 9999999, 3)), '978-99913': ((0, 2999999, 1), (3000000, 3599999, 2), (3600000, 5999999, 0), (6000000, 6049999, 3), (6050000, 9999999, 0)), '978-99914': ((0, 4999999, 1), (5000000, 6999999, 2), (7000000, 7999999, 1), (8000000, 8999999, 2), (9000000, 9999999, 3)), '978-99915': ((0, 4999999, 1), (5000000, 7999999, 2), (8000000, 9999999, 3)), '978-99916': ((0, 2999999, 1), (3000000, 6999999, 2), (7000000, 9999999, 3)), '978-99917': ((0, 2999999, 1), (3000000, 8999999, 2), (9000000, 9999999, 3)), '978-99918': ((0, 3999999, 1), (4000000, 7999999, 2), (8000000, 9999999, 3)), '978-99919': ((0, 2999999, 1), (3000000, 3999999, 3), (4000000, 6999999, 2), (7000000, 7999999, 2), (8000000, 8499999, 3), (8500000, 8999999, 3), (9000000, 9999999, 3)), '978-99920': ((0, 4999999, 1), (5000000, 8999999, 2), (9000000, 9999999, 3)), '978-99921': ((0, 1999999, 1), (2000000, 6999999, 2), (7000000, 7999999, 3), (8000000, 8999999, 1), (9000000, 9999999, 2)), '978-99922': ((0, 3999999, 1), (4000000, 6999999, 2), (7000000, 9999999, 3)), '978-99923': ((0, 1999999, 1), (2000000, 7999999, 2), (8000000, 9999999, 3)), '978-99924': ((0, 1999999, 1), (2000000, 7999999, 2), (8000000, 9999999, 3)), '978-99925': ((0, 3999999, 1), (4000000, 7999999, 2), (8000000, 9999999, 3)), '978-99926': ((0, 999999, 1), (1000000, 5999999, 2), (6000000, 8699999, 3), (8700000, 8999999, 2), (9000000, 9999999, 2)), '978-99927': ((0, 2999999, 1), (3000000, 5999999, 2), (6000000, 9999999, 3)), '978-99928': ((0, 999999, 1), (1000000, 7999999, 2), (8000000, 9999999, 3)), '978-99929': ((0, 4999999, 1), (5000000, 7999999, 2), (8000000, 9999999, 3)), '978-99930': ((0, 4999999, 1), (5000000, 7999999, 2), (8000000, 9999999, 3)), '978-99931': ((0, 4999999, 1), (5000000, 7999999, 2), (8000000, 9999999, 3)), '978-99932': ((0, 999999, 1), (1000000, 5999999, 2), (6000000, 6999999, 3), (7000000, 7999999, 1), (8000000, 9999999, 2)), '978-99933': ((0, 2999999, 1), (3000000, 5999999, 2), (6000000, 9999999, 3)), '978-99934': ((0, 1999999, 1), (2000000, 7999999, 2), (8000000, 9999999, 3)), '978-99935': ((0, 2999999, 1), (3000000, 5999999, 2), (6000000, 6999999, 3), (7000000, 8999999, 1), (9000000, 9999999, 2)), '978-99936': ((0, 999999, 1), (1000000, 5999999, 2), (6000000, 9999999, 3)), '978-99937': ((0, 1999999, 1), (2000000, 5999999, 2), (6000000, 9999999, 3)), '978-99938': ((0, 1999999, 1), (2000000, 5999999, 2), (6000000, 8999999, 3), (9000000, 9999999, 2)), '978-99939': ((0, 5999999, 1), (6000000, 8999999, 2), (9000000, 9999999, 3)), '978-99940': ((0, 999999, 1), (1000000, 6999999, 2), (7000000, 9999999, 3)), '978-99941': ((0, 2999999, 1), (3000000, 7999999, 2), (8000000, 9999999, 3)), '978-99942': ((0, 4999999, 1), (5000000, 7999999, 2), (8000000, 9999999, 3)), '978-99943': ((0, 2999999, 1), (3000000, 5999999, 2), (6000000, 9999999, 3)), '978-99944': ((0, 4999999, 1), (5000000, 7999999, 2), (8000000, 9999999, 3)), '978-99945': ((0, 5999999, 1), (6000000, 8999999, 2), (9000000, 9999999, 3)), '978-99946': ((0, 2999999, 1), (3000000, 5999999, 2), (6000000, 9999999, 3)), '978-99947': ((0, 2999999, 1), (3000000, 6999999, 2), (7000000, 9999999, 3)), '978-99948': ((0, 4999999, 1), (5000000, 7999999, 2), (8000000, 9999999, 3)), '978-99949': ((0, 1999999, 1), (2000000, 8999999, 2), (9000000, 9999999, 3)), '978-99950': ((0, 4999999, 1), (5000000, 7999999, 2), (8000000, 9999999, 3)), '978-99951': ((0, 9999999, 0),), '978-99952': ((0, 4999999, 1), (5000000, 7999999, 2), (8000000, 9999999, 3)), '978-99953': ((0, 2999999, 1), (3000000, 7999999, 2), (8000000, 9399999, 3), (9400000, 9999999, 2)), '978-99954': ((0, 2999999, 1), (3000000, 6999999, 2), (7000000, 8799999, 3), (8800000, 9999999, 2)), '978-99955': ((0, 1999999, 1), (2000000, 5999999, 2), (6000000, 7999999, 3), (8000000, 9999999, 2)), '978-99956': ((0, 5999999, 2), (6000000, 8599999, 3), (8600000, 9999999, 2)), '978-99957': ((0, 1999999, 1), (2000000, 7999999, 2), (8000000, 9399999, 3), (9400000, 9999999, 2)), '978-99958': ((0, 4999999, 1), (5000000, 9399999, 2), (9400000, 9499999, 3), (9500000, 9999999, 3)), '978-99959': ((0, 2999999, 1), (3000000, 5999999, 2), (6000000, 9999999, 3)), '978-99960': ((0, 999999, 1), (1000000, 9499999, 2), (9500000, 9999999, 3)), '978-99961': ((0, 2999999, 1), (3000000, 3999999, 3), (4000000, 8999999, 2), (9000000, 9999999, 3)), '978-99962': ((0, 4999999, 1), (5000000, 7999999, 2), (8000000, 9999999, 3)), '978-99963': ((0, 4999999, 2), (5000000, 9199999, 3), (9200000, 9999999, 2)), '978-99964': ((0, 1999999, 1), (2000000, 7999999, 2), (8000000, 9999999, 3)), '978-99965': ((0, 2999999, 1), (3000000, 3599999, 3), (3600000, 6299999, 2), (6300000, 9999999, 3)), '978-99966': ((0, 2999999, 1), (3000000, 6999999, 2), (7000000, 7999999, 3), (8000000, 9699999, 2), (9700000, 9999999, 3)), '978-99967': ((0, 999999, 1), (1000000, 1499999, 2), (1500000, 1999999, 0), (2000000, 5999999, 2), (6000000, 8999999, 3), (9000000, 9199999, 3), (9200000, 9499999, 3), (9500000, 9999999, 0)), '978-99968': ((0, 3999999, 1), (4000000, 5999999, 3), (6000000, 8999999, 2), (9000000, 9999999, 3)), '978-99969': ((0, 4999999, 1), (5000000, 7999999, 2), (8000000, 9999999, 3)), '978-99970': ((0, 4999999, 1), (5000000, 8999999, 2), (9000000, 9999999, 3)), '978-99971': ((0, 4999999, 1), (5000000, 8499999, 2), (8500000, 9999999, 3)), '978-99972': ((0, 4999999, 1), (5000000, 8999999, 2), (9000000, 9999999, 3)), '978-99973': ((0, 3999999, 1), (4000000, 7999999, 2), (8000000, 9999999, 3)), '978-99974': ((0, 999999, 1), (1000000, 2999999, 2), (3000000, 3999999, 3), (4000000, 7999999, 2), (8000000, 9999999, 3)), '978-99975': ((0, 2999999, 1), (3000000, 3999999, 3), (4000000, 7999999, 2), (8000000, 9999999, 3)), '978-99976': ((0, 1999999, 1), (2000000, 5999999, 2), (6000000, 7999999, 3), (8000000, 9999999, 0)), '978-99977': ((0, 1999999, 1), (2000000, 3999999, 0), (4000000, 6999999, 2), (7000000, 7999999, 3), (8000000, 9999999, 0)), '978-99978': ((0, 4999999, 1), (5000000, 7499999, 2), (7500000, 9999999, 3)), '978-99979': ((0, 4999999, 1), (5000000, 7999999, 2), (8000000, 9999999, 3)), '978-99980': ((0, 999999, 1), (1000000, 2999999, 0), (3000000, 5999999, 2), (6000000, 7999999, 0), (8000000, 9999999, 3)), '978-99981': ((0, 1999999, 1), (2000000, 2999999, 0), (3000000, 4999999, 2), (5000000, 8999999, 0), (9000000, 9999999, 3)), '979-10': ((0, 1999999, 2), (2000000, 6999999, 3), (7000000, 8999999, 4), (9000000, 9759999, 5), (9760000, 9999999, 6)), '979-11': ((0, 2499999, 2), (2500000, 5499999, 3), (5500000, 8499999, 4), (8500000, 9499999, 5), (9500000, 9999999, 6)), '979-12': ((0, 1999999, 0), (2000000, 2009999, 3), (2010000, 9999999, 0))}
+RDDATE='20181004'
diff -Nru isbnlib-3.5.6/isbnlib/_data/__init__.py isbnlib-3.9.3/isbnlib/_data/__init__.py
--- isbnlib-3.5.6/isbnlib/_data/__init__.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/_data/__init__.py 2018-10-05 11:18:35.000000000 +0000
@@ -0,0 +1 @@
+
diff -Nru isbnlib-3.5.6/isbnlib/_desc.py isbnlib-3.9.3/isbnlib/_desc.py
--- isbnlib-3.5.6/isbnlib/_desc.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/_desc.py 2018-10-05 11:18:35.000000000 +0000
@@ -1,38 +1,42 @@
# -*- coding: utf-8 -*-
"""Return a small description of the book."""
+import logging
from json import loads
from textwrap import fill
from .dev.webservice import query as wsquery
+LOGGER = logging.getLogger(__name__)
UA = "isbnlib (gzip)"
+SERVICE_URL = "https://www.googleapis.com/books/v1/volumes?q=isbn:{isbn}"\
+ "&fields=items/volumeInfo(description)"\
+ "&maxResults=1"
def goo_desc(isbn):
"""Get description from Google Books api."""
from .registry import metadata_cache # <-- dynamic
cache = metadata_cache
- if cache is not None: # pragma: no cover
- key = 'gdesc' + isbn
+ if cache is not None: # pragma: no cover
+ key = 'desc-go-' + isbn
try:
if cache[key]:
return cache[key]
else:
- raise # <-- IMPORTANT: usually the caches don't return error!
- except:
+ raise KeyError # <-- IMPORTANT: caches don't return error!
+ except KeyError:
pass
- url = "https://www.googleapis.com/books/v1/volumes?q=isbn+{isbn}"\
- "&fields=items/volumeInfo(description)"\
- "&maxResults=1".format(isbn=isbn)
+ url = SERVICE_URL.format(isbn=isbn)
content = wsquery(url, user_agent=UA)
try:
content = loads(content)
content = content['items'][0]['volumeInfo']['description']
+ # TODO don't format content here!
content = fill(content, width=75) if content else None
- if content and cache is not None: # pragma: no cover
+ if content and cache is not None: # pragma: no cover
cache[key] = content
return content
- except KeyError: # pragma: no cover
- return
+ except: # pragma: no cover
+ LOGGER.debug('No description for %s', isbn)
diff -Nru isbnlib-3.5.6/isbnlib/dev/_bouth23.py isbnlib-3.9.3/isbnlib/dev/_bouth23.py
--- isbnlib-3.5.6/isbnlib/dev/_bouth23.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/dev/_bouth23.py 2018-10-05 11:18:35.000000000 +0000
@@ -1,10 +1,8 @@
# -*- coding: utf-8 -*-
# flake8:noqa
# pylint: skip-file
-
"""Help code to run in py2 and py3."""
-
import sys
if sys.version < '3':
diff -Nru isbnlib-3.5.6/isbnlib/dev/bouth23.py isbnlib-3.9.3/isbnlib/dev/bouth23.py
--- isbnlib-3.5.6/isbnlib/dev/bouth23.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/dev/bouth23.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,8 +0,0 @@
-# -*- coding: utf-8 -*-
-# flake8:noqa
-# pylint: skip-file
-
-"""Help code to run in py2 and py3."""
-
-
-from ._bouth23 import *
diff -Nru isbnlib-3.5.6/isbnlib/dev/_coverscache.py isbnlib-3.9.3/isbnlib/dev/_coverscache.py
--- isbnlib-3.5.6/isbnlib/dev/_coverscache.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/dev/_coverscache.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,170 +0,0 @@
-# -*- coding: utf-8 -*-
-
-"""Read and write cover cache.
-
-
- NOTE
- 1. shelve has different incompatible formats in py2 and py3
- 2. if some methods detect that the cache is not consistent
- they delete the cache and create a new one.
- 3. After purge the cache keeps the records with more hits
- and the newests.
- 4. The design is for safety not for performance! Increasing
- MAXLEN can have an high detrimental impact on performance.
-
- Examples:
- cc = CoversCache('.covers')
- cc['9781408835029'] = (
- "http://books.google.com/books/content?id=uUcvgfTYTRnjh"\
- "&printsec=frontcover"\
- "&img=1&zoom=2&edge=curl&source=gbs_api",
- ".covers/slot01/9781408835029.jpg"
- )
- cc['9781408835029']
- cc.hits('9781408835029')
- cc.keys()
- cc.files()
- cc.sync()
- cc.make()
- cc.delete()
- del cc['9781408835029']
-
-"""
-
-import os
-import shutil
-import sys
-from random import randint
-
-from ._shelvecache import ShelveCache
-
-WINDOWS = os.name == 'nt'
-PY3 = sys.version > '3'
-
-
-class CoversCache(object):
-
- """Covers cache."""
-
- CACHEFOLDER = '.covers'
- INDEXFN = '.index'
- WINSHADOWIDX = INDEXFN + '.dat'
- MAXLEN = 3000
- NSLOTS = 10
-
- def __init__(self, cachepath=CACHEFOLDER):
- """Initialize attributes."""
- self.cachepath = cachepath
- self._indexpath = os.path.join(cachepath, self.INDEXFN)
- if WINDOWS and PY3:
- if not os.path.isfile(os.path.join(cachepath, self.WINSHADOWIDX)):
- self.make()
- elif not os.path.isfile(self._indexpath):
- self.make()
- self._index = ShelveCache(self._indexpath)
- self._index.MAXLEN = self.MAXLEN
- if len(self._index) > self.MAXLEN:
- self.purge()
-
- def __getitem__(self, key):
- """Read cache."""
- try:
- url, pth = self._index[key]
- pth = os.path.join(self.cachepath, pth)
- return (url, pth)
- except:
- return None
-
- def __setitem__(self, key, value):
- """Write to cache."""
- url, pth = value
- try:
- if pth and os.path.isfile(pth) and url:
- tocache = os.path.join(self._get_slot(), os.path.basename(pth))
- target = os.path.join(self.cachepath, tocache)
- shutil.copyfile(pth, target)
- if os.path.isfile(target):
- self._index[key] = (url, tocache)
- return True
- return False
- else:
- raise
- except:
- return False
-
- def __delitem__(self, key):
- """Delete record with key."""
- try:
- del self._index[key]
- return True
- except:
- return False
-
- def __len__(self):
- """Return the number of keys in cache."""
- return len(self._index.keys()) if self._index.keys() else 0
-
- def keys(self):
- """Return the number of keys in cache."""
- return self._index.keys()
-
- def hits(self, key):
- """Return the number of hits for key."""
- return self._index.hits(key)
-
- def _create_slots(self):
- for slot in range(self.NSLOTS):
- name = "slot%02d" % slot
- pth = os.path.join(self.cachepath, name)
- if not os.path.exists(pth):
- os.mkdir(pth)
-
- def make(self):
- """Init the cache."""
- # 1. Delete if available
- if os.path.isdir(self.cachepath):
- self.delete()
- # 2. Make folder
- os.mkdir(self.cachepath)
- # 3. Create Index
- self._index = ShelveCache(self._indexpath)
- # 4. Create slots
- self._create_slots()
-
- def _get_slot(self):
- return "slot%02d" % randint(0, self.NSLOTS - 1)
-
- def files(self):
- pths = []
- for root, _, fls in os.walk(self.cachepath):
- for fn in fls:
- pths.append(os.path.join(root, fn))
- return pths
-
- def sync(self):
- """Sync index entries with disk files."""
- # clear index entries not on disk
- checked = [self._indexpath]
- for key in self._index.keys():
- url, pth = self._index[key]
- pth = os.path.join(self.cachepath, pth)
- if not os.path.isfile(pth):
- self._index[key] = (url, None)
- checked.append(pth)
- # delete files not on index
- diff = tuple(set(self.files()) - set(checked))
- for fp in diff:
- if self.INDEXFN not in fp:
- os.remove(fp)
-
- def purge(self):
- try:
- self._index.purge()
- self.sync()
- return True
- except:
- return False
-
- def delete(self):
- self._index = None
- return shutil.rmtree(self.cachepath)
diff -Nru isbnlib-3.5.6/isbnlib/dev/_data.py isbnlib-3.9.3/isbnlib/dev/_data.py
--- isbnlib-3.5.6/isbnlib/dev/_data.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/dev/_data.py 2018-10-05 11:18:35.000000000 +0000
@@ -9,12 +9,10 @@
# For now you cannot add custom fields!
FIELDS = ('ISBN-13', 'Title', 'Authors', 'Publisher', 'Year', 'Language')
-
LOGGER = logging.getLogger(__name__)
class Metadata(object):
-
"""Class for metadata objects."""
def __init__(self, record=None):
@@ -36,12 +34,13 @@
def clean(self, broom=normalize_space, exclude=()):
"""Clean fields of value."""
- self._content.update((k, broom(v)) for k, v
- in list(self._content.items())
+ self._content.update((k, broom(v))
+ for k, v in list(self._content.items())
if k != 'Authors' and k not in exclude)
if 'Authors' not in exclude:
- self._content['Authors'] = [broom(i) for i in
- self._content['Authors']]
+ self._content['Authors'] = [
+ broom(i) for i in self._content['Authors']
+ ]
self._content['Title'] = self._content['Title'].strip(',.:;-_ ')
if self._content['Language'].lower() in ('en', 'eng', 'english'):
self._content['Title'] = titlecase(self._content['Title'])
@@ -66,13 +65,15 @@
"""Delete value."""
self._set_empty()
- def merge(self, record, overwrite=(),
+ def merge(self,
+ record,
+ overwrite=(),
overrule=lambda x: x == u('') or x == [u('')]):
"""Merge the record with value."""
# by default do nothing
- self._content.update((k, v) for k, v in list(record.items())
- if k in overwrite and not overrule(v) or
- self._content[k] == u(''))
+ self._content.update(
+ (k, v) for k, v in list(record.items())
+ if k in overwrite and not overrule(v) or self._content[k] == u(''))
if not self._validate(): # pragma: no cover
self._set_empty()
LOGGER.debug(record)
@@ -83,10 +84,9 @@
"""Validate value."""
# 'minimal' check
for k in self._content:
- if not type(self._content[k]) is type3str():
- if k != 'Authors':
- return False
- if not type(self._content['Authors']) is list:
+ if not isinstance(self._content[k], type3str()) and k != 'Authors':
+ return False
+ if not isinstance(self._content['Authors'], list):
return False
return True
@@ -98,5 +98,5 @@
def stdmeta(records):
"""Function API to the class."""
- dt = Metadata(records)
- return dt.value
+ data = Metadata(records)
+ return data.value
diff -Nru isbnlib-3.5.6/isbnlib/dev/_exceptions.py isbnlib-3.9.3/isbnlib/dev/_exceptions.py
--- isbnlib-3.5.6/isbnlib/dev/_exceptions.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/dev/_exceptions.py 2018-10-05 11:18:35.000000000 +0000
@@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
-
""" Exceptions for isbnlib.dev
The classes in isbnlib.dev should use the exceptions below.
@@ -18,7 +17,7 @@
self.message = '%s (%s)' % (self.message, msg)
def __str__(self):
- return getattr(self, 'message', '') # pragma: no cover
+ return getattr(self, 'message', '') # pragma: no cover
class ISBNLibHTTPError(ISBNLibDevException):
diff -Nru isbnlib-3.5.6/isbnlib/dev/_files.py isbnlib-3.9.3/isbnlib/dev/_files.py
--- isbnlib-3.5.6/isbnlib/dev/_files.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/dev/_files.py 2018-10-05 11:18:35.000000000 +0000
@@ -1,8 +1,6 @@
# -*- coding: utf-8 -*-
-
"""Helper module to work with files."""
-
import fnmatch
import logging
import os
@@ -18,7 +16,6 @@
class File(object):
-
"""Easy manipulation of files in the SAME directory."""
def __init__(self, fp):
@@ -60,10 +57,10 @@
LOGGER.critical("This (%s) is not a basename!", basename)
return False
name, ext = os.path.splitext(basename)
- if len(name) == 0:
+ if not name:
LOGGER.critical("Not a valid name (lenght 0)!")
return False
- if len(ext) == 0:
+ if not ext:
LOGGER.critical("Not a valid extension (lenght 0)!")
return False
return True
@@ -81,16 +78,15 @@
try:
os.rename(self.basename, new_basename)
except OSError as err:
- LOGGER.critical("%s", err.message)
+ LOGGER.critical("%s", err)
return False
self.basename = new_basename
self.name = name
self.ext = ext
- return True
else:
LOGGER.info("The file (%s) already exist in the directory!",
new_basename)
- return True
+ return True
@staticmethod
def uxchmod(fp, mode=MODE666):
diff -Nru isbnlib-3.5.6/isbnlib/dev/_fmt.py isbnlib-3.9.3/isbnlib/dev/_fmt.py
--- isbnlib-3.5.6/isbnlib/dev/_fmt.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/dev/_fmt.py 2018-10-05 11:18:35.000000000 +0000
@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
# flake8: noqa
# pylint: skip-file
-
"""Format canonical in bibliographic formats."""
import re
@@ -54,6 +53,14 @@
"identifier": [{"type": "ISBN", "id": "$ISBN"}],
"publisher": "$Publisher"}'''
+csl = r'''{"type":"book",
+ "id":"$ISBN",
+ "title":"$Title",
+ "author": [$AUTHORS],
+ "issued": {"date_parts": [[$Year]]},
+ "ISBN":"$ISBN",
+ "publisher":"$Publisher"}'''
+
opf = r"""
@@ -76,16 +83,17 @@
Publisher: $Publisher"""
templates = {
- 'labels': labels,
- 'bibtex': bibtex,
- 'endnote': endnote,
- 'refworks': refworks,
- 'msword': msword,
- 'json': json,
- 'opf': opf
- }
+ 'labels': labels,
+ 'bibtex': bibtex,
+ 'endnote': endnote,
+ 'refworks': refworks,
+ 'msword': msword,
+ 'json': json,
+ 'csl': csl,
+ 'opf': opf
+}
-fmts = list(templates.keys())
+_fmts = list(templates.keys())
def _gen_proc(name, canonical):
@@ -97,7 +105,7 @@
def _spec_proc(name, fmtrec, authors):
"""Fix the Authors records."""
- if name not in fmts:
+ if name not in _fmts:
return
if name == 'labels':
AUTHORS = '\nAuthor: '.join(authors)
@@ -112,11 +120,12 @@
person = r"$last"\
r"$first"
AUTHORS = '\n'.join(
- Template(person).safe_substitute(last_first(a))
- for a in authors)
+ Template(person).safe_substitute(last_first(a)) for a in authors)
elif name == 'json':
- AUTHORS = ', '.join('{"name": "$"}'.replace("$", a)
- for a in authors)
+ AUTHORS = ', '.join('{"name": "$"}'.replace("$", a) for a in authors)
+ elif name == 'csl':
+ AUTHORS = ', '.join(
+ '{"literal": "$"}'.replace("$", a) for a in authors)
elif name == 'opf':
fmtrec = fmtrec.replace('$uid', str(uuid.uuid4()))
creator = r' self.MAXLEN:
- self.purge()
- except:
- pass
- except:
- s = self._sh.open(self.filepath, 'n')
- self._keys = []
- s.close()
-
- def __getitem__(self, key):
- """Read cache."""
- if key not in self._keys:
- return None
- try:
- s = self._sh.open(self.filepath, writeback=True)
- if s[key]:
- s[key]['hits'] += 1
- return s[key]['value']
- else:
- return None
- except KeyError:
- return None
- except ValueError:
- self.new()
- return None
- finally:
- s.close()
-
- def __setitem__(self, key, value):
- """Write to cache."""
- try:
- s = self._sh.open(self.filepath)
- s[key] = {'value': value, 'hits': 0, 'timestamp': timestamp()}
- self._keys.append(key)
- status = True
- except:
- status = False
- finally:
- s.close()
- return status
-
- def __delitem__(self, key):
- """Delete record with key."""
- if key not in self._keys:
- return
- try:
- s = self._sh.open(self.filepath)
- del s[key]
- self._keys.remove(key)
- except KeyError:
- return
- except ValueError:
- self.new()
- return
- finally:
- s.close()
-
- def __len__(self):
- """Return the number of keys in cache."""
- return len(self.keys()) if self.keys() else 0
-
- def keys(self):
- """Return list of keys in Cache."""
- if self._keys:
- return self._keys
- try:
- s = self._sh.open(self.filepath)
- self._keys = list(s.keys())
- return self._keys
- finally:
- s.close()
-
- def ts(self, key):
- """Return the timestamp of the record with key."""
- if key not in self._keys:
- return None
- try:
- s = self._sh.open(self.filepath)
- ts = s[key]['timestamp'] if s[key] else None
- if not ts:
- return
- fmt = '%Y-%m-%d %H:%M:%S'
- return datetime.datetime.fromtimestamp(ts).strftime(fmt)
- except KeyError:
- return
- except ValueError:
- self.new()
- return
- finally:
- s.close()
-
- def hits(self, key):
- """Return the number of hits for the record with key."""
- if key not in self._keys:
- return None
- try:
- s = self._sh.open(self.filepath)
- hts = s[key]['hits'] if s[key] else None
- return hts
- except KeyError:
- return
- except ValueError:
- self.new()
- return
- finally:
- s.close()
-
- def new(self):
- """Make new cache."""
- s = self._sh.open(self.filepath, 'n')
- s.close()
- self._keys = []
-
- def purge(self):
- """Purge the cache."""
- try:
- if len(self.keys()) < self.MAXLEN:
- return
- s = self._sh.open(self.filepath)
- data = [(k, s[k]['timestamp'], s[k]['hits']) for k in s.keys()]
- data.sort(key=lambda tup: (-tup[2], -tup[1]))
- keep = int(self.CUTOFF * self.MAXLEN)
- garbk = [k[0] for k in data[keep:]]
- for k in garbk:
- del s[k]
- self._keys = s.keys()
- finally:
- s.close()
diff -Nru isbnlib-3.5.6/isbnlib/dev/vias.py isbnlib-3.9.3/isbnlib/dev/vias.py
--- isbnlib-3.5.6/isbnlib/dev/vias.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/dev/vias.py 2018-10-05 11:18:35.000000000 +0000
@@ -14,9 +14,9 @@
for name, task in named_tasks:
try:
results[name] = task(arg)
- except: # pragma: no cover
- LOGGER.debug("No result in 'serial' for %s[%s](%s)",
- task, name, arg)
+ except: # pragma: no cover
+ LOGGER.debug("No result in 'serial' for %s[%s](%s)", task, name,
+ arg)
results[name] = None
return results
@@ -29,9 +29,9 @@
def _worker(name, task, arg):
try:
results[name] = task(arg)
- except: # pragma: no cover
- LOGGER.debug("No result in 'parallel' for %s[%s](%s)",
- task, name, arg)
+ except: # pragma: no cover
+ LOGGER.debug("No result in 'parallel' for %s[%s](%s)", task, name,
+ arg)
results[name] = None
for name, task in named_tasks:
@@ -48,11 +48,11 @@
q = Queue()
def _worker(name, task, arg, q):
- try: # pragma: no cover
+ try: # pragma: no cover
q.put((name, task(arg)))
- except: # pragma: no cover
- LOGGER.debug("No result in 'multi' for %s[%s](%s)",
- task, name, arg)
+ except: # pragma: no cover
+ LOGGER.debug("No result in 'multi' for %s[%s](%s)", task, name,
+ arg)
q.put((name, None))
for name, task in named_tasks:
diff -Nru isbnlib-3.5.6/isbnlib/dev/webquery.py isbnlib-3.9.3/isbnlib/dev/webquery.py
--- isbnlib-3.5.6/isbnlib/dev/webquery.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/dev/webquery.py 2018-10-05 11:18:35.000000000 +0000
@@ -16,7 +16,6 @@
class WEBQuery(object):
-
"""Base class to query a webservice and parse the result to py objects."""
T = {'id': timestamp()} # noqa
@@ -50,7 +49,7 @@
"""Parse the data (default JSON -> PY)."""
if parser is None: # pragma: no cover
return self.data
- return parser(self.data) # <-- data is now unicode
+ return parser(self.data) # <-- data is now unicode
def query(url, user_agent=UA, data_checker=None, parser=json.loads):
diff -Nru isbnlib-3.5.6/isbnlib/dev/webservice.py isbnlib-3.9.3/isbnlib/dev/webservice.py
--- isbnlib-3.5.6/isbnlib/dev/webservice.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/dev/webservice.py 2018-10-05 11:18:35.000000000 +0000
@@ -6,12 +6,16 @@
from ._bouth23 import bstream, s
from ._exceptions import ISBNLibHTTPError, ISBNLibURLError
+from .. import config
-try: # pragma: no cover
+# pylint: disable=import-error
+# pylint: disable=wrong-import-order
+# pylint: disable=no-name-in-module
+try: # pragma: no cover
from urllib.parse import urlencode
from urllib.request import Request, urlopen
from urllib.error import HTTPError, URLError
-except ImportError: # pragma: no cover
+except ImportError: # pragma: no cover
from urllib import urlencode
from urllib2 import Request, urlopen, HTTPError, URLError
@@ -19,8 +23,8 @@
LOGGER = logging.getLogger(__name__)
+# pylint: disable=too-few-public-methods
class WEBService(object):
-
"""Class to query web services."""
def __init__(self, url, user_agent=UA, values=None, appheaders=None):
@@ -31,48 +35,48 @@
# add more user provided headers
if appheaders: # pragma: no cover
headers.update(appheaders)
- # if 'data' it does a PUT request (data must be urlencoded)
- data = urlencode(values) if values else None
+ # if 'data' it does a POST request (data must be urlencoded)
+ data = urlencode(values).encode('utf8') if values else None
self._request = Request(url, data, headers=headers)
- self.response = None
- def _response(self):
+ def response(self):
"""Check errors on response."""
try:
- self.response = urlopen(self._request)
+ response = urlopen(self._request, timeout=config.URLOPEN_TIMEOUT)
LOGGER.debug('Request headers:\n%s', self._request.header_items())
except HTTPError as e: # pragma: no cover
LOGGER.critical('ISBNLibHTTPError for %s with code %s [%s]',
self._url, e.code, e.msg)
if e.code in (401, 403, 429):
- raise ISBNLibHTTPError('%s Are you making many requests?'
- % e.code)
+ raise ISBNLibHTTPError(
+ '%s Are you making many requests?' % e.code)
if e.code in (502, 504):
- raise ISBNLibHTTPError('%s Service temporarily unavailable!'
- % e.code)
+ raise ISBNLibHTTPError(
+ '%s Service temporarily unavailable!' % e.code)
raise ISBNLibHTTPError('(%s) %s' % (e.code, e.msg))
- except URLError as e: # pragma: no cover
- LOGGER.critical('ISBNLibURLError for %s with reason %s',
- self._url, e.reason)
+ except URLError as e: # pragma: no cover
+ LOGGER.critical('ISBNLibURLError for %s with reason %s', self._url,
+ e.reason)
raise ISBNLibURLError(e.reason)
+ return response if response else None
def data(self):
"""Return the uncompressed data."""
- self._response()
- LOGGER.debug('Response headers:\n%s', self.response.info())
- if self.response.info().get('Content-Encoding') == 'gzip':
- buf = bstream(self.response.read())
+ res = self.response()
+ LOGGER.debug('Response headers:\n%s', res.info())
+ if res.info().get('Content-Encoding') == 'gzip':
+ buf = bstream(res.read())
f = gzip.GzipFile(fileobj=buf)
data = f.read()
- else: # pragma: no cover
- data = self.response.read()
+ else: # pragma: no cover
+ data = res.read()
return s(data)
def query(url, user_agent=UA, values=None, appheaders=None):
"""Query to a web service."""
- service = WEBService(url, user_agent=user_agent, values=values,
- appheaders=appheaders)
+ service = WEBService(
+ url, user_agent=user_agent, values=values, appheaders=appheaders)
data = service.data()
LOGGER.debug('Raw data from service:\n%s', data)
return data
diff -Nru isbnlib-3.5.6/isbnlib/_doitotex.py isbnlib-3.9.3/isbnlib/_doitotex.py
--- isbnlib-3.5.6/isbnlib/_doitotex.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/_doitotex.py 2018-10-05 11:18:35.000000000 +0000
@@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
-
"""Return metadata, of a given DOI, formated as BibTeX."""
import logging
@@ -8,18 +7,19 @@
LOGGER = logging.getLogger(__name__)
-
URL = 'http://dx.doi.org/{DOI}'
UA = 'isbnlib (gzip)'
def doi2tex(doi):
"""Get the bibtex ref for doi."""
- data = query(URL.format(DOI=doi),
- user_agent=UA,
- appheaders={'Accept': 'application/x-bibtex; charset=utf-8'}
- )
+ data = query(
+ URL.format(DOI=doi),
+ user_agent=UA,
+ appheaders={
+ 'Accept': 'application/x-bibtex; charset=utf-8',
+ })
if not data: # pragma: no cover
LOGGER.warning('no data return for doi: %s', doi)
- return
+ return None
return data
diff -Nru isbnlib-3.5.6/isbnlib/_editions.py isbnlib-3.9.3/isbnlib/_editions.py
--- isbnlib-3.5.6/isbnlib/_editions.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/_editions.py 2018-10-05 11:18:35.000000000 +0000
@@ -4,59 +4,61 @@
import logging
from ._core import EAN13
+from .dev import vias
from ._exceptions import NotRecognizedServiceError, NotValidISBNError
+from ._openled import query as oed
from ._thinged import query as ted
-from ._wcated import query as wed
-PROVIDERS = ('any', 'merge', 'thingl', 'wcat')
-TRUEPROVIDERS = ('wcat', 'thingl') # <-- by priority
+PROVIDERS = ('any', 'merge', 'openl', 'thingl')
+TRUEPROVIDERS = ('openl', 'thingl') # <-- by priority
LOGGER = logging.getLogger(__name__)
def fake_provider_any(isbn):
"""Fake provider 'any' service."""
- providers = {'wcat': wed, 'thingl': ted}
+ providers = {'openl': oed, 'thingl': ted}
for provider in TRUEPROVIDERS:
data = []
try:
data = providers[provider](isbn)
- if data:
+ if len(data) > 1:
return data
- continue # pragma: no cover
- except: # pragma: no cover
+ continue # pragma: no cover
+ except Exception: # pragma: no cover
continue
- return data # pragma: no cover
+ return data # pragma: no cover
def fake_provider_merge(isbn):
"""Fake provider 'merge' service."""
- data = []
- try: # pragma: no cover
- wdata = wed(isbn)
- if wdata:
- tdata = ted(isbn)
- if tdata:
- data = list(set(wdata + tdata))
- return data
- raise
- except: # pragma: no cover
+ try: # pragma: no cover
+ named_tasks = (('openl', oed), ('thingl', ted))
+ results = vias.parallel(named_tasks, isbn)
+ odata = results.get('openl', [])
+ tdata = results.get('thingl', [])
+ data = list(set(odata + tdata))
return data
+ except Exception: # pragma: no cover
+ return []
-def editions(isbn, service='wcat'):
+def editions(isbn, service='merge'):
"""Return the list of ISBNs of editions related with this ISBN."""
isbn = EAN13(isbn)
if not isbn:
LOGGER.critical('%s is not a valid ISBN', isbn)
raise NotValidISBNError(isbn)
- if service == 'any':
- return fake_provider_any(isbn)
+ if service not in PROVIDERS:
+ LOGGER.critical('%s is not a recognized editions provider', service)
+ raise NotRecognizedServiceError(service)
if service == 'merge':
return fake_provider_merge(isbn)
+ if service == 'any':
+ return fake_provider_any(isbn)
- if service not in PROVIDERS:
- LOGGER.critical('%s is not a recognized editions provider', service)
- raise NotRecognizedServiceError(service)
- return wed(isbn) if service == 'wcat' else ted(isbn)
+ if service == 'openl':
+ return oed(isbn)
+ if service == 'thingl':
+ return ted(isbn)
diff -Nru isbnlib-3.5.6/isbnlib/_exceptions.py isbnlib-3.9.3/isbnlib/_exceptions.py
--- isbnlib-3.5.6/isbnlib/_exceptions.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/_exceptions.py 2018-10-05 11:18:35.000000000 +0000
@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
+"""Exceptions for isbnlib."""
import sys
@@ -14,7 +15,6 @@
class ISBNLibException(Exception):
-
"""Base class for isbnlib exceptions.
This exception should not be raised directly,
@@ -22,11 +22,10 @@
"""
def __str__(self):
- return getattr(self, 'message', '') # pragma: no cover
+ return getattr(self, 'message', '') # pragma: no cover
class NotRecognizedServiceError(ISBNLibException):
-
"""Exception raised when the service is not in config.py."""
def __init__(self, service):
@@ -34,7 +33,6 @@
class NotValidISBNError(ISBNLibException):
-
"""Exception raised when the ISBN is not valid."""
def __init__(self, isbnlike):
@@ -42,10 +40,9 @@
class PluginNotLoadedError(ISBNLibException): # pragma: no cover
-
"""Exception raised when the plugin's loader doesn't load the plugin.
- TODO: Delete this in version 4
+ TODO: Delete this in version 4?
"""
def __init__(self, path):
diff -Nru isbnlib-3.5.6/isbnlib/_ext.py isbnlib-3.9.3/isbnlib/_ext.py
--- isbnlib-3.5.6/isbnlib/_ext.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/_ext.py 2018-10-05 11:18:35.000000000 +0000
@@ -31,10 +31,11 @@
return infogroup(isbn)
-def editions(isbn, service='wcat'):
+def editions(isbn, service='merge'):
"""Return the list of ISBNs of editions related with this ISBN.
- 'service' can have the values 'any', 'merge', 'thingl' and 'wcat' (default)
+ 'service' can have the values:
+ 'any', 'merge' (default), 'wcat', 'openl' and 'thingl'
"""
return eds(isbn, service)
@@ -54,24 +55,24 @@
"""Rename a file using metadata from an ISBN in his filename."""
cfp = File(fp)
isbn = EAN13(cfp.name)
- if not isbn: # pragma: no cover
- return
+ if not isbn: # pragma: no cover
+ return None
data = meta(isbn)
author = data.get('Authors', u('UNKNOWN'))
- if author != u('UNKNOWN'): # pragma: no cover
+ if author != u('UNKNOWN'): # pragma: no cover
author = last_first(author[0])['last']
year = data.get('Year', u('UNKNOWN'))
maxlen = 98 - (20 + len(author) + len(year))
title = data.get('Title', u('UNKNOWN'))
if title != u('UNKNOWN'):
regex1 = re.compile(r'[.,_!?/\\]')
- regex2 = re.compile('\s\s+')
+ regex2 = re.compile(r'\s\s+')
title = regex1.sub(' ', title)
title = regex2.sub(' ', title)
title = title.strip()
- if title == u('UNKNOWN') or not title: # pragma: no cover
- return
- if ' ' in title: # pragma: no cover
+ if title == u('UNKNOWN') or not title: # pragma: no cover
+ return None
+ if ' ' in title: # pragma: no cover
tokens = title.split(' ')
stitle = cutoff_tokens(tokens, maxlen)
title = ' '.join(stitle)
@@ -80,10 +81,10 @@
return cfp.baserename(b2u3(new_name + cfp.ext))
-def cover(isbn, size=2, mode='prt'):
- """Download the cover of the ISBN."""
+def cover(isbn):
+ """Get the img urls of the cover of the ISBN."""
isbn = EAN13(isbn)
- return gcover(isbn, size=size, mode=mode) if isbn else None
+ return gcover(isbn) if isbn else None
def desc(isbn):
diff -Nru isbnlib-3.5.6/isbnlib/_goob.py isbnlib-3.9.3/isbnlib/_goob.py
--- isbnlib-3.5.6/isbnlib/_goob.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/_goob.py 2018-10-05 11:18:35.000000000 +0000
@@ -5,12 +5,12 @@
from .dev import stdmeta
from .dev._bouth23 import u
-from .dev._exceptions import (ISBNNotConsistentError,
- NoDataForSelectorError, RecordMappingError)
+from .dev._exceptions import (ISBNNotConsistentError, NoDataForSelectorError,
+ RecordMappingError)
from .dev.webquery import query as wquery
UA = 'isbnlib (gzip)'
-SERVICE_URL = 'https://www.googleapis.com/books/v1/volumes?q=isbn+{isbn}'\
+SERVICE_URL = 'https://www.googleapis.com/books/v1/volumes?q=isbn:{isbn}'\
'&fields=items/volumeInfo(title,authors,publisher,publishedDate,language,'\
'industryIdentifiers)&maxResults=1'
LOGGER = logging.getLogger(__name__)
@@ -28,10 +28,10 @@
if 'publishedDate' in records \
and len(records['publishedDate']) >= 4:
canonical['Year'] = records['publishedDate'][0:4]
- else: # pragma: no cover
+ else: # pragma: no cover
canonical['Year'] = u('')
canonical['Language'] = records.get('language', u(''))
- except: # pragma: no cover
+ except: # pragma: no cover
LOGGER.debug("RecordMappingError for %s with data %s", isbn, records)
raise RecordMappingError(isbn)
# call stdmeta for extra cleanning and validation
@@ -49,9 +49,11 @@
# consistency check (isbn request = isbn response)
if recs:
ids = recs.get('industryIdentifiers', '')
- if isbn not in repr(ids): # pragma: no cover
+ if u('ISBN_13') in repr(ids) and \
+ isbn not in repr(ids): # pragma: no cover
LOGGER.debug('ISBNNotConsistentError for %s (%s)', isbn, repr(ids))
- raise ISBNNotConsistentError("%s not in %s" % (isbn, repr(ids)))
+ raise ISBNNotConsistentError("{0} not in {1}".format(
+ isbn, repr(ids)))
# map canonical <- records
return _mapper(isbn, recs)
diff -Nru isbnlib-3.5.6/isbnlib/_goom.py isbnlib-3.9.3/isbnlib/_goom.py
--- isbnlib-3.5.6/isbnlib/_goom.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/_goom.py 2018-10-05 11:18:35.000000000 +0000
@@ -22,7 +22,7 @@
try:
# mapping: canonical <- records
if 'industryIdentifiers' not in record: # pragma: no cover
- return
+ return None
canonical = {}
isbn = None
for ident in record['industryIdentifiers']:
@@ -30,7 +30,7 @@
isbn = ident['identifier']
break
if not isbn: # pragma: no cover
- return
+ return None
canonical['ISBN-13'] = isbn
canonical['Title'] = record.get('title', u('')).replace(' :', ':')
canonical['Authors'] = record.get('authors', [])
@@ -38,10 +38,10 @@
if 'publishedDate' in record \
and len(record['publishedDate']) >= 4:
canonical['Year'] = record['publishedDate'][0:4]
- else: # pragma: no cover
+ else: # pragma: no cover
canonical['Year'] = u('')
canonical['Language'] = record.get('language', u(''))
- except: # pragma: no cover
+ except: # pragma: no cover
raise RecordMappingError(isbn)
# call stdmeta for extra cleanning and validation
return stdmeta(canonical)
diff -Nru isbnlib-3.5.6/isbnlib/_gwords.py isbnlib-3.9.3/isbnlib/_gwords.py
--- isbnlib-3.5.6/isbnlib/_gwords.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/_gwords.py 2018-10-05 11:18:35.000000000 +0000
@@ -1,29 +1,44 @@
# -*- coding: utf-8 -*-
"""Use Google to get an ISBN from words from title and author's name."""
-
import logging
from ._core import get_canonical_isbn, get_isbnlike
from .dev import webservice
+try: # pragma: no cover
+ from urllib.parse import quote
+except ImportError: # pragma: no cover
+
+ def quote(x): # pragma: no cover
+ """Do nothing if PY2."""
+ return x
+
+
LOGGER = logging.getLogger(__name__)
def goos(words):
"""Use Google to get an ISBN from words from title and author's name."""
- service_url = "http://www.google.com/search?q={words}+ISBN"
- search_url = service_url.format(words=words.replace(' ', '+'))
- user_agent = 'w3m/0.5.2'
+ service_url = "http://www.google.com/search?q=ISBN+"
+ search_url = service_url + quote(words.replace(' ', '+'))
+
+ user_agent = 'w3m/0.5.3'
- content = webservice.query(search_url, user_agent)
+ content = webservice.query(
+ search_url,
+ user_agent=user_agent,
+ appheaders={
+ 'Content-Type': 'text/plain; charset="UTF-8"',
+ 'Content-Transfer-Encoding': 'Quoted-Printable',
+ })
isbns = get_isbnlike(content)
for item in isbns:
isbn = get_canonical_isbn(item, output='isbn13')
if isbn:
break
- if not isbns or not isbn: # pragma: no cover
+ if not isbns or not isbn: # pragma: no cover
LOGGER.debug('No ISBN found for %s', words)
- return
+ return None
return isbn
diff -Nru isbnlib-3.5.6/isbnlib/_imcache.py isbnlib-3.9.3/isbnlib/_imcache.py
--- isbnlib-3.5.6/isbnlib/_imcache.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/_imcache.py 2018-10-05 11:18:35.000000000 +0000
@@ -1,13 +1,10 @@
# -*- coding: utf-8 -*-
-
"""Read and write to a dict-like cache."""
-
from collections import MutableMapping
class IMCache(MutableMapping):
-
"""Read and write to a dict-like cache."""
MAXLEN = 1000
@@ -35,3 +32,15 @@
def __delitem__(self, k):
del self.d[k]
+
+ def __bool__(self):
+ return len(self) != 0
+
+ # For PY2 compatibility
+ __nonzero__ = __bool__
+
+ def __call__(self, k):
+ try:
+ return self.__getitem__(k)
+ except KeyError:
+ return None
diff -Nru isbnlib-3.5.6/isbnlib/__init__.py isbnlib-3.9.3/isbnlib/__init__.py
--- isbnlib-3.5.6/isbnlib/__init__.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/__init__.py 2018-10-05 11:18:35.000000000 +0000
@@ -1,33 +1,24 @@
# -*- coding: utf-8 -*-
# flake8: noqa
# isort:skip_file
+"""Library to validate, clean, transform and get metadata of ISBN strings (for devs)."""
-"""Define isbnlib API and set lib environment."""
+# Define isbnlib API and set lib environment
import logging as _logging
from ._exceptions import (quiet_errors, ISBNLibException,
- NotRecognizedServiceError,
- NotValidISBNError,
+ NotRecognizedServiceError, NotValidISBNError,
PluginNotLoadedError)
-# config _logging for lib (NullHandler not available for py26)
-try:
- _nh = _logging.NullHandler()
-except: # pragma: no cover
- class NullHandler(_logging.Handler):
- def emit(self, record):
- pass
- _nh = NullHandler()
-_logging.getLogger('isbnlib').addHandler(_nh)
-
# configuration
-from . import config # <-- first import
+from . import config # <-- first import
# main modules
-from ._core import (is_isbn10, is_isbn13, to_isbn10, to_isbn13, clean,
- canonical, notisbn, get_isbnlike, get_canonical_isbn,
- EAN13)
+from ._core import (is_isbn10, is_isbn13, to_isbn10, to_isbn13, check_digit10,
+ check_digit13, clean, canonical, notisbn, get_isbnlike,
+ get_canonical_isbn, GTIN13, EAN13, RE_ISBN10, RE_ISBN13,
+ RE_LOOSE, RE_NORMAL, RE_STRICT)
from ._ext import (cover, desc, mask, meta, info, editions, isbn_from_words,
doi, ren)
from ._goom import query as goom
@@ -36,20 +27,24 @@
# Ranges Database date
from ._data.data4mask import RDDATE
+# config _logging for lib
+_nh = _logging.NullHandler()
+_logging.getLogger('isbnlib').addHandler(_nh)
+
# alias
ISBN13 = EAN13
ean13 = EAN13
# dunders
-__all__ = ('is_isbn10', 'is_isbn13', 'clean', 'mask', 'info', 'meta',
- 'to_isbn10', 'to_isbn13', 'get_isbnlike', 'notisbn',
- 'ean13', 'EAN13', 'cover', 'desc',
- 'canonical', 'get_canonical_isbn', 'editions', 'isbn_from_words',
- 'quiet_errors', 'config', '__version__', '__support__',
- 'doi', 'ren', 'ISBN13', 'ISBNLibException',
- 'NotRecognizedServiceError', 'NotValidISBNError',
- 'PluginNotLoadedError', 'goom', 'doi2tex', 'RDDATE')
+__all__ = ('is_isbn10', 'is_isbn13', 'clean', 'check_digit10', 'check_digit13',
+ 'mask', 'info', 'meta', 'to_isbn10', 'to_isbn13', 'get_isbnlike',
+ 'notisbn', 'ean13', 'EAN13', 'cover', 'desc', 'canonical',
+ 'get_canonical_isbn', 'editions', 'isbn_from_words', 'quiet_errors',
+ 'config', '__version__', '__support__', 'doi', 'ren', 'ISBN13',
+ 'GTIN13', 'ISBNLibException', 'NotRecognizedServiceError',
+ 'NotValidISBNError', 'PluginNotLoadedError', 'goom', 'doi2tex',
+ 'RDDATE')
-__version__ = '3.5.6' # <-- literal IDs
-__support__ = 'py26, py27, py33, py34, pypy' # <-- literal IDs
+__version__ = '3.9.3' # <-- literal IDs
+__support__ = 'py27, py34, py35, py36, py37, pypy, pypy3' # <-- literal IDs
diff -Nru isbnlib-3.5.6/isbnlib/_isbndb.py isbnlib-3.9.3/isbnlib/_isbndb.py
--- isbnlib-3.5.6/isbnlib/_isbndb.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/_isbndb.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,79 +0,0 @@
-# -*- coding: utf-8 -*-
-"""Query the isbndb.org service for metadata."""
-
-import logging
-import re
-
-from .config import apikeys
-from .dev import stdmeta
-from .dev._bouth23 import u
-from .dev._exceptions import (DataWrongShapeError, ISBNNotConsistentError,
- NoAPIKeyError, NoDataForSelectorError,
- RecordMappingError)
-from .dev.webquery import query as wquery
-
-UA = 'isbnlib (gzip)'
-SERVICE_URL = 'http://isbndb.com/api/v2/json/{apikey}/book/{isbn}'
-PATT_YEAR = re.compile(r'\d{4}')
-LOGGER = logging.getLogger(__name__)
-
-
-def _mapper(isbn, records):
- """Map canonical <- records."""
- # canonical:
- # -> ISBN-13, Title, Authors, Publisher, Year, Language
- try:
- # mapping: canonical <- records
- canonical = {}
- canonical['ISBN-13'] = u(isbn)
- # assert isbn == records['isbn13'], "isbn was mungled!"
- canonical['Title'] = records.get('title', u(''))
- authors = [a['name'] for a in records['author_data']]
- canonical['Authors'] = authors
- canonical['Publisher'] = records.get('publisher_name', u(''))
- canonical['Year'] = u('')
- if 'edition_info' in records:
- match = re.search(PATT_YEAR, records['edition_info'])
- if match:
- canonical['Year'] = str(match.group(0))
- canonical['Language'] = records.get('language', u(''))
- except:
- raise RecordMappingError(isbn)
- # call stdmeta for extra cleanning and validation
- return stdmeta(canonical)
-
-
-def _records(isbn, data):
- """Classify (canonically) the parsed data."""
- # check status
- try:
- err = data.get('error', '')
- if err:
- raise
- except:
- LOGGER.debug('DataWrongShapeError for %s with status %s',
- isbn, err)
- raise DataWrongShapeError("error: '%s' for isbn %s" % (err, isbn))
- # put the selected data in records
- try:
- recs = data['data'][0]
- except: # pragma: no cover
- LOGGER.debug('NoDataForSelectorError for %s', isbn)
- raise NoDataForSelectorError(isbn)
- # consistency check (isbn request = isbn response)
- if recs:
- ids = recs.get('isbn13', '')
- if isbn not in repr(ids): # pragma: no cover
- LOGGER.debug('ISBNNotConsistentError for %s (%s)', isbn, repr(ids))
- raise ISBNNotConsistentError("%s not in %s" % (isbn, repr(ids)))
- # map canonical <- records
- return _mapper(isbn, recs)
-
-
-def query(isbn):
- """Query the isbndb.org service for metadata."""
- if not apikeys.get('isbndb'):
- raise NoAPIKeyError
- data = wquery(SERVICE_URL.format(apikey=apikeys['isbndb'], isbn=isbn),
- user_agent=UA)
- return _records(isbn, data)
diff -Nru isbnlib-3.5.6/isbnlib/_merge.py isbnlib-3.9.3/isbnlib/_merge.py
--- isbnlib-3.5.6/isbnlib/_merge.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/_merge.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,40 +0,0 @@
-# -*- coding: utf-8 -*-
-"""Provide metadata by merging metadata from other providers."""
-
-from . import config
-from ._goob import query as qgoob
-from ._wcat import query as qwcat
-from .dev import Metadata, vias
-
-
-def query(isbn, processor=None):
- """Query function for the 'merge provider' (waterfall model)."""
- if not processor:
- processor = config.options.get('VIAS_MERGE', processor).lower()
- if not processor: # pragma: no cover
- processor = 'serial'
-
- named_tasks = (('wcat', qwcat), ('goob', qgoob))
- if processor == 'parallel':
- results = vias.parallel(named_tasks, isbn)
- elif processor == 'serial':
- results = vias.serial(named_tasks, isbn)
- elif processor == 'multi':
- results = vias.multi(named_tasks, isbn)
-
- rw = results.get('wcat', None)
- rg = results.get('goob', None)
-
- if not rw and not rg: # pragma: no cover
- return None
-
- md = Metadata(rw) if rw else None
-
- if md and rg:
- # Overwrite with Authors and Language from Google
- md.merge(rg, overwrite=('Authors'))
- return md.value
- if not md and rg: # pragma: no cover
- md = Metadata(rg)
- return md.value
- return md.value if not rg and rw else None # pragma: no cover
diff -Nru isbnlib-3.5.6/isbnlib/_metadata.py isbnlib-3.9.3/isbnlib/_metadata.py
--- isbnlib-3.5.6/isbnlib/_metadata.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/_metadata.py 2018-10-05 11:18:35.000000000 +0000
@@ -8,24 +8,26 @@
def query(isbn, service='default', cache='default'):
"""Query worldcat.org, Google Books (JSON API), ... for metadata."""
- from .registry import metadata_cache # <-- dinamic now!
- ean = EAN13(isbn) # <-- XXX maybe this is too strict?
+ # validate inputs
+ ean = EAN13(isbn)
if not ean:
raise NotValidISBNError(isbn)
isbn = ean
- if cache == 'default':
- cache = metadata_cache
if service != 'default' and service not in services: # pragma: no cover
raise NotRecognizedServiceError(service)
- if cache is None: # pragma: no cover
+ # set cache and get metadata
+ if cache is None: # pragma: no cover
return services[service](isbn)
+ if cache == 'default':
+ from .registry import metadata_cache
+ cache = metadata_cache
key = isbn + service
try:
if cache[key]:
return cache[key]
- else: # pragma: no cover
- raise # <-- IMPORTANT: usually the caches don't return error!
- except:
+ else: # pragma: no cover
+ raise # <-- IMPORTANT: "caches don't return error"!
+ except Exception:
meta = services[service](isbn)
if meta:
cache[key] = meta
diff -Nru isbnlib-3.5.6/isbnlib/_msk.py isbnlib-3.9.3/isbnlib/_msk.py
--- isbnlib-3.5.6/isbnlib/_msk.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/_msk.py 2018-10-05 11:18:35.000000000 +0000
@@ -34,13 +34,13 @@
isbn10 = True
idx = None
- check = ib[-1:] # <-- hack!
+ check = ib[-1:] # <-- HACK!
cur = 3
igi = cur
buf = ib[igi:cur + 1]
group = ib[0:cur] + '-' + buf
- for _ in range(6): # pragma: no cover
+ for _ in range(6): # pragma: no cover
if group in ranges:
sevens = ib[cur + 1:cur + 8].ljust(7, '0')
for l in ranges[group]:
@@ -50,14 +50,14 @@
break
cur += 1
buf = ib[igi:cur + 1]
- group = group + buf[-1:] # <-- hack!
+ group = group + buf[-1:] # <-- HACK!
if idx:
if isbn10:
group = group[4:]
check = check10
- return separator.join([group, ib[cur + 1:cur + idx + 1],
- ib[cur + idx + 1:-1], check])
+ return separator.join(
+ [group, ib[cur + 1:cur + idx + 1], ib[cur + idx + 1:-1], check])
LOGGER.warning('identifier not found! '
'Please, update the program.') # pragma: no cover
- return # pragma: no cover
+ return None
diff -Nru isbnlib-3.5.6/isbnlib/_openled.py isbnlib-3.9.3/isbnlib/_openled.py
--- isbnlib-3.5.6/isbnlib/_openled.py 1970-01-01 00:00:00.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/_openled.py 2018-10-05 11:18:35.000000000 +0000
@@ -0,0 +1,36 @@
+# -*- coding: utf-8 -*-
+"""Query the Open Library for related ISBNs."""
+
+import logging
+
+from . import get_canonical_isbn, get_isbnlike
+from .dev._bouth23 import u
+from .dev.webquery import query as wquery
+
+LOGGER = logging.getLogger(__name__)
+UA = 'isbnlib (gzip)'
+SERVICE_URL = 'http://openlibrary.org/query.json?type=/type/edition&'\
+ '{selectors}'
+CODES = 'isbn_13={isbn}&books='
+ISBNS = '{code}&isbn_13='
+
+
+def query(isbn):
+ """Query the Open Library for related ISBNs."""
+ try:
+ data = wquery(
+ SERVICE_URL.format(selectors=CODES.format(isbn=isbn)),
+ user_agent=UA)
+ codes = [rec['key'] for rec in data]
+ isbnlikes = [isbn]
+ for code in codes:
+ txt = wquery(
+ SERVICE_URL.format(selectors=ISBNS.format(code=code)),
+ user_agent=UA,
+ parser=None)
+ isbnlikes.extend(get_isbnlike(txt))
+ isbns = [get_canonical_isbn(isbnlike) for isbnlike in isbnlikes]
+ isbns = sorted(list(set([u(n) for n in isbns if n]))) # qa: py26
+ except Exception: # pragma: no cover, qa: FIXME
+ LOGGER.debug('No data from Open Library for isbn %s', isbn)
+ return isbns
diff -Nru isbnlib-3.5.6/isbnlib/_openl.py isbnlib-3.9.3/isbnlib/_openl.py
--- isbnlib-3.5.6/isbnlib/_openl.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/_openl.py 2018-10-05 11:18:35.000000000 +0000
@@ -24,17 +24,23 @@
canonical = {}
canonical['ISBN-13'] = u(isbn)
canonical['Title'] = records.get('title', u('')).replace(' :', ':')
- canonical['Authors'] = [a['name'] for a in
- records.get('authors', ({'name': u('')},))]
- canonical['Publisher'] = records.get('publishers',
- [{'name': u('')}, ])[0]['name']
+ canonical['Authors'] = [
+ a['name'] for a in records.get('authors', ({
+ 'name': u(''),
+ }, ))
+ ]
+ canonical['Publisher'] = records.get('publishers', [
+ {
+ 'name': u(''),
+ },
+ ])[0]['name']
canonical['Year'] = u('')
strdate = records.get('publish_date', u(''))
- if strdate: # pragma: no cover
+ if strdate: # pragma: no cover
match = re.search(r'\d{4}', strdate)
if match:
canonical['Year'] = match.group(0)
- except: # pragma: no cover
+ except: # pragma: no cover
LOGGER.debug("RecordMappingError for %s with data %s", isbn, records)
raise RecordMappingError(isbn)
# call stdmeta for extra cleanning and validation
@@ -46,7 +52,7 @@
try:
# put the selected data in records
records = data['ISBN:%s' % isbn]
- except: # pragma: no cover
+ except: # pragma: no cover
LOGGER.debug('NoDataForSelectorError for %s', isbn)
raise NoDataForSelectorError(isbn)
diff -Nru isbnlib-3.5.6/isbnlib/registry.py isbnlib-3.9.3/isbnlib/registry.py
--- isbnlib-3.5.6/isbnlib/registry.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/registry.py 2018-10-05 11:18:35.000000000 +0000
@@ -1,34 +1,29 @@
# -*- coding: utf-8 -*-
-
"""Registry for metadata services, formatters and cache."""
+from pkg_resources import iter_entry_points
from . import _goob as goob
-from . import _isbndb as isbndb
-from . import _merge as merge
from . import _openl as openl
-from . import _wcat as wcat
from ._imcache import IMCache
-from .dev._fmt import fmtbib
+from .dev._fmt import _fmtbib
# SERVICES
-services = {'default': merge.query,
- 'wcat': wcat.query,
- 'goob': goob.query,
- 'merge': merge.query,
- 'openl': openl.query,
- 'isbndb': isbndb.query
- }
+services = {
+ 'default': goob.query,
+ 'goob': goob.query,
+ 'openl': openl.query,
+}
-def setdefaultservice(name): # pragma: no cover
+def setdefaultservice(name): # pragma: no cover
"""Set the default service."""
global services
services['default'] = services[name]
-def add_service(name, query): # pragma: no cover
+def add_service(name, query): # pragma: no cover
"""Add a new service to services."""
global services
services[name] = query
@@ -36,52 +31,64 @@
# FORMATTERS
-bibformatters = {'default': lambda x: fmtbib('labels', x),
- 'labels': lambda x: fmtbib('labels', x),
- 'bibtex': lambda x: fmtbib('bibtex', x),
- 'endnote': lambda x: fmtbib('endnote', x),
- 'refworks': lambda x: fmtbib('refworks', x),
- 'msword': lambda x: fmtbib('msword', x),
- 'json': lambda x: fmtbib('json', x),
- 'opf': lambda x: fmtbib('opf', x)} # pragma: no cover
+bibformatters = {
+ 'default': lambda x: _fmtbib('labels', x),
+ 'labels': lambda x: _fmtbib('labels', x),
+ 'bibtex': lambda x: _fmtbib('bibtex', x),
+ 'csl': lambda x: _fmtbib('csl', x),
+ 'json': lambda x: _fmtbib('json', x),
+ 'opf': lambda x: _fmtbib('opf', x),
+ 'endnote': lambda x: _fmtbib('endnote', x),
+ 'refworks': lambda x: _fmtbib('refworks', x),
+ 'msword': lambda x: _fmtbib('msword', x),
+} # pragma: no cover
-def setdefaultbibformatter(name): # pragma: no cover
+def setdefaultbibformatter(name): # pragma: no cover
"""Set the default formatter."""
global bibformatters
bibformatters['default'] = bibformatters[name]
-def add_bibformatter(name, formatter): # pragma: no cover
+def add_bibformatter(name, formatter): # pragma: no cover
"""Add a new formatter to formatters."""
global bibformatters
bibformatters[name] = formatter
-# CACHE
-# if you want a persistant cache you could use
-# .dev.helpers ShelveCache(pathtofile)
+def load_plugins(): # pragma: no cover
+ """Load plugins with groups: isbnlib.metadata & isbnlib.formatters."""
+ # get metadata plugins from entry_points
+ try:
+ for entry in iter_entry_points(group='isbnlib.metadata'):
+ add_service(entry.name, entry.load())
+ except:
+ pass
+ # get formatters from entry_points
+ try:
+ for entry in iter_entry_points(group='isbnlib.formatters'):
+ add_bibformatter(entry.name, entry.load())
+ except:
+ pass
-metadata_cache = IMCache() # should be an instance
+# load plugins on import
+load_plugins()
+
+# CACHE
+metadata_cache = IMCache() # should be an instance
-def set_cache(cache): # pragma: no cover
+
+def set_cache(cache): # pragma: no cover
"""Set cache for metadata."""
global metadata_cache
metadata_cache = cache
-covers_cache = None # should be an instance
-
-
-def set_covers_cache(cache): # pragma: no cover
- """Set cache for covers."""
- global covers_cache
- covers_cache = cache
-custom_cache = None # should be an instance
+custom_cache = None # should be an instance
-def set_custom_cache(cache): # pragma: no cover
+def set_custom_cache(cache): # pragma: no cover
"""Set a 'spare' cache."""
global custom_cache
custom_cache = cache
diff -Nru isbnlib-3.5.6/isbnlib/test/data4tests.py isbnlib-3.9.3/isbnlib/test/data4tests.py
--- isbnlib-3.5.6/isbnlib/test/data4tests.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/test/data4tests.py 2018-10-05 11:18:35.000000000 +0000
@@ -81,4 +81,5 @@
ISBN 978-99937-1-056-1
ISBN 978-99965-2-047-1
'''
+
# flake8: noqa
diff -Nru isbnlib-3.5.6/isbnlib/test/__init__.py isbnlib-3.9.3/isbnlib/test/__init__.py
--- isbnlib-3.5.6/isbnlib/test/__init__.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/test/__init__.py 2018-10-05 11:18:35.000000000 +0000
@@ -0,0 +1 @@
+
diff -Nru isbnlib-3.5.6/isbnlib/test/test_core.py isbnlib-3.9.3/isbnlib/test/test_core.py
--- isbnlib-3.5.6/isbnlib/test/test_core.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/test/test_core.py 2018-10-05 11:18:35.000000000 +0000
@@ -3,33 +3,34 @@
# pylint: skip-file
from nose.tools import assert_equals
-from .._core import (_check_digit10, _check_digit13, _check_structure10,
- _check_structure13, is_isbn10, is_isbn13, to_isbn10, to_isbn13,
- canonical, clean, notisbn, get_isbnlike, get_canonical_isbn, EAN13)
+from .._core import (check_digit10, check_digit13, _check_structure10,
+ _check_structure13, is_isbn10, is_isbn13, to_isbn10,
+ to_isbn13, canonical, clean, notisbn, get_isbnlike,
+ get_canonical_isbn, EAN13)
from .data4tests import ISBNs
-
# nose tests
-def test__check_digit10():
+
+def test_check_digit10():
"""Test check digit algo for ISBN-10."""
- assert_equals(_check_digit10('082649752'), '7')
- assert_equals(_check_digit10('585270001'), '0')
- assert_equals(_check_digit10('08264975X'), None)
- assert_equals(_check_digit10('08264975'), None)
+ assert_equals(check_digit10('082649752'), '7')
+ assert_equals(check_digit10('585270001'), '0')
+ assert_equals(check_digit10('08264975X'), None)
+ assert_equals(check_digit10('08264975'), None)
-def test__check_digit13():
+def test_check_digit13():
"""Test check digit algo for ISBN-13."""
- assert_equals(_check_digit13('978082649752'), '9')
- assert_equals(_check_digit13('97808264975'), None)
- assert_equals(_check_digit13('97808264975X'), None)
+ assert_equals(check_digit13('978082649752'), '9')
+ assert_equals(check_digit13('97808264975'), None)
+ assert_equals(check_digit13('97808264975X'), None)
def test__check_structure10():
"""Test structure detection for ISBN-10."""
assert_equals(_check_structure10('0826497527'), True)
- assert_equals(_check_structure10('0826497X27'), True) # isbnlike!
+ assert_equals(_check_structure10('0826497X27'), True) # isbnlike!
assert_equals(_check_structure10('0826497XI7'), False)
@@ -62,10 +63,10 @@
"""Test transformation of ISBN to ISBN-10."""
assert_equals(to_isbn10('9780826497529'), '0826497527')
assert_equals(to_isbn10('0826497527'), '0826497527')
- assert_equals(to_isbn10('9780826497520'), None) # ISBN13 not valid
+ assert_equals(to_isbn10('9780826497520'), None) # ISBN13 not valid
assert_equals(to_isbn10('9790826497529'), None)
assert_equals(to_isbn10('97808264975X3'), None)
- assert_equals(to_isbn10('978-826497'), None) # (bug #14)
+ assert_equals(to_isbn10('978-826497'), None) # (bug #14)
assert_equals(to_isbn10('isbn 0-8264-9752-7'), '0826497527')
assert_equals(to_isbn10('isbn 979-10-90636-07-1'), None)
assert_equals(to_isbn10('isbn 978-0-8264-9752-9'), '0826497527')
@@ -76,11 +77,12 @@
"""Test transformation of ISBN to ISBN-13."""
assert_equals(to_isbn13('0826497527'), '9780826497529')
assert_equals(to_isbn13('9780826497529'), '9780826497529')
- assert_equals(to_isbn13('0826497520'), None) # ISBN10 not valid
+ assert_equals(to_isbn13('0826497520'), None) # ISBN10 not valid
assert_equals(to_isbn13('08X6497527'), None)
- assert_equals(to_isbn13('91-43-01019-9'), '9789143010190') # (bug #14)
+ assert_equals(to_isbn13('91-43-01019-9'), '9789143010190') # (bug #14)
assert_equals(to_isbn13('isbn 91-43-01019-9'), '9789143010190')
- assert_equals(to_isbn13('asd isbn 979-10-90636-07-1 blabla'), '9791090636071')
+ assert_equals(
+ to_isbn13('asd isbn 979-10-90636-07-1 blabla'), '9791090636071')
def test_clean():
@@ -118,17 +120,23 @@
def test_get_canonical_isbn():
"""Test the extraction of canonical ISBN from ISBN-like string."""
- assert_equals(get_canonical_isbn('0826497527', output='bouth'),
- '0826497527')
+ assert_equals(
+ get_canonical_isbn(
+ '0826497527', output='bouth'), '0826497527')
assert_equals(get_canonical_isbn('0826497527'), '0826497527')
- assert_equals(get_canonical_isbn('0826497527', output='isbn10'),
- '0826497527')
- assert_equals(get_canonical_isbn('0826497527', output='isbn13'),
- '9780826497529')
- assert_equals(get_canonical_isbn('ISBN 0826497527', output='isbn13'),
- '9780826497529')
- assert_equals(get_canonical_isbn('ISBN 0826497527', output='NOOPTION'),
- None)
+ assert_equals(
+ get_canonical_isbn(
+ '0826497527', output='isbn10'), '0826497527')
+ assert_equals(
+ get_canonical_isbn(
+ '0826497527', output='isbn13'), '9780826497529')
+ assert_equals(
+ get_canonical_isbn(
+ 'ISBN 0826497527', output='isbn13'),
+ '9780826497529')
+ assert_equals(
+ get_canonical_isbn(
+ 'ISBN 0826497527', output='NOOPTION'), None)
assert_equals(get_canonical_isbn('0826497520'), None)
assert_equals(get_canonical_isbn('9780826497529'), '9780826497529')
assert_equals(get_canonical_isbn('9780826497520'), None)
diff -Nru isbnlib-3.5.6/isbnlib/test/test_data.py isbnlib-3.9.3/isbnlib/test/test_data.py
--- isbnlib-3.5.6/isbnlib/test/test_data.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/test/test_data.py 2018-10-05 11:18:35.000000000 +0000
@@ -13,52 +13,53 @@
def test_stdmeta():
"""Test the transformation of raw records into standard metadata."""
# test stdmeta from data
- r={
- 'ISBN-13': u('9780123456789 '),
- 'Title': u('Bla. Bla /Title .'),
- 'Publisher': u(''),
- 'Year': u('2000'),
- 'Language': u('en'),
- 'Authors': [u('author1. mba'), u('author2 ')]
- }
- R={
- 'ISBN-13': u('9780123456789'),
- 'Title': u('Bla. Bla /Title'),
- 'Publisher': u(''),
- 'Year': u('2000'),
- 'Language': u('en'),
- 'Authors': [u('author1. mba'), u('author2')]
- }
- A={
- 'ISBN-13': u('9780123456789 '),
- 'Title': b'Bla. Bla /Title .',
- 'Publisher': u(''),
- 'Year': b'2000',
- 'Language': u('en'),
- 'Authors': [u('author1. mba'), u('author2 ')]
- }
- B={
- 'ISBN-13': u('9780123456789'),
- 'Title': u('Bla. Bla /Title .'),
- 'Publisher': u(''),
- 'Year': u('2000'),
- 'Language': u('en'),
- 'Authors': u('author1')
- }
+ r = {
+ 'ISBN-13': u('9780123456789 '),
+ 'Title': u('Bla. Bla /Title .'),
+ 'Publisher': u(''),
+ 'Year': u('2000'),
+ 'Language': u('en'),
+ 'Authors': [u('author1. mba'), u('author2 ')]
+ }
+ R = {
+ 'ISBN-13': u('9780123456789'),
+ 'Title': u('Bla. Bla /Title'),
+ 'Publisher': u(''),
+ 'Year': u('2000'),
+ 'Language': u('en'),
+ 'Authors': [u('author1. mba'), u('author2')]
+ }
+ A = {
+ 'ISBN-13': u('9780123456789 '),
+ 'Title': b'Bla. Bla /Title .',
+ 'Publisher': u(''),
+ 'Year': b'2000',
+ 'Language': u('en'),
+ 'Authors': [u('author1. mba'), u('author2 ')]
+ }
+ B = {
+ 'ISBN-13': u('9780123456789'),
+ 'Title': u('Bla. Bla /Title .'),
+ 'Publisher': u(''),
+ 'Year': u('2000'),
+ 'Language': u('en'),
+ 'Authors': u('author1')
+ }
assert_equals(stdmeta(r), R)
assert_equals(stdmeta(R), R)
assert_raises(Exception, stdmeta, A)
assert_raises(Exception, stdmeta, B)
+
def test_metaclass():
"""Test the creation of a Metadata class from raw records."""
- R={
- 'ISBN-13': u('9780123456789'),
- 'Title': u('Bla. Bla /Title'),
- 'Publisher': u(''),
- 'Year': u('2000'),
- 'Language': u('en'),
- 'Authors': [u('author1. mba'), u('author2')]
- }
+ R = {
+ 'ISBN-13': u('9780123456789'),
+ 'Title': u('Bla. Bla /Title'),
+ 'Publisher': u(''),
+ 'Year': u('2000'),
+ 'Language': u('en'),
+ 'Authors': [u('author1. mba'), u('author2')]
+ }
dt = Metadata(R)
assert_equals(dt.value, R)
diff -Nru isbnlib-3.5.6/isbnlib/test/test_doi2tex.py isbnlib-3.9.3/isbnlib/test/test_doi2tex.py
--- isbnlib-3.5.6/isbnlib/test/test_doi2tex.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/test/test_doi2tex.py 2018-10-05 11:18:35.000000000 +0000
@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
# flake8: noqa
# pylint: skip-file
-
"""
nose tests
"""
diff -Nru isbnlib-3.5.6/isbnlib/test/test_editions.py isbnlib-3.9.3/isbnlib/test/test_editions.py
--- isbnlib-3.5.6/isbnlib/test/test_editions.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/test/test_editions.py 2018-10-05 11:18:35.000000000 +0000
@@ -7,25 +7,37 @@
from .._exceptions import NotRecognizedServiceError, NotValidISBNError
from .._ext import editions
-
# nose tests
-def test_editions1():
- """Test the 'editions' service."""
- assert_equals(len(editions('9780156001311', service='wcat')) > 19, True)
+
+def test_editions_openl():
+ """Test the 'openl editions' service."""
+ assert_equals(len(editions('9780099536017', service='openl')) > 4, True)
+
+
+def test_editions_thingl():
+ """Test the 'thingl editions' service."""
assert_equals(len(editions('9780151446476', service='thingl')) > 19, True)
+
+
+def test_editions_any():
+ """Test the 'any editions' service."""
assert_equals(len(editions('9780151446476', service='any')) > 19, True)
+
+
+def test_editions_merge():
+ """Test the 'merge editions' service."""
assert_equals(len(editions('9780151446476', service='merge')) > 19, True)
@raises(NotValidISBNError)
-def test_editions2():
+def test_editions_NotValidISBNError():
"""Test the 'editions' service error detection (NotValidISBNError)."""
editions('978')
@raises(NotRecognizedServiceError)
-def test_editions3():
+def test_editions_NotRecognizedServiceError():
"""Test the 'editions' service error detection (NotRecognizedServiceError)."""
editions('9780156001311', service='xxx')
diff -Nru isbnlib-3.5.6/isbnlib/test/test_ext.py isbnlib-3.9.3/isbnlib/test/test_ext.py
--- isbnlib-3.5.6/isbnlib/test/test_ext.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/test/test_ext.py 2018-10-05 11:18:35.000000000 +0000
@@ -5,7 +5,6 @@
from nose.tools import assert_equals, assert_raises
from .._ext import mask, editions, isbn_from_words, doi, desc, cover
-
# nose tests
@@ -29,7 +28,8 @@
assert_equals(mask('9789993075899'), '978-99930-75-89-9')
assert_equals(mask('0-330284983'), '0-330-28498-3')
assert_equals(mask('9791090636071'), '979-10-90636-07-1')
- assert_equals(mask('9786131796364'), '978-613-1-79636-4') # <-- prefix with 1 rule
+ assert_equals(
+ mask('9786131796364'), '978-613-1-79636-4') # <-- prefix with 1 rule
assert_equals(mask('isbn 979-10-90636-07-1'), '979-10-90636-07-1')
assert_raises(Exception, mask, '')
assert_raises(Exception, mask, '9786')
@@ -56,9 +56,9 @@
def test_cover():
"""Test 'cover' command."""
- assert_equals(cover('9780156001311')[1][:13], '9780156001311') # <-- no size 2 (in most areas) but size 1
- assert_equals(cover('9780000000000'), None) # <-- invalid ISBN
- assert_equals(cover('9781408835029')[1][:13], '9781408835029')
- assert_equals(cover('9789727576807')[1], None) # <-- no image of any size
-
-
+ assert_equals(len(repr(cover('9780156001311'))) > 50, True)
+ assert_equals(cover('9780000000000'), None) # <-- invalid ISBN
+ assert_equals(len(repr(cover('9781408835029'))) > 50, True)
+ assert_equals(
+ len(repr(cover('9789727576807'))) < 50,
+ True) # <-- no image of any size
diff -Nru isbnlib-3.5.6/isbnlib/test/test_files.py isbnlib-3.9.3/isbnlib/test/test_files.py
--- isbnlib-3.5.6/isbnlib/test/test_files.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/test/test_files.py 2018-10-05 11:18:35.000000000 +0000
@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
# flake8: noqa
# pylint: skip-file
-
""" nose tests
"""
@@ -17,28 +16,34 @@
TESTFILE = './ç-deleteme.pdf' if WINDOWS else '/tmp/海明威-deleteme.pdf'
NEW_BASENAME = 'ç-deleteme-PLEASE.pdf' if WINDOWS else '海明威-deleteme-PLEASE.pdf'
else:
- print("Your default locale encoding (%s) doesn't allow unicode filenames!" % ENCODING)
+ print("Your default locale encoding (%s) doesn't allow unicode filenames!"
+ % ENCODING)
TESTFILE = './deleteme.pdf'
NEW_BASENAME = 'deleteme-PLEASE.pdf'
+
def setup_module():
with open(TESTFILE, 'w') as f:
- f.write('ooo')
+ f.write('ooo')
os.chdir(os.path.dirname(TESTFILE))
+
def teardown_module():
os.remove(os.path.join(os.path.dirname(TESTFILE), NEW_BASENAME))
+
def test_isfile():
"""Test if a path is a file."""
f = File(TESTFILE)
assert f.isfile(TESTFILE) == True
+
def test_exists():
"""Test if a path is a file or a directory."""
f = File(TESTFILE)
assert f.exists(TESTFILE) == True
+
def test_validate():
"""Test if a string is a valid filename for 'ren' command."""
f = File(TESTFILE)
diff -Nru isbnlib-3.5.6/isbnlib/test/test_fmt.py isbnlib-3.9.3/isbnlib/test/test_fmt.py
--- isbnlib-3.5.6/isbnlib/test/test_fmt.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/test/test_fmt.py 2018-10-05 11:18:35.000000000 +0000
@@ -1,31 +1,31 @@
# -*- coding: utf-8 -*-
# flake8: noqa
# pylint: skip-file
-
"""
nose tests
"""
from nose.tools import assert_equals
from ..dev._bouth23 import u
-from ..dev._fmt import fmtbib
-
+from ..dev._fmt import _fmtbib
canonical = {
- 'ISBN-13': u('9780123456789'),
- 'Title': u('A book about nothing'),
- 'Publisher': u('No Paper Press'),
- 'Year': u('2000'),
- 'Language': u('en'),
- 'Authors': [u('John Smith'), u('José Silva')]
- }
+ 'ISBN-13': u('9780123456789'),
+ 'Title': u('A book about nothing'),
+ 'Publisher': u('No Paper Press'),
+ 'Year': u('2000'),
+ 'Language': u('en'),
+ 'Authors': [u('John Smith'), u('José Silva')]
+}
+
def test_fmtbib():
"""Test the formating into several bibliographic formats."""
- assert_equals(len(fmtbib("bibtex", canonical)), 182)
- assert_equals(len(fmtbib("labels", canonical)), 158)
- assert_equals(len(fmtbib("endnote", canonical)), 103)
- assert_equals(len(fmtbib("msword", canonical)), 485)
- assert_equals(len(fmtbib("json", canonical)), 229)
- assert_equals(len(fmtbib("refworks", canonical)), 130)
- assert_equals(len(fmtbib("opf", canonical)), 861)
+ assert_equals(len(_fmtbib("bibtex", canonical)), 182)
+ assert_equals(len(_fmtbib("labels", canonical)), 158)
+ assert_equals(len(_fmtbib("endnote", canonical)), 103)
+ assert_equals(len(_fmtbib("msword", canonical)), 485)
+ assert_equals(len(_fmtbib("json", canonical)), 229)
+ assert_equals(len(_fmtbib("csl", canonical)), 253)
+ assert_equals(len(_fmtbib("refworks", canonical)), 130)
+ assert_equals(len(_fmtbib("opf", canonical)), 861)
diff -Nru isbnlib-3.5.6/isbnlib/test/test_goom.py isbnlib-3.9.3/isbnlib/test/test_goom.py
--- isbnlib-3.5.6/isbnlib/test/test_goom.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/test/test_goom.py 2018-10-05 11:18:35.000000000 +0000
@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
# flake8: noqa
# pylint: skip-file
-
"""
nose tests
"""
@@ -12,4 +11,5 @@
def test_goom():
"""Test the Google's Multiple Books service."""
- assert_equals(len(repr(goom.query('the old man and the sea'))) > 1000, True)
+ assert_equals(len(repr(goom.query('the old man and the sea'))) > 1000,
+ True)
diff -Nru isbnlib-3.5.6/isbnlib/test/test_helpers.py isbnlib-3.9.3/isbnlib/test/test_helpers.py
--- isbnlib-3.5.6/isbnlib/test/test_helpers.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/test/test_helpers.py 2018-10-05 11:18:35.000000000 +0000
@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
# flake8: noqa
# pylint: skip-file
-
"""
nose tests
"""
@@ -12,9 +11,15 @@
def test_last_first():
"""Test the parsing of author's name into (Surname, First Name)."""
- assert_equals(last_first("Surname, First Name"), {"last": "Surname", "first": "First Name"})
- assert_equals(last_first("First Name Surname"), {"last": "Surname", "first": "First Name"})
- assert_equals(last_first("Surname1, First1 and Sur2, First2"), {"last": "Surname1", "first": "First1 and Sur2, First2"})
+ assert_equals(last_first("Surname, First Name"),
+ {"last": "Surname",
+ "first": "First Name"})
+ assert_equals(last_first("First Name Surname"),
+ {"last": "Surname",
+ "first": "First Name"})
+ assert_equals(last_first("Surname1, First1 and Sur2, First2"),
+ {"last": "Surname1",
+ "first": "First1 and Sur2, First2"})
def test_cutoff_tokens():
@@ -24,14 +29,29 @@
def test_parse_placeholders():
"""Test the parsing of placeholders."""
- assert_equals(parse_placeholders('{isbn}_akaj_{name}'), ['{isbn}', '{name}'])
+ assert_equals(parse_placeholders('{isbn}_akaj_{name}'), ['{isbn}', '{name}'
+ ])
def test_fake_isbn():
"""Test the 'fake_isbn' function."""
- assert_equals(fake_isbn(' Hello?? Wer, ! ksDf: asdf. ; '), '1111006407537')
- assert_equals(fake_isbn(' Hello?? Wer, ! ksDf: asdf. ; ', author=''), '1108449680873')
- assert_equals(fake_isbn(' Hello?? Wer, ! ksDf: asdf. ; ', author=' '), '1108449680873')
- assert_equals(fake_isbn(' Hello?? Wer, ! ksDf: asdf. ; ', author='', publisher=''), '1181593982422')
- assert_equals(fake_isbn(' Hello?? Wer, ! ksDf: asdf. ; ', author='a', publisher='K'), '1895031085488')
- assert_equals(fake_isbn(' Hello?? Wer, ! ksDf: asdf. ; ', author='A', publisher='k'), '1895031085488')
+ assert_equals(fake_isbn(' Hello?? Wer, ! ksDf: asdf. ; '),
+ '1111006407537')
+ assert_equals(fake_isbn(' Hello?? Wer, ! ksDf: asdf. ; ',
+ author=''),
+ '1108449680873')
+ assert_equals(fake_isbn(' Hello?? Wer, ! ksDf: asdf. ; ',
+ author=' '),
+ '1108449680873')
+ assert_equals(fake_isbn(' Hello?? Wer, ! ksDf: asdf. ; ',
+ author='',
+ publisher=''),
+ '1181593982422')
+ assert_equals(fake_isbn(' Hello?? Wer, ! ksDf: asdf. ; ',
+ author='a',
+ publisher='K'),
+ '1895031085488')
+ assert_equals(fake_isbn(' Hello?? Wer, ! ksDf: asdf. ; ',
+ author='A',
+ publisher='k'),
+ '1895031085488')
diff -Nru isbnlib-3.5.6/isbnlib/test/test_info.py isbnlib-3.9.3/isbnlib/test/test_info.py
--- isbnlib-3.5.6/isbnlib/test/test_info.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/test/test_info.py 2018-10-05 11:18:35.000000000 +0000
@@ -2,7 +2,6 @@
# flake8: noqa
# pylint: skip-file
-
from .._infogroup import infogroup
from .._ext import info
from nose.tools import assert_equals, assert_raises
@@ -16,16 +15,15 @@
assert_equals(infogroup('7500117019'), "China, People's Republic")
assert_equals(infogroup('7-5001-1701-9'), "China, People's Republic")
assert_equals(infogroup('9524712946'), 'Finland')
- assert_equals(infogroup('0330284983'),
- 'English language')
- assert_equals(infogroup('3796519008'),
- 'German language')
+ assert_equals(infogroup('0330284983'), 'English language')
+ assert_equals(infogroup('3796519008'), 'German language')
assert_raises(Exception, infogroup, '92xxxxxxxxxxx')
assert_raises(Exception, infogroup, '')
assert_equals(infogroup('9791090636071'), 'France')
assert_equals(infogroup('9786131796364'), 'Mauritius')
assert_equals(infogroup('9789992158104'), 'Qatar')
+
def test_ext_info():
"""Test 'info' language/country function."""
assert_equals(info('9524712946'), 'Finland')
diff -Nru isbnlib-3.5.6/isbnlib/test/test_metadata.py isbnlib-3.9.3/isbnlib/test/test_metadata.py
--- isbnlib-3.5.6/isbnlib/test/test_metadata.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/test/test_metadata.py 2018-10-05 11:18:35.000000000 +0000
@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
# flake8: noqa
# pylint: skip-file
-
"""nose tests for metadata."""
from random import randrange
@@ -14,24 +13,21 @@
"""Test the query of metadata with 'low level' queries."""
# test query from metadata
assert_raises(Exception, query, '9781849692341', 'goog')
- assert_raises(Exception, query, '9781849692342', 'goob')
- assert_raises(Exception, query, '9781849692341', 'wcat')
- assert_equals(len(repr(query('9780321534965', 'wcat'))) > 150, True)
- assert_equals(len(repr(query('9780321534965'))) > 150, True)
- assert_equals(len(repr(query('9780321534965', 'merge'))) > 150, True)
- assert_equals(len(repr(query('9780321534965', 'goob'))) > 150, True)
- assert_equals(len(repr(query('9789934015960'))) > 150, True)
- assert_equals(len(repr(query(u'9781118241257'))) > 149, True)
- assert_raises(Exception, query, '9780000000', 'wcat', None)
- assert_raises(Exception, query, randrange(0, 1000000), 'wcat')
+ assert_raises(Exception, query, '9781849692343', 'goob')
+ assert_raises(Exception, query, '9789934015960', 'goob')
+ assert_equals(len(repr(query('9780321534965'))) > 100, True)
+ assert_equals(len(repr(query('9780321534965', 'goob'))) > 100, True)
+ #assert_equals(len(repr(query('9789934015960'))) > 100, True)
+ assert_equals(len(repr(query(u'9781118241257'))) > 100, True)
+ assert_raises(Exception, query, '9780000000', 'goob', None)
+ assert_raises(Exception, query, randrange(0, 1000000), 'goob')
def test_ext_meta():
"""Test the query of metadata with 'high level' meta function."""
# test meta from core
- assert_equals(len(repr(meta('9780321534965', 'wcat'))) > 150, True)
- assert_equals(len(repr(meta('9780321534965', 'merge'))) > 150, True)
- assert_equals(len(repr(meta('9780321534965'))) > 150, True)
- assert_raises(Exception, meta, '9780000000', 'wcat', None)
- assert_raises(Exception, meta, randrange(0, 1000000), 'wcat')
- assert_raises(Exception, meta, '9781849692342', 'goob', None)
+ assert_equals(len(repr(meta('9780321534965', 'goob'))) > 100, True)
+ assert_equals(len(repr(meta('9780321534965'))) > 100, True)
+ assert_raises(Exception, meta, '9780000000', 'goob', None)
+ assert_raises(Exception, meta, randrange(0, 1000000), 'goob')
+ assert_raises(Exception, meta, '9781849692343', 'goob', None)
diff -Nru isbnlib-3.5.6/isbnlib/test/test_openl.py isbnlib-3.9.3/isbnlib/test/test_openl.py
--- isbnlib-3.5.6/isbnlib/test/test_openl.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/test/test_openl.py 2018-10-05 11:18:35.000000000 +0000
@@ -1,8 +1,6 @@
# -*- coding: utf-8 -*-
# flake8: noqa
# pylint: skip-file
-
-
""" nose tests
"""
diff -Nru isbnlib-3.5.6/isbnlib/test/test_rename.py isbnlib-3.9.3/isbnlib/test/test_rename.py
--- isbnlib-3.5.6/isbnlib/test/test_rename.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/test/test_rename.py 2018-10-05 11:18:35.000000000 +0000
@@ -8,7 +8,6 @@
from .._ext import ren
from ..dev._bouth23 import b2u3, u
from ..dev.helpers import File, cwdfiles
-
"""
nose tests
"""
@@ -16,7 +15,8 @@
WINDOWS = os.name == 'nt'
ENCODING = locale.getpreferredencoding()
if ENCODING != 'UTF-8':
- print("Your default locale encoding (%s) doesn't allow unicode filenames!" % ENCODING)
+ print("Your default locale encoding (%s) doesn't allow unicode filenames!"
+ % ENCODING)
print("=> Some tests could fail.")
TESTFILE_1 = './ç-deleteme.pdf' if WINDOWS else '/tmp/ç-deleteme.pdf'
@@ -48,7 +48,8 @@
with open(fn, 'w') as f:
f.write(b2u3('ooo') + b2u3(fn))
except UnicodeEncodeError:
- print("Your default locale (%s) doesn't allow non-ascii filenames!" % locale.CODESET)
+ print("Your default locale (%s) doesn't allow non-ascii filenames!"
+ % locale.CODESET)
def delete_files(fnpatt):
@@ -60,7 +61,8 @@
def setup_module():
# create_files([u(TESTFILE_1), u(TESTFILE_2)])
os.chdir(os.path.dirname(TESTFILE_1))
- create_files(FISBN+[F11])
+ #create_files(FISBN + [F11])
+ create_files([F1])
def teardown_module():
@@ -70,8 +72,8 @@
def test_ren():
"""Test 'high level' ren function."""
ren(F1)
- assert_equals('Knuth2008_The Art Of Computer Programming_9780321534965.pdf' in cwdfiles("*.pdf"), True)
+ assert_equals('Knuth2008_The Art Of Computer Programming_9780321534965.pdf'
+ in cwdfiles("*.pdf"), True)
# create_files([F5])
# ren(F5)
# assert_equals('Campos2011_Emergências obstétricas_9789727576807.pdf' in cwdfiles("*.pdf"), True)
-
diff -Nru isbnlib-3.5.6/isbnlib/test/test_unicode_to_utf8tex.py isbnlib-3.9.3/isbnlib/test/test_unicode_to_utf8tex.py
--- isbnlib-3.5.6/isbnlib/test/test_unicode_to_utf8tex.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/test/test_unicode_to_utf8tex.py 2018-10-05 11:18:35.000000000 +0000
@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
# flake8: noqa
# pylint: skip-file
-
"""
nose tests
"""
@@ -13,4 +12,5 @@
def test_unicode_to_utf8tex():
"""Test 'unicode_to_utf8tex' identity transformation."""
assert_equals(unicode_to_utf8tex(u"\u00E2 \u00F5"), b"\^{a}\space \~{o}")
- assert_equals(unicode_to_utf8tex(u"\u00E2 \u00F5", (b"\\space ",)), b"\^{a} \~{o}")
+ assert_equals(unicode_to_utf8tex(u"\u00E2 \u00F5",
+ (b"\\space ", )), b"\^{a} \~{o}")
diff -Nru isbnlib-3.5.6/isbnlib/test/test_vias.py isbnlib-3.9.3/isbnlib/test/test_vias.py
--- isbnlib-3.5.6/isbnlib/test/test_vias.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/test/test_vias.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,32 +0,0 @@
-# -*- coding: utf-8 -*-
-# flake8: noqa
-# pylint: skip-file
-
-"""
-nose tests
-"""
-
-import os
-
-from .. import _merge as merge
-from nose.tools import assert_equals
-
-
-WINDOWS = os.name == 'nt'
-
-
-def test_vias_modes():
- """Test 'vias' several modes of operation."""
- if WINDOWS:
- # appveyor doesn't allow!
- return
- assert_equals(len(repr(merge.query('9780321534965', 'parallel'))) > 170, True)
- assert_equals(len(repr(merge.query('9780321534965', 'multi'))) > 170, True)
- assert_equals(len(repr(merge.query('9780321534965', 'serial'))) > 170, True)
-
-def test_vias_cache_cleanning():
- """Test 'vias' cache cleanning for serial."""
- # test if the secondary cache (cache in vias) does clears... sequentially
- assert_equals(len(repr(merge.query('9781484206546', 'serial'))) < 20, True) # NO METADATA
- assert_equals(len(repr(merge.query('9780321534965', 'serial'))) > 170, True)
- assert_equals(len(repr(merge.query('9781484206546', 'serial'))) < 20, True) # NO METADATA
diff -Nru isbnlib-3.5.6/isbnlib/test/test_webservice.py isbnlib-3.9.3/isbnlib/test/test_webservice.py
--- isbnlib-3.5.6/isbnlib/test/test_webservice.py 1970-01-01 00:00:00.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/test/test_webservice.py 2018-10-05 11:18:35.000000000 +0000
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+# flake8: noqa
+# pylint: skip-file
+"""
+nose tests
+"""
+
+from ..dev.webservice import query as wsquery
+from nose.tools import assert_equals
+
+
+def test_webservice():
+ """Test that values can be passed to a WebService query."""
+ assert_equals(len(repr(wsquery("http://example.org", values={'some': 'values'}))) > 0,
+ True)
diff -Nru isbnlib-3.5.6/isbnlib/test/test_words.py isbnlib-3.9.3/isbnlib/test/test_words.py
--- isbnlib-3.5.6/isbnlib/test/test_words.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/test/test_words.py 2018-10-05 11:18:35.000000000 +0000
@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
# flake8: noqa
# pylint: skip-file
-
"""
nose tests
"""
@@ -13,4 +12,5 @@
def test_words():
"""Test 'isbn_from_words' function."""
assert_equals(len(words.goos('the old man and the sea')), 13)
+ assert_equals(len(words.goos('Camões Lusíadas')), 13)
# assert_equals(words.goos('-ISBN -isbn') in ('9781364200329', None), True)
diff -Nru isbnlib-3.5.6/isbnlib/_thinged.py isbnlib-3.9.3/isbnlib/_thinged.py
--- isbnlib-3.5.6/isbnlib/_thinged.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/_thinged.py 2018-10-05 11:18:35.000000000 +0000
@@ -29,10 +29,9 @@
def query(isbn):
- """Query the worldcat.org service for related ISBNs."""
- data = wquery(SERVICE_URL.format(isbn=isbn),
- user_agent=UA,
- parser=parser_thinged)
- if not data: # pragma: no cover
+ """Query the ThingISBN service for related ISBNs."""
+ data = wquery(
+ SERVICE_URL.format(isbn=isbn), user_agent=UA, parser=parser_thinged)
+ if not data: # pragma: no cover
LOGGER.debug('No data from ThingISBN for isbn %s', isbn)
return data
diff -Nru isbnlib-3.5.6/isbnlib/_wcated.py isbnlib-3.9.3/isbnlib/_wcated.py
--- isbnlib-3.5.6/isbnlib/_wcated.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/_wcated.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,41 +0,0 @@
-# -*- coding: utf-8 -*-
-"""Query the worldcat.org xID service for related ISBNs."""
-
-import logging
-from ast import literal_eval
-
-from .dev._exceptions import DataWrongShapeError, NoDataForSelectorError
-from .dev.webquery import query as wquery
-
-LOGGER = logging.getLogger(__name__)
-UA = 'isbnlib (gzip)'
-SERVICE_URL = 'http://xisbn.worldcat.org/webservices/xid/isbn/{isbn}?'\
- 'method=getEditions&format=python'
-
-
-def _editions(isbn, data):
- """Return the records from the parsed response."""
- # check status
- try:
- status = data['stat']
- if status != 'ok':
- raise # pragma: no cover
- except: # pragma: no cover
- LOGGER.debug('DataWrongShapeError for %s with status %s',
- isbn, status)
- raise DataWrongShapeError("status: '%s' for isbn %s" % (status, isbn))
- # put the selected data in records
- try:
- recs = [ib['isbn'][0] for ib in data['list']]
- except: # pragma: no cover
- LOGGER.debug('NoDataForSelectorError for %s', isbn)
- raise NoDataForSelectorError(isbn)
- return recs
-
-
-def query(isbn):
- """Query the worldcat.org service for related ISBNs."""
- data = wquery(SERVICE_URL.format(isbn=isbn),
- user_agent=UA,
- parser=literal_eval)
- return _editions(isbn, data)
diff -Nru isbnlib-3.5.6/isbnlib/_wcat.py isbnlib-3.9.3/isbnlib/_wcat.py
--- isbnlib-3.5.6/isbnlib/_wcat.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/isbnlib/_wcat.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,67 +0,0 @@
-# -*- coding: utf-8 -*-
-"""Query the worldcat.org xID service for metadata."""
-
-import logging
-
-from .dev import stdmeta
-from .dev._bouth23 import u
-from .dev._exceptions import (DataWrongShapeError, ISBNNotConsistentError,
- NoDataForSelectorError, RecordMappingError)
-from .dev.webquery import query as wquery
-
-UA = 'isbnlib (gzip)'
-SERVICE_URL = 'http://xisbn.worldcat.org/webservices/xid/isbn/{isbn}?'\
- 'method=getMetadata&format=json&fl=title,author,year,publisher,lang'
-LOGGER = logging.getLogger(__name__)
-
-
-def _mapper(isbn, records):
- """Mapp: canonical <- records."""
- # canonical: ISBN-13, Title, Authors, Publisher, Year, Language
- try:
- canonical = {}
- canonical['ISBN-13'] = u(isbn)
- canonical['Title'] = records.get('title', u('')).replace(' :', ':')
- buf = records.get('author', u(''))
- canonical['Authors'] = [x.strip('. ') for x in buf.split(';')]
- canonical['Publisher'] = records.get('publisher', u(''))
- canonical['Year'] = records.get('year', u(''))
- canonical['Language'] = records.get('lang', u(''))
- except: # pragma: no cover
- LOGGER.debug("RecordMappingError for %s with data %s", isbn, records)
- raise RecordMappingError(isbn)
- # call stdmeta for extra cleanning and validation
- return stdmeta(canonical)
-
-
-def _records(isbn, data):
- """Classify (canonically) the parsed data."""
- # check status
- try:
- status = data['stat']
- if status != 'ok':
- raise
- except:
- LOGGER.debug('DataWrongShapeError for %s with status %s',
- isbn, status)
- raise DataWrongShapeError("status: '%s' for isbn %s" % (status, isbn))
- # put the selected data in records
- try:
- recs = data['list'][0]
- except: # pragma: no cover
- LOGGER.debug('NoDataForSelectorError for %s', isbn)
- raise NoDataForSelectorError(isbn)
- # consistency check (isbn request = isbn response)
- if recs:
- ids = recs.get('isbn', '')
- if isbn not in repr(ids): # pragma: no cover
- LOGGER.debug('ISBNNotConsistentError for %s (%s)', isbn, repr(ids))
- raise ISBNNotConsistentError("%s not in %s" % (isbn, repr(ids)))
- # map canonical <- records
- return _mapper(isbn, recs)
-
-
-def query(isbn):
- """Query the worldcat.org service for metadata."""
- data = wquery(SERVICE_URL.format(isbn=isbn), user_agent=UA)
- return _records(isbn, data)
diff -Nru isbnlib-3.5.6/LICENSE isbnlib-3.9.3/LICENSE
--- isbnlib-3.5.6/LICENSE 1970-01-01 00:00:00.000000000 +0000
+++ isbnlib-3.9.3/LICENSE 2018-10-05 11:18:35.000000000 +0000
@@ -0,0 +1,165 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+ 0. Additional Definitions.
+
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+ 1. Exception to Section 3 of the GNU GPL.
+
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+ 2. Conveying Modified Versions.
+
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
+
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
+
+ 3. Object Code Incorporating Material from Library Header Files.
+
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
+
+ 4. Combined Works.
+
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version
+ of the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is
+ necessary to install and execute a modified version of the
+ Combined Work produced by recombining or relinking the
+ Application with a modified version of the Linked Version. (If
+ you use option 4d0, the Installation Information must accompany
+ the Minimal Corresponding Source and Corresponding Application
+ Code. If you use option 4d1, you must provide the Installation
+ Information in the manner specified by section 6 of the GNU GPL
+ for conveying Corresponding Source.)
+
+ 5. Combined Libraries.
+
+ You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff -Nru isbnlib-3.5.6/LICENSE-LGPL.txt isbnlib-3.9.3/LICENSE-LGPL.txt
--- isbnlib-3.5.6/LICENSE-LGPL.txt 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/LICENSE-LGPL.txt 1970-01-01 00:00:00.000000000 +0000
@@ -1,165 +0,0 @@
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc.
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-
- This version of the GNU Lesser General Public License incorporates
-the terms and conditions of version 3 of the GNU General Public
-License, supplemented by the additional permissions listed below.
-
- 0. Additional Definitions.
-
- As used herein, "this License" refers to version 3 of the GNU Lesser
-General Public License, and the "GNU GPL" refers to version 3 of the GNU
-General Public License.
-
- "The Library" refers to a covered work governed by this License,
-other than an Application or a Combined Work as defined below.
-
- An "Application" is any work that makes use of an interface provided
-by the Library, but which is not otherwise based on the Library.
-Defining a subclass of a class defined by the Library is deemed a mode
-of using an interface provided by the Library.
-
- A "Combined Work" is a work produced by combining or linking an
-Application with the Library. The particular version of the Library
-with which the Combined Work was made is also called the "Linked
-Version".
-
- The "Minimal Corresponding Source" for a Combined Work means the
-Corresponding Source for the Combined Work, excluding any source code
-for portions of the Combined Work that, considered in isolation, are
-based on the Application, and not on the Linked Version.
-
- The "Corresponding Application Code" for a Combined Work means the
-object code and/or source code for the Application, including any data
-and utility programs needed for reproducing the Combined Work from the
-Application, but excluding the System Libraries of the Combined Work.
-
- 1. Exception to Section 3 of the GNU GPL.
-
- You may convey a covered work under sections 3 and 4 of this License
-without being bound by section 3 of the GNU GPL.
-
- 2. Conveying Modified Versions.
-
- If you modify a copy of the Library, and, in your modifications, a
-facility refers to a function or data to be supplied by an Application
-that uses the facility (other than as an argument passed when the
-facility is invoked), then you may convey a copy of the modified
-version:
-
- a) under this License, provided that you make a good faith effort to
- ensure that, in the event an Application does not supply the
- function or data, the facility still operates, and performs
- whatever part of its purpose remains meaningful, or
-
- b) under the GNU GPL, with none of the additional permissions of
- this License applicable to that copy.
-
- 3. Object Code Incorporating Material from Library Header Files.
-
- The object code form of an Application may incorporate material from
-a header file that is part of the Library. You may convey such object
-code under terms of your choice, provided that, if the incorporated
-material is not limited to numerical parameters, data structure
-layouts and accessors, or small macros, inline functions and templates
-(ten or fewer lines in length), you do both of the following:
-
- a) Give prominent notice with each copy of the object code that the
- Library is used in it and that the Library and its use are
- covered by this License.
-
- b) Accompany the object code with a copy of the GNU GPL and this license
- document.
-
- 4. Combined Works.
-
- You may convey a Combined Work under terms of your choice that,
-taken together, effectively do not restrict modification of the
-portions of the Library contained in the Combined Work and reverse
-engineering for debugging such modifications, if you also do each of
-the following:
-
- a) Give prominent notice with each copy of the Combined Work that
- the Library is used in it and that the Library and its use are
- covered by this License.
-
- b) Accompany the Combined Work with a copy of the GNU GPL and this license
- document.
-
- c) For a Combined Work that displays copyright notices during
- execution, include the copyright notice for the Library among
- these notices, as well as a reference directing the user to the
- copies of the GNU GPL and this license document.
-
- d) Do one of the following:
-
- 0) Convey the Minimal Corresponding Source under the terms of this
- License, and the Corresponding Application Code in a form
- suitable for, and under terms that permit, the user to
- recombine or relink the Application with a modified version of
- the Linked Version to produce a modified Combined Work, in the
- manner specified by section 6 of the GNU GPL for conveying
- Corresponding Source.
-
- 1) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (a) uses at run time
- a copy of the Library already present on the user's computer
- system, and (b) will operate properly with a modified version
- of the Library that is interface-compatible with the Linked
- Version.
-
- e) Provide Installation Information, but only if you would otherwise
- be required to provide such information under section 6 of the
- GNU GPL, and only to the extent that such information is
- necessary to install and execute a modified version of the
- Combined Work produced by recombining or relinking the
- Application with a modified version of the Linked Version. (If
- you use option 4d0, the Installation Information must accompany
- the Minimal Corresponding Source and Corresponding Application
- Code. If you use option 4d1, you must provide the Installation
- Information in the manner specified by section 6 of the GNU GPL
- for conveying Corresponding Source.)
-
- 5. Combined Libraries.
-
- You may place library facilities that are a work based on the
-Library side by side in a single library together with other library
-facilities that are not Applications and are not covered by this
-License, and convey such a combined library under terms of your
-choice, if you do both of the following:
-
- a) Accompany the combined library with a copy of the same work based
- on the Library, uncombined with any other library facilities,
- conveyed under the terms of this License.
-
- b) Give prominent notice with the combined library that part of it
- is a work based on the Library, and explaining where to find the
- accompanying uncombined form of the same work.
-
- 6. Revised Versions of the GNU Lesser General Public License.
-
- The Free Software Foundation may publish revised and/or new versions
-of the GNU Lesser General Public License from time to time. Such new
-versions will be similar in spirit to the present version, but may
-differ in detail to address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
-Library as you received it specifies that a certain numbered version
-of the GNU Lesser General Public License "or any later version"
-applies to it, you have the option of following the terms and
-conditions either of that published version or of any later version
-published by the Free Software Foundation. If the Library as you
-received it does not specify a version number of the GNU Lesser
-General Public License, you may choose any version of the GNU Lesser
-General Public License ever published by the Free Software Foundation.
-
- If the Library as you received it specifies that a proxy can decide
-whether future versions of the GNU Lesser General Public License shall
-apply, that proxy's public statement of acceptance of any version is
-permanent authorization for you to choose that version for the
-Library.
diff -Nru isbnlib-3.5.6/MANIFEST.in isbnlib-3.9.3/MANIFEST.in
--- isbnlib-3.5.6/MANIFEST.in 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/MANIFEST.in 2018-10-05 11:18:35.000000000 +0000
@@ -1,2 +1,3 @@
include *.txt
include *.rst
+include *.coveragerc
diff -Nru isbnlib-3.5.6/.mention-bot isbnlib-3.9.3/.mention-bot
--- isbnlib-3.5.6/.mention-bot 1970-01-01 00:00:00.000000000 +0000
+++ isbnlib-3.9.3/.mention-bot 2018-10-05 11:18:35.000000000 +0000
@@ -0,0 +1,3 @@
+{
+ "maxReviewers": 1
+}
diff -Nru isbnlib-3.5.6/.noserc isbnlib-3.9.3/.noserc
--- isbnlib-3.5.6/.noserc 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/.noserc 2018-10-05 11:18:35.000000000 +0000
@@ -1,2 +1,6 @@
[nosetests]
verbosity=1
+with-coverage=1
+cover-package=isbnlib
+cover-branches=1
+cover-min-percentage=99
diff -Nru isbnlib-3.5.6/.pep257 isbnlib-3.9.3/.pep257
--- isbnlib-3.5.6/.pep257 1970-01-01 00:00:00.000000000 +0000
+++ isbnlib-3.9.3/.pep257 2018-10-05 11:18:35.000000000 +0000
@@ -0,0 +1,2 @@
+[pep257]
+ignore=D203
Binary files /tmp/tmpu7yK9M/RpOPkkJAZP/isbnlib-3.5.6/PLUGIN.zip and /tmp/tmpu7yK9M/uGP3_Ilz_V/isbnlib-3.9.3/PLUGIN.zip differ
diff -Nru isbnlib-3.5.6/.pylintrc isbnlib-3.9.3/.pylintrc
--- isbnlib-3.5.6/.pylintrc 1970-01-01 00:00:00.000000000 +0000
+++ isbnlib-3.9.3/.pylintrc 2018-10-05 11:18:35.000000000 +0000
@@ -0,0 +1,379 @@
+[MASTER]
+
+# Specify a configuration file.
+#rcfile=
+
+# Python code to execute, usually for sys.path manipulation such as
+# pygtk.require().
+#init-hook=
+
+# Add files or directories to the blacklist. They should be base names, not
+# paths.
+ignore=CVS,_data,test
+
+# Pickle collected data for later comparisons.
+persistent=yes
+
+# List of plugins (as comma separated values of python modules names) to load,
+# usually to register additional checkers.
+load-plugins=
+
+# Use multiple processes to speed up Pylint.
+jobs=1
+
+# Allow loading of arbitrary C extensions. Extensions are imported into the
+# active Python interpreter and may run arbitrary code.
+unsafe-load-any-extension=no
+
+# A comma-separated list of package or module names from where C extensions may
+# be loaded. Extensions are loading into the active Python interpreter and may
+# run arbitrary code
+extension-pkg-whitelist=
+
+# Allow optimization of some AST trees. This will activate a peephole AST
+# optimizer, which will apply various small optimizations. For instance, it can
+# be used to obtain the result of joining multiple strings with the addition
+# operator. Joining a lot of strings can lead to a maximum recursion error in
+# Pylint and this flag can prevent that. It has one side effect, the resulting
+# AST will be different than the one from reality.
+optimize-ast=no
+
+
+[MESSAGES CONTROL]
+
+# Only show warnings with the listed confidence levels. Leave empty to show
+# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
+confidence=
+
+# Enable the message, report, category or checker with the given id(s). You can
+# either give multiple identifier separated by comma (,) or put this option
+# multiple time (only on the command line, not in the configuration file where
+# it should appear only once). See also the "--disable" option for examples.
+#enable=
+
+# Disable the message, report, category or checker with the given id(s). You
+# can either give multiple identifiers separated by comma (,) or put this
+# option multiple times (only on the command line, not in the configuration
+# file where it should appear only once).You can also use "--disable=all" to
+# disable everything first and then reenable specific checks. For example, if
+# you want to run only the similarities checker, you can use "--disable=all
+# --enable=similarities". If you want to run only the classes checker, but have
+# no Warning level messages displayed, use"--disable=all --enable=classes
+# --disable=W"
+disable=cmp-method,round-builtin,suppressed-message,old-division,hex-method,coerce-builtin,import-star-module-level,long-builtin,cmp-builtin,backtick,setslice-method,raw_input-builtin,unichr-builtin,no-absolute-import,standarderror-builtin,file-builtin,next-method-called,getslice-method,reduce-builtin,indexing-exception,xrange-builtin,buffer-builtin,dict-view-method,reload-builtin,coerce-method,print-statement,basestring-builtin,nonzero-method,input-builtin,range-builtin-not-iterating,useless-suppression,old-ne-operator,long-suffix,parameter-unpacking,raising-string,unpacking-in-except,map-builtin-not-iterating,apply-builtin,unicode-builtin,delslice-method,filter-builtin-not-iterating,zip-builtin-not-iterating,intern-builtin,using-cmp-argument,metaclass-assignment,oct-method,old-octal-literal,dict-iter-method,execfile-builtin,old-raise-syntax,global-statement,file-ignored,invalid-name
+
+
+[REPORTS]
+
+# Set the output format. Available formats are text, parseable, colorized, msvs
+# (visual studio) and html. You can also give a reporter class, eg
+# mypackage.mymodule.MyReporterClass.
+output-format=text
+
+# Put messages in a separate file for each module / package specified on the
+# command line instead of printing them on stdout. Reports (if any) will be
+# written in a file name "pylint_global.[txt|html]".
+files-output=no
+
+# Tells whether to display a full report or only the messages
+reports=yes
+
+# Python expression which should return a note less than 10 (10 is the highest
+# note). You have access to the variables errors warning, statement which
+# respectively contain the number of errors / warnings messages and the total
+# number of statements analyzed. This is used by the global evaluation report
+# (RP0004).
+evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
+
+# Template used to display messages. This is a python new-style format string
+# used to format the message information. See doc for all details
+#msg-template=
+
+
+[MISCELLANEOUS]
+
+# List of note tags to take in consideration, separated by a comma.
+notes=FIXME,XXX,TODO
+
+
+[VARIABLES]
+
+# Tells whether we should check for unused import in __init__ files.
+init-import=no
+
+# A regular expression matching the name of dummy variables (i.e. expectedly
+# not used).
+dummy-variables-rgx=_$|dummy
+
+# List of additional names supposed to be defined in builtins. Remember that
+# you should avoid to define new builtins when possible.
+additional-builtins=
+
+# List of strings which can identify a callback function by name. A callback
+# name must start or end with one of those strings.
+callbacks=cb_,_cb
+
+
+[LOGGING]
+
+# Logging modules to check that the string format arguments are in logging
+# function parameter format
+logging-modules=logging
+
+
+[SIMILARITIES]
+
+# Minimum lines number of a similarity.
+min-similarity-lines=4
+
+# Ignore comments when computing similarities.
+ignore-comments=yes
+
+# Ignore docstrings when computing similarities.
+ignore-docstrings=yes
+
+# Ignore imports when computing similarities.
+ignore-imports=no
+
+
+[SPELLING]
+
+# Spelling dictionary name. Available dictionaries: none. To make it working
+# install python-enchant package.
+spelling-dict=
+
+# List of comma separated words that should not be checked.
+spelling-ignore-words=
+
+# A path to a file that contains private dictionary; one word per line.
+spelling-private-dict-file=
+
+# Tells whether to store unknown words to indicated private dictionary in
+# --spelling-private-dict-file option instead of raising a message.
+spelling-store-unknown-words=no
+
+
+[BASIC]
+
+# List of builtins function names that should not be used, separated by a comma
+bad-functions=map,filter
+
+# Good variable names which should always be accepted, separated by a comma
+good-names=i,j,k,ex,Run,_
+
+# Bad variable names which should always be refused, separated by a comma
+bad-names=foo,bar,baz,toto,tutu,tata
+
+# Colon-delimited sets of names that determine each other's naming style when
+# the name regexes allow several styles.
+name-group=
+
+# Include a hint for the correct naming format with invalid-name
+include-naming-hint=no
+
+# Regular expression matching correct argument names
+argument-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Naming hint for argument names
+argument-name-hint=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression matching correct function names
+function-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Naming hint for function names
+function-name-hint=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression matching correct method names
+method-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Naming hint for method names
+method-name-hint=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression matching correct attribute names
+attr-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Naming hint for attribute names
+attr-name-hint=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression matching correct class names
+class-rgx=[A-Z_][a-zA-Z0-9]+$
+
+# Naming hint for class names
+class-name-hint=[A-Z_][a-zA-Z0-9]+$
+
+# Regular expression matching correct inline iteration names
+inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
+
+# Naming hint for inline iteration names
+inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$
+
+# Regular expression matching correct variable names
+variable-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Naming hint for variable names
+variable-name-hint=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression matching correct class attribute names
+class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
+
+# Naming hint for class attribute names
+class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
+
+# Regular expression matching correct constant names
+const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
+
+# Naming hint for constant names
+const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$
+
+# Regular expression matching correct module names
+module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
+
+# Naming hint for module names
+module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
+
+# Regular expression which should only match function or class names that do
+# not require a docstring.
+no-docstring-rgx=^_
+
+# Minimum line length for functions/classes that require docstrings, shorter
+# ones are exempt.
+docstring-min-length=-1
+
+
+[ELIF]
+
+# Maximum number of nested blocks for function / method body
+max-nested-blocks=5
+
+
+[FORMAT]
+
+# Maximum number of characters on a single line.
+max-line-length=100
+
+# Regexp for a line that is allowed to be longer than the limit.
+ignore-long-lines=^\s*(# )??$
+
+# Allow the body of an if to be on the same line as the test if there is no
+# else.
+single-line-if-stmt=no
+
+# List of optional constructs for which whitespace checking is disabled. `dict-
+# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.
+# `trailing-comma` allows a space between comma and closing bracket: (a, ).
+# `empty-line` allows space-only lines.
+no-space-check=trailing-comma,dict-separator
+
+# Maximum number of lines in a module
+max-module-lines=1000
+
+# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
+# tab).
+indent-string=' '
+
+# Number of spaces of indent required inside a hanging or continued line.
+indent-after-paren=4
+
+# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
+expected-line-ending-format=
+
+
+[TYPECHECK]
+
+# Tells whether missing members accessed in mixin class should be ignored. A
+# mixin class is detected if its name ends with "mixin" (case insensitive).
+ignore-mixin-members=yes
+
+# List of module names for which member attributes should not be checked
+# (useful for modules/projects where namespaces are manipulated during runtime
+# and thus existing member attributes cannot be deduced by static analysis. It
+# supports qualified module names, as well as Unix pattern matching.
+ignored-modules=
+
+# List of classes names for which member attributes should not be checked
+# (useful for classes with attributes dynamically set). This supports can work
+# with qualified names.
+ignored-classes=
+
+# List of members which are set dynamically and missed by pylint inference
+# system, and so shouldn't trigger E1101 when accessed. Python regular
+# expressions are accepted.
+generated-members=
+
+
+[DESIGN]
+
+# Maximum number of arguments for function / method
+max-args=5
+
+# Argument names that match this expression will be ignored. Default to name
+# with leading underscore
+ignored-argument-names=_.*
+
+# Maximum number of locals for function / method body
+max-locals=15
+
+# Maximum number of return / yield for function / method body
+max-returns=6
+
+# Maximum number of branch for function / method body
+max-branches=12
+
+# Maximum number of statements in function / method body
+max-statements=50
+
+# Maximum number of parents for a class (see R0901).
+max-parents=7
+
+# Maximum number of attributes for a class (see R0902).
+max-attributes=7
+
+# Minimum number of public methods for a class (see R0903).
+min-public-methods=2
+
+# Maximum number of public methods for a class (see R0904).
+max-public-methods=20
+
+# Maximum number of boolean expressions in a if statement
+max-bool-expr=5
+
+
+[CLASSES]
+
+# List of method names used to declare (i.e. assign) instance attributes.
+defining-attr-methods=__init__,__new__,setUp
+
+# List of valid names for the first argument in a class method.
+valid-classmethod-first-arg=cls
+
+# List of valid names for the first argument in a metaclass class method.
+valid-metaclass-classmethod-first-arg=mcs
+
+# List of member names, which should be excluded from the protected access
+# warning.
+exclude-protected=_asdict,_fields,_replace,_source,_make
+
+
+[IMPORTS]
+
+# Deprecated modules which should not be used, separated by a comma
+deprecated-modules=optparse
+
+# Create a graph of every (i.e. internal and external) dependencies in the
+# given file (report RP0402 must not be disabled)
+import-graph=
+
+# Create a graph of external dependencies in the given file (report RP0402 must
+# not be disabled)
+ext-import-graph=
+
+# Create a graph of internal dependencies in the given file (report RP0402 must
+# not be disabled)
+int-import-graph=
+
+
+[EXCEPTIONS]
+
+# Exceptions that will emit a warning when being caught. Defaults to
+# "Exception"
+overgeneral-exceptions=Exception
diff -Nru isbnlib-3.5.6/README.rst isbnlib-3.9.3/README.rst
--- isbnlib-3.5.6/README.rst 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/README.rst 2018-10-05 11:18:35.000000000 +0000
@@ -1,25 +1,32 @@
-.. image:: https://sourcegraph.com/api/repos/github.com/xlcnd/isbnlib/.badges/status.svg
+.. image:: https://img.shields.io/badge/Sourcegraph-Status-blue.svg
:target: https://sourcegraph.com/github.com/xlcnd/isbnlib
:alt: Graph
.. image:: https://readthedocs.org/projects/isbnlib/badge/?version=latest
- :target: http://isbnlib.readthedocs.org/en/latest/
+ :target: https://isbnlib.readthedocs.org/en/latest/
:alt: Documentation Status
-.. image:: https://coveralls.io/repos/xlcnd/isbnlib/badge.svg?branch=v3.5.6
- :target: https://coveralls.io/r/xlcnd/isbnlib?branch=v3.5.6
- :alt: Coverage
+.. image:: https://coveralls.io/repos/github/xlcnd/isbnlib/badge.svg?branch=v3.9.3
+ :target: https://coveralls.io/github/xlcnd/isbnlib?branch=v3.9.3
+ :alt: Coverage Status
-.. image:: https://travis-ci.org/xlcnd/isbnlib.svg?branch=v3.5.6
+.. image:: https://travis-ci.org/xlcnd/isbnlib.svg?branch=v3.9.3
:target: https://travis-ci.org/xlcnd/isbnlib
:alt: Built Status
-.. image:: https://ci.appveyor.com/api/projects/status/github/xlcnd/isbnlib?branch=v3.5.6&svg=true
+.. image:: https://ci.appveyor.com/api/projects/status/github/xlcnd/isbnlib?branch=v3.9.3&svg=true
:target: https://ci.appveyor.com/project/xlcnd/isbnlib
:alt: Windows Built Status
+Warning
+=======
+
+ The service xISBN was decommissioned (see issue 51_)!
+
+
+
Info
====
@@ -30,23 +37,23 @@
This short version, is suitable to be include as a dependency in other projects.
Has a straightforward setup and a very easy programmatic api.
+Runs on py27, py34, py35, py36 and py37.
Typical usage (as library):
.. code-block:: python
- #!/usr/bin/env python
import isbnlib
...
-Note
+ISBN
----
The official form of an ISBN is something like ``ISBN 979-10-90636-07-1``. However for most
applications only the numbers are important, you can always 'masked' them if you need (see below).
- This library works mainly with 'striped' ISBNs (only numbers and X) like '0826497527'. You can
+ This library works mainly with 'striped' ISBNs (only digits and X) like '0826497527'. You can
strip an ISBN-like string by using ``canonical(isbnlike)``. You can
'mask' the ISBN by using ``mask(isbn)``. So in the examples below, when you see 'isbn'
in the argument, it is a 'striped' ISBN, when the argument is an 'isbnlike' it is a string
@@ -61,8 +68,8 @@
(because '9786610326266' follows the rules of an ISBN). But the situation is even murkier,
try ``meta('9786610326266')`` and you will see that this ISBN was already used!
- If possible, work with ISBNs in the isbn-13 format (since 2007, only are issued ISBNs in the isbn-13
- format). You can always convert isbn-10 to isbn-13, but **not** the reverse.
+ If possible, work with ISBNs in the isbn-13 format (since 2007, only are issued ISBNs
+ in the isbn-13 format). You can always convert isbn-10 to isbn-13, but **not** the reverse.
Read more about ISBN at isbn-international.org_ or wikipedia_.
@@ -71,84 +78,82 @@
--------------
``is_isbn10(isbn10like)``
- Validates as ISBN-10.
+ Validates as ISBN-10.
``is_isbn13(isbn13like)``
- Validates as ISBN-13.
+ Validates as ISBN-13.
``to_isbn10(isbn13)``
- Transforms isbn-13 to isbn-10.
+ Transforms isbn-13 to isbn-10.
``to_isbn13(isbn10)``
- Transforms isbn-10 to isbn-13.
+ Transforms isbn-10 to isbn-13.
``canonical(isbnlike)``
- Keeps only numbers and X. You will get strings like `9780321534965` and `954430603X`.
+ Keeps only digits and X. You will get strings like `9780321534965` and `954430603X`.
``clean(isbnlike)``
- Cleans ISBN (only legal characters).
+ Cleans ISBN (only legal characters).
``notisbn(isbnlike, level='strict')``
- Check with the goal to invalidate isbn-like.
+ Check with the goal to invalidate isbn-like.
``get_isbnlike(text, level='normal')``
- Extracts all substrings that seem like ISBNs (very useful for scraping).
+ Extracts all substrings that seem like ISBNs (very useful for scraping).
``get_canonical_isbn(isbnlike, output='bouth')``
- Extracts ISBNs and transform them to the canonical form.
+ Extracts ISBNs and transform them to the canonical form.
``EAN13(isbnlike)``
- Transforms an `isbnlike` string into an EAN13 number (validated canonical ISBN-13).
+ Transforms an `isbnlike` string into an EAN13 number (validated canonical ISBN-13).
``info(isbn)``
- Gets the language or country assigned to this ISBN.
+ Gets the language or country assigned to this ISBN.
``mask(isbn, separator='-')``
- `Mask` (hyphenate) a canonical ISBN.
+ `Mask` (hyphenate) a canonical ISBN.
``meta(isbn, service='default', cache='default')``
Gives you the main metadata associated with the ISBN. As `service` parameter you can use:
- ``'wcat'`` uses **worldcat.org**
- (**no key is needed**), ``'goob'`` uses the **Google Books service** (**no key is needed**),
- ``'isbndb'`` uses the **isbndb.com** service (**an api key is needed**),
- ``'openl'`` uses the **OpenLibrary.org** api (**no key is needed**), ``merge`` uses
- a merged record of ``wcat`` and ``goob`` records (**no key is needed**) and
- **is the default option**.
- You can get an API key for the *isbndb.com service* here_. You can enter API keys
- with ``config.add_apikey(service, apikey)``.
- The output can be formatted as ``bibtex``, ``msword``, ``endnote``, ``refworks``,
+ ``'goob'`` uses the **Google Books service** (**no key is needed**) and
+ **is the default option**,
+ ``'openl'`` uses the **OpenLibrary.org** api (**no key is needed**).
+ You can enter API keys
+ with ``config.add_apikey(service, apikey)`` (see example below).
+ The output can be formatted as ``bibtex``, ``csl`` (CSL-JSON), ``msword``, ``endnote``, ``refworks``,
``opf`` or ``json`` (BibJSON) bibliographic formats with ``isbnlib.registry.bibformatters``.
``cache`` only allows two values: 'default' or None. You can change the kind of cache by using
``isbnlib.registry.set_cache`` (see below).
+ Now, you can extend the functionality of this function by adding pluggins, more metadata
+ providers or new bibliographic formatters (check_ for available pluggins).
-``editions(isbn, service='wcat')``
+``editions(isbn, service='merge')``
Returns the list of ISBNs of editions related with this ISBN. By default
- uses 'wcat', but other providers are available: 'thingl' (uses the
- service ThingISBN from **LibraryThing**), 'merge' (merges 'wcat' with 'thingl')
- and 'any' (first tries 'wcat', if no data, tries 'thingl').
+ uses 'merge' (merges 'openl' and 'thingl'), but other providers are available:
+ 'openl' users **Open Library**, 'thingl' (uses the service ThingISBN from **LibraryThing**)
+ and 'any' (first tries 'openl', if no data, then 'thingl').
``isbn_from_words(words)``
- Returns the most probable ISBN from a list of words (for your geographic area).
+ Returns the most probable ISBN from a list of words (for your geographic area).
``goom(words)``
- Returns a list of references from **Google Books multiple references**.
+ Returns a list of references from **Google Books multiple references**.
``doi(isbn)``
- Returns a DOI's ISBN-A from a ISBN-13.
+ Returns a DOI's ISBN-A from a ISBN-13.
``doi2tex(DOI)``
- Returns metadata formated as BibTeX for a given DOI.
+ Returns metadata formated as BibTeX for a given DOI.
``ren(filename)``
- Renames a file using metadata from an ISBN in his filename.
+ Renames a file using metadata from an ISBN in his filename.
``desc(isbn)``
- **BETA** Returns a small description of the book.
+ Returns a small description of the book.
*Almost all data available are for US books!*
``cover(isbn)``
- **BETA** Downloads an image of the cover of the book or, with
- `cover(isbn, mode='url')`, returns an url of the image.
+ Returns a dictionary with the url for cover.
*Almost all data available are for US books!*
@@ -173,6 +178,11 @@
$ easy_install isbnlib
+If you use linux systems, you can install using your distribution package
+manager (all major distributions have packages ``python-isbnlib``
+and ``python3-isbnlib``), however (usually) are **very old and don't work well anymore**!
+
+
For Devs
========
@@ -213,17 +223,13 @@
* ``vias`` exposes several functions to put calls to services, just by passing the name and
a pointer to the service's ``query`` function.
- ``vias.parallel`` allows to put threaded calls.
+ ``vias.parallel`` allows to put threaded calls.
You can use ``vias.serial`` to make serial calls and
``vias.multi`` to use several cores. The default is ``vias.serial``.
-* ``bouth23`` (**DEPRECATED**) a small module to make it possible the code to run
- in **bouth** python 2 and python 3. **It will disappear in the next major version!**.
- See python-future.org_ for a built-in alternative to ``bouth23``.
-
The exceptions raised by these methods can all be catched using ``ISBNLibDevException``.
You **should't raise** this exception in your code, only raise the specific exceptions
-exposed in ``isbnlib.dev`` whose name end in Error.
+exposed in ``isbnlib.dev`` whose name ends in Error.
In ``isbnlib.dev.helpers`` you can find several methods, that we found very useful, some of then
@@ -239,36 +245,57 @@
Finally, from ``isbnlib.config`` you can read and set configuration options:
-change timeouts with ``setsocketstimeout`` and ``setthreadstimeout``,
+change timeouts with ``seturlopentimeout`` and ``setthreadstimeout``,
access api keys with ``apikeys`` and add new one with ``add_apikey`` and
access and set generic and user-defined options with ``options`` and ``set_option``.
+Let us concretize the last point with a small example.
+
+Suppose you want a small script to get metadata using ``Open Library`` formated in BibTeX.
+
+A minimal script would be:
+
+
+.. code-block:: python
+
+ from isbnlib import meta
+ from isbnlib.registry import bibformatters
+
+ SERVICE = 'openl'
+
+ # now you can use the service
+ isbn = '9780446310789'
+ bibtex = bibformatters['bibtex']
+ print(bibtex(meta(isbn, SERVICE)))
+
+
+
+Plugins
+-------
+
+You can extend the functionality of the library by adding plugins (for now, just
+new metadata providers or new bibliographic formatters).
+
+For available plugins check_ here.
+
+After install, your plugin will blend transparently in ``isbnlib`` (you will have more options in ``meta`` and ``bibformatters``).
+
+If you want to develop a plugin, start with this template_ and follow the instructions there. For inspiration take a look
+at goob_.
+
+
+Remember that plugins **must** support python 2.7 and python 3.4+ (see python-future.org_).
-Merge Metadata
---------------
-The original quality of metadata, at the several services, is not very good!
-If you need high quality metadata in your app, the only solution is to use
-*polling & merge* of several providers **and** a **lot** of cleaning and standardization
-for fields like ``Authors`` and ``Publisher``.
-
-A *merge* provider is now the default in ``meta``.
-It gives priority to ``wcat`` but overwrites the ``Authors`` field with the value from ``goob``.
-Uses the ``merge`` method of ``Metadata`` and *serial* calls to services
-by default (faster for one-call to services through fast internet connections).
-You can change that by using ``vias``'s other methods
-(e.g. ``isbnlib.config.set_option('VIAS_MERGE', 'multi')``.
Caveats
-------
-1. These classes are optimized for one-call to services and not for batch calls. However,
- is very easy to produce an high volume processing system using these classes
- (use ``vias.multi``) and Redis.
+1. These classes are optimized for one-call to services and not for batch calls.
2. If you inspect the library, you will see that there are a lot of private modules
(their name starts with '_'). These modules **should not** be accessed directly since,
@@ -276,14 +303,37 @@
+Projects using *isbnlib*
+------------------------
+
+**isbntools** https://github.com/xlcnd/isbntools
+
+**Spreads** https://github.com/DIYBookScanner/spreads
+
+**BiblioManager** https://github.com/Phyks/BMC/
+
+**libBMC** https://github.com/Phyks/libbmc/
+
+**Alessandria** https://gitlab.com/openlabmatera/alessandria
+
+**Comic Collector** https://github.com/wengole/comiccollector
+
+**Abelujo** http://www.abelujo.cc/
+
+**BibLib** https://pypi.python.org/pypi/biblib
+
+
+
+
Help
-____
+----
If you need help, please take a look at github_ or post a question on
stackoverflow_ (with tag **isbnlib**)
+
----------------------------------------------------------------------------------------------
.. class:: center
@@ -297,8 +347,6 @@
.. _range: https://www.isbn-international.org/range_file_generation
-.. _here: http://isbndb.com/api/v2/docs
-
.. _isbntools: https://pypi.python.org/pypi/isbntools
.. _sourcegraph: http://bit.ly/ISBNLib_srcgraph
@@ -316,3 +364,19 @@
.. _wikipedia: http://en.wikipedia.org/wiki/International_Standard_Book_Number
.. _python-future.org: http://python-future.org/compatible_idioms.html
+
+.. _issue: https://github.com/xlcnd/isbnlib/issues/28
+
+.. _check: https://pypi.python.org/pypi?%3Aaction=search&term=isbnlib_&submit=search
+
+.. _template: https://github.com/xlcnd/isbnlib/blob/dev/PLUGIN.zip
+
+
+.. _goob: https://github.com/xlcnd/isbnlib/blob/dev/isbnlib/_goob.py
+
+
+.. _search: https://pypi.python.org/pypi?%3Aaction=search&term=isbnlib&submit=search
+
+.. _51: https://github.com/xlcnd/isbnlib/issues/51
+
+
diff -Nru isbnlib-3.5.6/requirements-appveyor.txt isbnlib-3.9.3/requirements-appveyor.txt
--- isbnlib-3.5.6/requirements-appveyor.txt 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/requirements-appveyor.txt 2018-10-05 11:18:35.000000000 +0000
@@ -1,6 +1,6 @@
-coverage==3.7.1
-flake8==2.1.0
-nose==1.3.4
-tox==1.7.1
-setuptools==12.0.4
-wheel==0.23.0
+coverage==4.4.2
+flake8==3.5.0
+nose==1.3.7
+setuptools==38.4.0
+tox==2.9.1
+wheel==0.30.0
diff -Nru isbnlib-3.5.6/requirements-dev.txt isbnlib-3.9.3/requirements-dev.txt
--- isbnlib-3.5.6/requirements-dev.txt 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/requirements-dev.txt 2018-10-05 11:18:35.000000000 +0000
@@ -1,13 +1,13 @@
-coverage==3.7.1
-flake8==2.1.0
-mccabe==0.2.1
-mock==1.0.1
-nose==1.3.4
-pep8==1.5.7
-pep8-naming==0.2.2
-pep257==0.3.2
-pyflakes==0.8.1
-pylint==1.2.1
-tox==1.7.1
-virtualenv==12.0.5
-wheel==0.23.0
+coverage==4.4.2
+flake8==3.5.0
+flake8-bugbear==18.2.0
+flake8-commas==1.0.0
+flake8-docstrings==1.3.0
+flake8-import-order==0.17.1
+isort==4.3.4
+nose==1.3.7
+pep8-naming==0.5.0
+setuptools==38.4.0
+tox==2.9.1
+wheel==0.30.0
+yapf==0.20.2
diff -Nru isbnlib-3.5.6/setup.cfg isbnlib-3.9.3/setup.cfg
--- isbnlib-3.5.6/setup.cfg 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/setup.cfg 2018-10-05 11:18:35.000000000 +0000
@@ -1,6 +1,29 @@
+[metadata]
+license_file = LICENSE
+
+
[bdist_wheel]
universal=1
+
[nosetests]
verbosity=1
+with-coverage=1
+cover-package=isbnlib
+cover-branches=1
+cover-min-percentage=90
+
+
+[pep257]
+ignore=D203
+
+
+[flake8]
+ignore=N806,E721,W503
+exclude=*/test/*,*/_data/*
+max-complexity=13
+
+[doc8]
+max-line-length=120
+verbose=1
diff -Nru isbnlib-3.5.6/setup.py isbnlib-3.9.3/setup.py
--- isbnlib-3.5.6/setup.py 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/setup.py 2018-10-05 11:18:35.000000000 +0000
@@ -1,7 +1,9 @@
# -*- coding: utf-8 -*-
+# flake8: noqa
+# isort:skip_file
-# isbnlib - tools for extracting, cleaning and transforming ISBNs
-# Copyright (C) 2014 Alexandre Lima Conde
+# isbnlib -- tools for extracting, cleaning and transforming ISBNs
+# Copyright (C) 2014-2018 Alexandre Lima Conde
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
@@ -27,7 +29,7 @@
author='xlcnd',
author_email='xlcnd@outlook.com',
url='https://github.com/xlcnd/isbnlib',
- download_url='https://github.com/xlcnd/isbnlib/archive/v3.5.6.zip',
+ download_url='https://github.com/xlcnd/isbnlib/archive/v3.9.3.zip',
packages=['isbnlib',
'isbnlib/dev',
'isbnlib/_data',
@@ -36,15 +38,16 @@
license='LGPL v3',
description='Extract, clean, transform, hyphenate and metadata for ISBNs (International Standard Book Number).',
long_description=open('README.rst').read(),
- keywords='ISBN, validate, transform, hyphenate, metadata, World Catalogue, Google Books, Open Library, isbndb.com, BibTeX, EndNote, RefWorks, MSWord, opf, BibJSON, ISBN-A, doi, EAN13',
+ keywords='ISBN metadata World_Catalogue Google_Books Open_Library BibTeX EndNote RefWorks MSWord opf BibJSON',
classifiers=[
'Programming Language :: Python',
'Programming Language :: Python :: 2',
- 'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
- 'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
+ 'Programming Language :: Python :: 3.5',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: 3.7',
'License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)',
'Operating System :: OS Independent',
'Development Status :: 5 - Production/Stable',
@@ -52,6 +55,6 @@
'Topic :: Text Processing :: General',
'Topic :: Software Development :: Libraries :: Python Modules',
],
- tests_require=['nose'],
+ tests_require=['nose', 'coverage'],
test_suite='nose.collector',
)
diff -Nru isbnlib-3.5.6/.style.yapf isbnlib-3.9.3/.style.yapf
--- isbnlib-3.5.6/.style.yapf 1970-01-01 00:00:00.000000000 +0000
+++ isbnlib-3.9.3/.style.yapf 2018-10-05 11:18:35.000000000 +0000
@@ -0,0 +1,2 @@
+[style]
+based_on_style = pep8
diff -Nru isbnlib-3.5.6/tox.ini isbnlib-3.9.3/tox.ini
--- isbnlib-3.5.6/tox.ini 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/tox.ini 2018-10-05 11:18:35.000000000 +0000
@@ -1,17 +1,24 @@
[flake8]
-ignore=N806,E721
+ignore=N806,I100,I101,I201,N802,C901,E722,E741
exclude=*/test/*,*/_data/*
max-complexity=13
+[pep257]
+ignore=D203
+
+[doc8]
+max-line-length=120
+verbose=1
+
[tox]
-envlist=py26,py27,py33,py34,checkers
+envlist=py27,py34,py35,py36,nightly,checkers
[testenv]
deps=
nose
coverage
commands=
- nosetests -v --with-coverage --cover-package=isbnlib
+ nosetests -v --with-coverage --cover-package=isbnlib --cover-min-percentage=90
[testenv:checkers]
basepython=python
diff -Nru isbnlib-3.5.6/.travis.yml isbnlib-3.9.3/.travis.yml
--- isbnlib-3.5.6/.travis.yml 2015-06-03 10:51:03.000000000 +0000
+++ isbnlib-3.9.3/.travis.yml 2018-10-05 11:18:35.000000000 +0000
@@ -1,41 +1,45 @@
sudo: false
language: python
-os:
-- linux
-- osx
branches:
only:
- - v3.5.6
- - none
+ - v3.9.3
matrix:
include:
+ - os: osx
+ language: generic
+ env: TOXENV=py37
- python: "2.7"
env: TOXENV=py27
+ - python: "3.6"
+ env: TOXENV=py36
+ - python: "3.5"
+ env: TOXENV=py35
- python: "3.4"
env: TOXENV=py34
- - python: "3.3"
- env: TOXENV=py33
- - python: "2.6"
- env: TOXENV=py26
- - python: "pypy"
- env: TOXENV=pypy
+ - python: "nightly"
+ env: TOXENV=nightly
- python: "2.7"
env: TOXENV=checkers
- python: "2.7"
env: DOC=sphinx
allow_failures:
- - env: TOXENV=pypy
+ - env: TOXENV=nightly
+ - env: TOXENV=py34
- env: TOXENV=checkers
install:
-- if [[ ! -z $TOXENV ]]; then pip install tox; fi
-- if [[ ! -z $TOXENV ]]; then pip install flake8; fi
-- if [[ ! -z $TOXENV ]]; then pip install pep8-naming; fi
-- if [[ $TOXENV == 'py27' ]]; then pip install coveralls; fi
+- if [[ $TRAVIS_OS_NAME == 'osx' ]]; then brew upgrade python && python --version; fi
+- if [[ $TRAVIS_OS_NAME == 'osx' ]]; then pip3 install tox; fi
+- if [[ $TRAVIS_OS_NAME == 'linux' ]]; then pip install tox; fi
+- if [[ $TOXENV == 'checkers' ]]; then pip install flake8; fi
+- if [[ $TOXENV == 'checkers' ]]; then pip install pep8-naming; fi
+- if [[ $TOXENV == 'py27' ]]; then pip install coveralls; fi
- if [[ $DOC == 'sphinx' ]]; then pip install sphinx; fi
+- if [[ $TRAVIS_PULL_REQUEST != 'false' ]]; then pip install yapf; fi
script:
+- if [[ $TRAVIS_PULL_REQUEST != 'false' ]] && [[ $TOXENV == 'checkers' ]]; then yapf -i isbnlib; fi
- if [[ ! -z $TOXENV ]]; then tox -e $TOXENV; fi
- if [[ $DOC == 'sphinx' ]]; then cd docs; sphinx-build -n -b html -d _build/.doctrees . _build/html; fi
after_success:
- if [[ $TOXENV == 'py27' ]]; then coveralls; fi
notifications:
- email: false
+ email: false