Merge branch 'gutenbergtools:master' into master

master
Eric Hellman 2021-05-11 10:57:00 -04:00
commit fbe927d12b
16 changed files with 1354 additions and 326 deletions

208
AdvSearchPage.py Normal file
View File

@ -0,0 +1,208 @@
#!/usr/bin/env python
# -*- mode: python; indent-tabs-mode: nil; -*- coding: utf-8 -*-
"""
AdvSearchPage.py
Copyright 2021 by Project Gutenberg
Distributable under the GNU General Public License Version 3 or newer.
Not really "advanced", it reproduces functionality of the old results.php search,
labelled as "Advanced Search", using SQLAlchemy ORM
Differences:
- instead of a link for a new search, a pre-filled advanced search form is shown contextually
- Following our Bibrecord pages, BC -> BCE in dates
- The language selector invokes some language-localization
- Authors are now all in a <ul>
- the first page of results is pageno=1, not 0
- cataloguer mode to list for missing subjects and loccs no longer supported
(no authentication in autocat3!)
"""
import cherrypy
import routes
from sqlalchemy import or_, and_, select
from genshi.filters import HTMLFormFiller
from libgutenberg.Models import (
Alias, Attribute, Author, Book, BookAuthor, Category, File, Lang, Locc, Subject)
import BaseSearcher
from errors import ErrorPage
from Page import Page
from Formatters import formatters
config = cherrypy.config
BROWSE_KEYS = {'lang': 'languages', 'locc': 'loccs', 'category': 'categories'}
PAGESIZE = 100
MAX_RESULTS = 1000
_langs = {}
def langname(langcode):
""" cache of Language names"""
if not _langs:
session = cherrypy.engine.pool.Session()
for lang in session.query(Lang).all():
_langs[lang.id] = lang.language
return _langs.get(langcode, langcode)
_cats = {}
def catname(catpk):
""" cache of category names"""
if not _cats:
session = cherrypy.engine.pool.Session()
for cat in session.query(Category).all():
_cats[cat.pk] = cat.category
return _cats.get(catpk, 'Not a valid Category')
class AdvSearcher(BaseSearcher.OpenSearch):
""" this object passes the context for the page renderer """
def __init__(self):
super().__init__()
self.items_per_page = PAGESIZE
def url(self, *args, **params):
params = BaseSearcher.OpenSearch.params(**params)
return super(AdvSearcher,self).url('results', *args, **params)
def finalize(self):
super().finalize()
self.lastpage = int(self.total_results / PAGESIZE) + 1
self.nextpage = self.pageno + 1 if self.pageno + 1 <= self.lastpage else 0
self.prevpage = self.pageno - 1 if self.pageno > 1 <= self.lastpage else 0
class AdvSearchPage(Page):
""" search term => list of items """
def __init__(self):
super().__init__()
self.host = cherrypy.config['host']
self.urlgen = routes.URLGenerator(cherrypy.routes_mapper, {'HTTP_HOST': self.host})
self.formatter = formatters['html']
def index (self, **kwargs):
def entries(results, offset):
""" results is a list of book ids, sorted by first Author,
the query lazily returns book objects
"""
query = session.query(Book).join(
Book.authors.and_(BookAuthor.heading == 1)).join(BookAuthor.author).filter(
Book.pk.in_(results)).order_by(Author.name).offset(offset).limit(PAGESIZE)
for book in query:
yield book
os = AdvSearcher()
params = cherrypy.request.params.copy()
try:
pageno = abs(int(params.pop("pageno", 1)))
except KeyError:
pageno = 1
os.pageno = pageno
for key in ["submit_search", "route_name", "controller", "action"]:
params.pop(key, None)
terms = [key for key in params if params[key]]
# Return a search result page.
# no terms provided
if len(terms) == 0:
os.total_results = 0
os.finalize()
return self.formatter.render('advresults', os)
# single term, redirect if browsable
if len(terms) == 1:
browse_key = BROWSE_KEYS.get(terms[0], None)
if browse_key:
raise cherrypy.HTTPRedirect(
"/browse/%s/%s" % (browse_key, params[terms[0]].lower()))
# multiple terms, create a query
session = cherrypy.engine.pool.Session()
query = session.query(Book.pk)
selections = []
resultpks = None
searchterms = []
for key in terms:
if key in ['author', 'title', 'subject']:
for word in params[key].split():
searchterms.append((key, word))
else:
searchterms.append((key, params[key]))
for key, val in searchterms:
if key == 'filetype':
pks = query.join(File).filter(File.fk_filetypes == val).all()
key = 'Filetype'
elif key == 'lang':
pks = query.join(Book.langs).filter(Lang.id == val).all()
val = langname(val)
key = 'Language'
elif key == 'locc':
pks = query.join(Book.loccs).filter(Locc.id == val).all()
val = val.upper()
key = 'LoC Class'
elif key == 'category':
try:
val = int(val)
except ValueError:
continue
pks = query.join(Book.categories).filter(Category.pk == val).all()
val = catname(val)
key = 'Category'
elif key == 'author':
word = "%{}%".format(val)
subq = select(Author.id).join(Author.aliases).filter(
Alias.alias.ilike(word))
pks = query.join(Book.authors).join(BookAuthor.author).filter(or_(
Author.name.ilike(word),
Author.id.in_(subq),
)).all()
key = 'Author'
elif key == 'title':
word = "%{}%".format(val)
pks = query.join(Book.attributes).filter(and_(
Attribute.fk_attriblist.in_([240, 245, 246, 505]),
Attribute.text.ilike(word),
)).all()
key = 'Title'
elif key == 'subject':
word = "%{}%".format(val)
pks = query.join(Book.subjects).filter(
Subject.subject.ilike(word),
).all()
key = 'Subject'
pks = {row[0] for row in pks}
resultpks = resultpks.intersection(pks) if resultpks is not None else pks
num_rows = len(pks)
selections.append((key, val, num_rows))
os.total_results = len(resultpks)
os.finalize()
offset = PAGESIZE * (pageno - 1)
os.start_index = offset + 1
if os.total_results > MAX_RESULTS:
os.entries = []
else:
os.entries = entries(resultpks, offset)
os.search_terms = selections
instance_filter = HTMLFormFiller(data=params)
rendered = self.formatter.render('advresults', os, instance_filter)
session.close()
return rendered

View File

@ -71,7 +71,7 @@ class BaseFormatter(object):
cherrypy.response.headers['Content-Type'] = self.CONTENT_TYPE
def render(self, page, os):
def render(self, page, os, instance_filter=None):
""" Render and send to browser. """
self.send_headers()
@ -82,6 +82,9 @@ class BaseFormatter(object):
stream = template.stream
for filter_ in template.filters:
stream = filter_(iter(stream), ctxt)
if instance_filter:
stream = instance_filter(stream)
# there's no easy way in genshi to pass collapse_lines to this filter
stream = WHITESPACE_FILTER(stream, collapse_lines=COLLAPSE_LINES)
@ -162,7 +165,6 @@ class BaseFormatter(object):
# file_.dropbox_filename = None
file_.gdrive_url = None
file_.msdrive_url = None
file_.honeypot_url = None
if file_.filetype == 'cover.medium':
dc.cover_image = file_

View File

@ -491,7 +491,6 @@ class OpenSearch(object):
lang = self.lang_to_default_locale.get(lang, 'en_US')
lang2 = self.lang[:2]
self.fb_lang = lang if lang in FB_LANGS else 'en_US'
self.paypal_lang = lang if lang in PAYPAL_LANGS else 'en_US'
self.flattr_lang = lang if lang in FLATTR_LANGS else 'en_US'
@ -553,7 +552,6 @@ class OpenSearch(object):
self.show_next_page_link = (self.end_index < self.total_results)
self.desktop_search = self.url('search', format = None)
self.json_search = self.url('suggest', format = None)
self.base_url = self.url(host = self.file_host, protocol='https')

View File

@ -68,8 +68,6 @@ tools.I18nTool.mo_dir: CherryPyApp.install_dir + '/i18n'
tools.I18nTool.domain: 'messages'
tools.sessions.on: True
tools.sessions.storage_class = sessions.RamSession
#tools.sessions.storage_type = "postgres"
tools.sessions.table_name = "cherrypy.sessions"
tools.sessions.timeout: 30
tools.sessions.path: '/'

View File

@ -37,6 +37,7 @@ import SuggestionsPage
from SearchPage import BookSearchPage, AuthorSearchPage, SubjectSearchPage, BookshelfSearchPage, \
AuthorPage, SubjectPage, BookshelfPage, AlsoDownloadedPage
from BibrecPage import BibrecPage
from AdvSearchPage import AdvSearchPage
import CoverPages
import QRCodePage
import diagnostics
@ -156,12 +157,6 @@ def main():
cherrypy.log("Continuing App Init", context='ENGINE', severity=logging.INFO)
# Used to bust the cache on js and css files. This should be the
# files' mtime, but the files are not stored on the app server.
# This is a `good enough´ replacement though.
t = str(int(time.time()))
cherrypy.config['css_mtime'] = t
cherrypy.config['js_mtime'] = t
cherrypy.config['all_hosts'] = (
cherrypy.config['host'], cherrypy.config['file_host'])
@ -231,6 +226,9 @@ def main():
d.connect('bookshelf_search', r'/ebooks/bookshelves/search{.format}/',
controller=BookshelfSearchPage())
d.connect('results', r'/ebooks/results{.format}/',
controller=AdvSearchPage())
# 'id' pages
d.connect('author', r'/ebooks/author/{id:\d+}{.format}',
@ -273,9 +271,6 @@ def main():
d.connect('stats', r'/stats/',
controller=Page.NullPage(), _static=True)
d.connect('honeypot_send', r'/ebooks/send/megaupload/{id:\d+}.{filetype}',
controller=Page.NullPage(), _static=True)
# /w/captcha/question/ so varnish will cache it
d.connect('captcha.question', r'/w/captcha/question/',
controller=Page.GoHomePage())

View File

@ -15,86 +15,93 @@ from __future__ import unicode_literals
import logging
import psycopg2
import sqlalchemy.pool as pool
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
import cherrypy
from cherrypy.process import plugins
DUMMY_SQL_URL = "postgresql://127.0.0.1:5432/gutenberg"
class ConnectionCreator ():
class ConnectionCreator():
""" Creates connections for the connection pool. """
def __init__ (self, params):
def __init__(self, params):
self.params = params
def __call__ (self):
cherrypy.log (
def __call__(self):
cherrypy.log(
"Connecting to database '%(database)s' on '%(host)s:%(port)d' as user '%(user)s'."
% self.params, context = 'POSTGRES', severity = logging.INFO)
conn = psycopg2.connect (**self.params)
conn.cursor ().execute ('SET statement_timeout = 5000')
% self.params, context='POSTGRES', severity=logging.INFO)
conn = psycopg2.connect(**self.params)
conn.cursor().execute('SET statement_timeout = 5000')
return conn
class ConnectionPool (plugins.SimplePlugin):
class ConnectionPool(plugins.SimplePlugin):
"""A WSPBus plugin that controls a SQLAlchemy engine/connection pool."""
def __init__ (self, bus, params = None):
plugins.SimplePlugin.__init__ (self, bus)
def __init__(self, bus, params=None):
plugins.SimplePlugin.__init__(self, bus)
self.params = params
self.name = 'sqlalchemy'
self.pool = None
def _start (self):
def _start(self):
""" Init the connection pool. """
pool_size = cherrypy.config.get ('sqlalchemy.pool_size', 5)
max_overflow = cherrypy.config.get ('sqlalchemy.max_overflow', 10)
timeout = cherrypy.config.get ('sqlalchemy.timeout', 30)
recycle = cherrypy.config.get ('sqlalchemy.recycle', 3600)
pool_size = cherrypy.config.get('sqlalchemy.pool_size', 5)
max_overflow = cherrypy.config.get('sqlalchemy.max_overflow', 10)
timeout = cherrypy.config.get('sqlalchemy.timeout', 30)
recycle = cherrypy.config.get('sqlalchemy.recycle', 3600)
self.bus.log ("... pool_size = %d, max_overflow = %d" % (pool_size, max_overflow))
return pool.QueuePool (ConnectionCreator (self.params),
pool_size = pool_size,
max_overflow = max_overflow,
timeout = timeout,
recycle = recycle)
self.bus.log("... pool_size = %d, max_overflow = %d" % (pool_size, max_overflow))
my_pool = pool.QueuePool(ConnectionCreator(self.params),
pool_size=pool_size,
max_overflow=max_overflow,
timeout=timeout,
recycle=recycle)
engine = create_engine(DUMMY_SQL_URL, echo=False, pool=my_pool)
Session = sessionmaker(bind=engine)
return engine, Session
def connect (self):
def connect(self):
""" Return a connection. """
return self.pool.connect ()
return self.pool.raw_connection()
def start (self):
def start(self):
""" Called on engine start. """
if self.pool is None:
self.bus.log ("Creating the SQL connection pool ...")
self.pool = self._start ()
self.bus.log("Creating the SQL connectors ...")
self.pool, self.Session = self._start()
else:
self.bus.log ("An SQL connection pool already exists.")
# start.priority = 80
self.bus.log("SQL connectors already exists.")
def stop (self):
def stop(self):
""" Called on engine stop. """
if self.pool is not None:
self.bus.log ("Disposing the SQL connection pool.")
self.pool.dispose ()
self.bus.log("Disposing the SQL connection pool.")
self.Session = None
self.pool.dispose()
self.pool = None
def graceful (self):
def graceful(self):
""" Called on engine restart. """
if self.pool is not None:
self.bus.log ("Restarting the SQL connection pool ...")
self.pool.dispose ()
self.pool = self._start ()
self.bus.log("Restarting the SQL connection pool ...")
self.pool.dispose()
self.pool, self.Session = self._start()
cherrypy.process.plugins.ConnectionPool = ConnectionPool

View File

@ -94,10 +94,6 @@ class XMLishFormatter (BaseFormatter.BaseFormatter):
file_.filename = file_.filename + '?' + urllib.parse.urlencode (
{ 'session_id': str (cherrypy.session.id) } )
for file_ in dc.files:
file_.honeypot_url = os.url (
'honeypot_send', id = dc.project_gutenberg_id, filetype = file_.filetype)
break
def format (self, page, os):

View File

@ -9,18 +9,18 @@ verify_ssl = true
"repoze.lru" = "*"
Babel = "*"
chardet = "*"
CherryPy = "*"
CherryPy = ">=18.6.0"
colorama = "*"
#command-not-found = "*"
Genshi = "*"
html5lib = "*"
isodate = "*"
#language-selector = "*"
libgutenberg = ">=0.6.7"
libgutenberg = "==0.7.0"
netaddr = "*"
oauth = "*"
oauthlib = "*"
Pillow = "*"
Pillow = ">=8.1.1"
#pycurl = "*"
#PyGObject = "*"
pyparsing = "*"

461
Pipfile.lock generated
View File

@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "fd062a1525a82ac365a00e54473fc0fa1ff0afe4100fd20f129297e07e24d713"
"sha256": "a72f9398afe4bb83eac7533643e2091d74428231a3f701f2b32999edb4b67e3a"
},
"pipfile-spec": 6,
"requires": {
@ -18,33 +18,33 @@
"default": {
"babel": {
"hashes": [
"sha256:1aac2ae2d0d8ea368fa90906567f5c08463d98ade155c0c4bfedd6a0f7160e38",
"sha256:d670ea0b10f8b723672d3a6abeb87b565b244da220d76b4dba1b66269ec152d4"
"sha256:9d35c22fcc79893c3ecc85ac4a56cde1ecf3f19c540bba0922308a6c06ca6fa5",
"sha256:da031ab54472314f210b0adcff1588ee5d1d1d0ba4dbd07b94dba82bde791e05"
],
"index": "pypi",
"version": "==2.8.0"
"version": "==2.9.0"
},
"certifi": {
"hashes": [
"sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3",
"sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41"
"sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c",
"sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830"
],
"version": "==2020.6.20"
"version": "==2020.12.5"
},
"chardet": {
"hashes": [
"sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
"sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
"sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa",
"sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5"
],
"index": "pypi",
"version": "==3.0.4"
"version": "==4.0.0"
},
"cheroot": {
"hashes": [
"sha256:ab342666c8e565a55cd2baf2648be9b379269a89d47e60862a087cff9d8b33ce",
"sha256:b6c18caf5f79cdae668c35fc8309fc88ea4a964cce9e2ca8504fab13bcf57301"
"sha256:7ba11294a83468a27be6f06066df8a0f17d954ad05945f28d228aa3f4cd1b03c",
"sha256:f137d03fd5155b1364bea557a7c98168665c239f6c8cedd8f80e81cdfac01567"
],
"version": "==8.4.5"
"version": "==8.5.2"
},
"cherrypy": {
"hashes": [
@ -64,11 +64,60 @@
},
"genshi": {
"hashes": [
"sha256:5e92e278ca1ea395349a451d54fc81dc3c1b543c48939a15bd36b7b3335e1560",
"sha256:7933c95151d7dd2124a2b4c8dd85bb6aec881ca17c0556da0b40e56434b313a0"
"sha256:507edff06388c7d8136fecbd9f4e09bc8e199af1a45238be304ce60523f2efa7",
"sha256:c12d6c2abf7df0ec661d9ff2e197522eae846e43dc58abd5a36443d05bc41135"
],
"index": "pypi",
"version": "==0.7.3"
"version": "==0.7.5"
},
"greenlet": {
"hashes": [
"sha256:0a77691f0080c9da8dfc81e23f4e3cffa5accf0f5b56478951016d7cfead9196",
"sha256:0ddd77586553e3daf439aa88b6642c5f252f7ef79a39271c25b1d4bf1b7cbb85",
"sha256:111cfd92d78f2af0bc7317452bd93a477128af6327332ebf3c2be7df99566683",
"sha256:122c63ba795fdba4fc19c744df6277d9cfd913ed53d1a286f12189a0265316dd",
"sha256:181300f826625b7fd1182205b830642926f52bd8cdb08b34574c9d5b2b1813f7",
"sha256:1a1ada42a1fd2607d232ae11a7b3195735edaa49ea787a6d9e6a53afaf6f3476",
"sha256:1bb80c71de788b36cefb0c3bb6bfab306ba75073dbde2829c858dc3ad70f867c",
"sha256:1d1d4473ecb1c1d31ce8fd8d91e4da1b1f64d425c1dc965edc4ed2a63cfa67b2",
"sha256:292e801fcb3a0b3a12d8c603c7cf340659ea27fd73c98683e75800d9fd8f704c",
"sha256:2c65320774a8cd5fdb6e117c13afa91c4707548282464a18cf80243cf976b3e6",
"sha256:4365eccd68e72564c776418c53ce3c5af402bc526fe0653722bc89efd85bf12d",
"sha256:5352c15c1d91d22902582e891f27728d8dac3bd5e0ee565b6a9f575355e6d92f",
"sha256:58ca0f078d1c135ecf1879d50711f925ee238fe773dfe44e206d7d126f5bc664",
"sha256:5d4030b04061fdf4cbc446008e238e44936d77a04b2b32f804688ad64197953c",
"sha256:5d69bbd9547d3bc49f8a545db7a0bd69f407badd2ff0f6e1a163680b5841d2b0",
"sha256:5f297cb343114b33a13755032ecf7109b07b9a0020e841d1c3cedff6602cc139",
"sha256:62afad6e5fd70f34d773ffcbb7c22657e1d46d7fd7c95a43361de979f0a45aef",
"sha256:647ba1df86d025f5a34043451d7c4a9f05f240bee06277a524daad11f997d1e7",
"sha256:719e169c79255816cdcf6dccd9ed2d089a72a9f6c42273aae12d55e8d35bdcf8",
"sha256:7cd5a237f241f2764324396e06298b5dee0df580cf06ef4ada0ff9bff851286c",
"sha256:875d4c60a6299f55df1c3bb870ebe6dcb7db28c165ab9ea6cdc5d5af36bb33ce",
"sha256:90b6a25841488cf2cb1c8623a53e6879573010a669455046df5f029d93db51b7",
"sha256:94620ed996a7632723a424bccb84b07e7b861ab7bb06a5aeb041c111dd723d36",
"sha256:b5f1b333015d53d4b381745f5de842f19fe59728b65f0fbb662dafbe2018c3a5",
"sha256:c5b22b31c947ad8b6964d4ed66776bcae986f73669ba50620162ba7c832a6b6a",
"sha256:c93d1a71c3fe222308939b2e516c07f35a849c5047f0197442a4d6fbcb4128ee",
"sha256:cdb90267650c1edb54459cdb51dab865f6c6594c3a47ebd441bc493360c7af70",
"sha256:cfd06e0f0cc8db2a854137bd79154b61ecd940dce96fad0cba23fe31de0b793c",
"sha256:d3789c1c394944084b5e57c192889985a9f23bd985f6d15728c745d380318128",
"sha256:da7d09ad0f24270b20f77d56934e196e982af0d0a2446120cb772be4e060e1a2",
"sha256:df3e83323268594fa9755480a442cabfe8d82b21aba815a71acf1bb6c1776218",
"sha256:df8053867c831b2643b2c489fe1d62049a98566b1646b194cc815f13e27b90df",
"sha256:e1128e022d8dce375362e063754e129750323b67454cac5600008aad9f54139e",
"sha256:e6e9fdaf6c90d02b95e6b0709aeb1aba5affbbb9ccaea5502f8638e4323206be",
"sha256:eac8803c9ad1817ce3d8d15d1bb82c2da3feda6bee1153eec5c58fa6e5d3f770",
"sha256:eb333b90036358a0e2c57373f72e7648d7207b76ef0bd00a4f7daad1f79f5203",
"sha256:ed1d1351f05e795a527abc04a0d82e9aecd3bdf9f46662c36ff47b0b00ecaf06",
"sha256:f3dc68272990849132d6698f7dc6df2ab62a88b0d36e54702a8fd16c0490e44f",
"sha256:f59eded163d9752fd49978e0bab7a1ff21b1b8d25c05f0995d140cc08ac83379",
"sha256:f5e2d36c86c7b03c94b8459c3bd2c9fe2c7dab4b258b8885617d44a22e453fb7",
"sha256:f6f65bf54215e4ebf6b01e4bb94c49180a589573df643735107056f7a910275b",
"sha256:f8450d5ef759dbe59f84f2c9f77491bb3d3c44bc1a573746daf086e70b14c243",
"sha256:f97d83049715fd9dec7911860ecf0e17b48d8725de01e45de07d8ac0bd5bc378"
],
"markers": "python_version >= '3'",
"version": "==1.0.0"
},
"html5lib": {
"hashes": [
@ -85,13 +134,21 @@
],
"version": "==2.10"
},
"importlib-metadata": {
"hashes": [
"sha256:8c501196e49fb9df5df43833bdb1e4328f64847763ec8a50703148b73784d581",
"sha256:d7eb1dea6d6a6086f8be21784cc9e3bcfa55872b52309bc5fad53a8ea444465d"
],
"markers": "python_version < '3.8'",
"version": "==4.0.1"
},
"importlib-resources": {
"hashes": [
"sha256:7b51f0106c8ec564b1bef3d9c588bc694ce2b92125bbb6278f4f2f5b54ec3592",
"sha256:a3d34a8464ce1d5d7c92b0ea4e921e696d86f2aa212e684451cb1482c8d84ed5"
"sha256:642586fc4740bd1cad7690f836b3321309402b20b332529f25617ff18e8e1370",
"sha256:ebab3efe74d83b04d6bf5cd9a17f0c5c93e60fb60f30c90f56265fce4682a469"
],
"markers": "python_version < '3.7'",
"version": "==3.3.0"
"version": "==5.1.2"
},
"isodate": {
"hashes": [
@ -103,86 +160,86 @@
},
"jaraco.classes": {
"hashes": [
"sha256:116429c2047953f525afdcae165475c4589c7b14870e78b2d068ecb01018827e",
"sha256:c38698ff8ef932eb33d91c0e8fc192ad7c44ecee03f7f585afd4f35aeaef7aab"
"sha256:22ac35313cf4b145bf7b217cc51be2d98a3d2db1c8558a30ca259d9f0b9c0b7d",
"sha256:ed54b728af1937dc16b7236fbaf34ba561ba1ace572b03fffa5486ed363ecf34"
],
"version": "==3.1.0"
"version": "==3.2.1"
},
"jaraco.collections": {
"hashes": [
"sha256:a7889f28c80c4875bd6256d9924e8526dacfef22cd7b80ff8469b4d312f9f144",
"sha256:be570ef4f2e7290b757449395238fa63d70a9255574624e73c5ff9f1ee554721"
"sha256:3662267424b55f10bf15b6f5dee6a6e48a2865c0ec50cc7a16040c81c55a98dc",
"sha256:fa45052d859a7c28aeef846abb5857b525a1b9ec17bd4118b78e43a222c5a2f1"
],
"version": "==3.0.0"
"version": "==3.3.0"
},
"jaraco.functools": {
"hashes": [
"sha256:9fedc4be3117512ca3e03e1b2ffa7a6a6ffa589bfb7d02bfb324e55d493b94f4",
"sha256:d3dc9f6c1a1d45d7f59682a3bf77aceb685c1a60891606c7e4161e72ecc399ad"
"sha256:7c788376d69cf41da675b186c85366fe9ac23c92a70697c455ef9135c25edf31",
"sha256:bfcf7da71e2a0e980189b0744b59dba6c1dcf66dcd7a30f8a4413e478046b314"
],
"version": "==3.0.1"
"version": "==3.3.0"
},
"jaraco.text": {
"hashes": [
"sha256:c87569c9afae14f71b2e1c57f316770ab6981ab675d9c602be1c7981161bacdd",
"sha256:e5078b1126cc0f166c7859aa75103a56c0d0f39ebcafc21695615472e0f810ec"
"sha256:b647f2bf912e201bfefd01d691bf5d603a94f2b3f998129e4fea595873a25613",
"sha256:f07f1076814a17a98eb915948b9a0dc71b1891c833588066ec1feb04ea4389b1"
],
"version": "==3.2.0"
"version": "==3.5.0"
},
"libgutenberg": {
"hashes": [
"sha256:ec2c99bb0210b106d0c30b06ad0a3a46af44f1c5cd60d8c4482c99c5e22a292c"
"sha256:faa41e56705ca1af474f6790edae94ae9f8525817f093cc2f1c87ece83a52926"
],
"index": "pypi",
"version": "==0.6.7"
"version": "==0.7.0"
},
"lxml": {
"hashes": [
"sha256:0e89f5d422988c65e6936e4ec0fe54d6f73f3128c80eb7ecc3b87f595523607b",
"sha256:189ad47203e846a7a4951c17694d845b6ade7917c47c64b29b86526eefc3adf5",
"sha256:1d87936cb5801c557f3e981c9c193861264c01209cb3ad0964a16310ca1b3301",
"sha256:211b3bcf5da70c2d4b84d09232534ad1d78320762e2c59dedc73bf01cb1fc45b",
"sha256:2358809cc64394617f2719147a58ae26dac9e21bae772b45cfb80baa26bfca5d",
"sha256:23c83112b4dada0b75789d73f949dbb4e8f29a0a3511647024a398ebd023347b",
"sha256:24e811118aab6abe3ce23ff0d7d38932329c513f9cef849d3ee88b0f848f2aa9",
"sha256:2d5896ddf5389560257bbe89317ca7bcb4e54a02b53a3e572e1ce4226512b51b",
"sha256:2d6571c48328be4304aee031d2d5046cbc8aed5740c654575613c5a4f5a11311",
"sha256:2e311a10f3e85250910a615fe194839a04a0f6bc4e8e5bb5cac221344e3a7891",
"sha256:302160eb6e9764168e01d8c9ec6becddeb87776e81d3fcb0d97954dd51d48e0a",
"sha256:3a7a380bfecc551cfd67d6e8ad9faa91289173bdf12e9cfafbd2bdec0d7b1ec1",
"sha256:3d9b2b72eb0dbbdb0e276403873ecfae870599c83ba22cadff2db58541e72856",
"sha256:475325e037fdf068e0c2140b818518cf6bc4aa72435c407a798b2db9f8e90810",
"sha256:4b7572145054330c8e324a72d808c8c8fbe12be33368db28c39a255ad5f7fb51",
"sha256:4fff34721b628cce9eb4538cf9a73d02e0f3da4f35a515773cce6f5fe413b360",
"sha256:56eff8c6fb7bc4bcca395fdff494c52712b7a57486e4fbde34c31bb9da4c6cc4",
"sha256:573b2f5496c7e9f4985de70b9bbb4719ffd293d5565513e04ac20e42e6e5583f",
"sha256:7ecaef52fd9b9535ae5f01a1dd2651f6608e4ec9dc136fc4dfe7ebe3c3ddb230",
"sha256:803a80d72d1f693aa448566be46ffd70882d1ad8fc689a2e22afe63035eb998a",
"sha256:8862d1c2c020cb7a03b421a9a7b4fe046a208db30994fc8ff68c627a7915987f",
"sha256:9b06690224258db5cd39a84e993882a6874676f5de582da57f3df3a82ead9174",
"sha256:a71400b90b3599eb7bf241f947932e18a066907bf84617d80817998cee81e4bf",
"sha256:bb252f802f91f59767dcc559744e91efa9df532240a502befd874b54571417bd",
"sha256:be1ebf9cc25ab5399501c9046a7dcdaa9e911802ed0e12b7d620cd4bbf0518b3",
"sha256:be7c65e34d1b50ab7093b90427cbc488260e4b3a38ef2435d65b62e9fa3d798a",
"sha256:c0dac835c1a22621ffa5e5f999d57359c790c52bbd1c687fe514ae6924f65ef5",
"sha256:c152b2e93b639d1f36ec5a8ca24cde4a8eefb2b6b83668fcd8e83a67badcb367",
"sha256:d182eada8ea0de61a45a526aa0ae4bcd222f9673424e65315c35820291ff299c",
"sha256:d18331ea905a41ae71596502bd4c9a2998902328bbabd29e3d0f5f8569fabad1",
"sha256:d20d32cbb31d731def4b1502294ca2ee99f9249b63bc80e03e67e8f8e126dea8",
"sha256:d4ad7fd3269281cb471ad6c7bafca372e69789540d16e3755dd717e9e5c9d82f",
"sha256:d6f8c23f65a4bfe4300b85f1f40f6c32569822d08901db3b6454ab785d9117cc",
"sha256:d84d741c6e35c9f3e7406cb7c4c2e08474c2a6441d59322a00dcae65aac6315d",
"sha256:e65c221b2115a91035b55a593b6eb94aa1206fa3ab374f47c6dc10d364583ff9",
"sha256:f98b6f256be6cec8dd308a8563976ddaff0bdc18b730720f6f4bee927ffe926f"
"sha256:079f3ae844f38982d156efce585bc540c16a926d4436712cf4baee0cce487a3d",
"sha256:0fbcf5565ac01dff87cbfc0ff323515c823081c5777a9fc7703ff58388c258c3",
"sha256:122fba10466c7bd4178b07dba427aa516286b846b2cbd6f6169141917283aae2",
"sha256:1b7584d421d254ab86d4f0b13ec662a9014397678a7c4265a02a6d7c2b18a75f",
"sha256:26e761ab5b07adf5f555ee82fb4bfc35bf93750499c6c7614bd64d12aaa67927",
"sha256:289e9ca1a9287f08daaf796d96e06cb2bc2958891d7911ac7cae1c5f9e1e0ee3",
"sha256:2a9d50e69aac3ebee695424f7dbd7b8c6d6eb7de2a2eb6b0f6c7db6aa41e02b7",
"sha256:33bb934a044cf32157c12bfcfbb6649807da20aa92c062ef51903415c704704f",
"sha256:3439c71103ef0e904ea0a1901611863e51f50b5cd5e8654a151740fde5e1cade",
"sha256:39b78571b3b30645ac77b95f7c69d1bffc4cf8c3b157c435a34da72e78c82468",
"sha256:4289728b5e2000a4ad4ab8da6e1db2e093c63c08bdc0414799ee776a3f78da4b",
"sha256:4bff24dfeea62f2e56f5bab929b4428ae6caba2d1eea0c2d6eb618e30a71e6d4",
"sha256:542d454665a3e277f76954418124d67516c5f88e51a900365ed54a9806122b83",
"sha256:5a0a14e264069c03e46f926be0d8919f4105c1623d620e7ec0e612a2e9bf1c04",
"sha256:66e575c62792c3f9ca47cb8b6fab9e35bab91360c783d1606f758761810c9791",
"sha256:74f7d8d439b18fa4c385f3f5dfd11144bb87c1da034a466c5b5577d23a1d9b51",
"sha256:7610b8c31688f0b1be0ef882889817939490a36d0ee880ea562a4e1399c447a1",
"sha256:76fa7b1362d19f8fbd3e75fe2fb7c79359b0af8747e6f7141c338f0bee2f871a",
"sha256:7728e05c35412ba36d3e9795ae8995e3c86958179c9770e65558ec3fdfd3724f",
"sha256:8157dadbb09a34a6bd95a50690595e1fa0af1a99445e2744110e3dca7831c4ee",
"sha256:820628b7b3135403540202e60551e741f9b6d3304371712521be939470b454ec",
"sha256:884ab9b29feaca361f7f88d811b1eea9bfca36cf3da27768d28ad45c3ee6f969",
"sha256:89b8b22a5ff72d89d48d0e62abb14340d9e99fd637d046c27b8b257a01ffbe28",
"sha256:92e821e43ad382332eade6812e298dc9701c75fe289f2a2d39c7960b43d1e92a",
"sha256:b007cbb845b28db4fb8b6a5cdcbf65bacb16a8bd328b53cbc0698688a68e1caa",
"sha256:bc4313cbeb0e7a416a488d72f9680fffffc645f8a838bd2193809881c67dd106",
"sha256:bccbfc27563652de7dc9bdc595cb25e90b59c5f8e23e806ed0fd623755b6565d",
"sha256:c4f05c5a7c49d2fb70223d0d5bcfbe474cf928310ac9fa6a7c6dddc831d0b1d4",
"sha256:ce256aaa50f6cc9a649c51be3cd4ff142d67295bfc4f490c9134d0f9f6d58ef0",
"sha256:d2e35d7bf1c1ac8c538f88d26b396e73dd81440d59c1ef8522e1ea77b345ede4",
"sha256:df7c53783a46febb0e70f6b05df2ba104610f2fb0d27023409734a3ecbb78fb2",
"sha256:efac139c3f0bf4f0939f9375af4b02c5ad83a622de52d6dfa8e438e8e01d0eb0",
"sha256:efd7a09678fd8b53117f6bae4fa3825e0a22b03ef0a932e070c0bdbb3a35e654",
"sha256:f2380a6376dfa090227b663f9678150ef27543483055cc327555fb592c5967e2",
"sha256:f8380c03e45cf09f8557bdaa41e1fa7c81f3ae22828e1db470ab2a6c96d8bc23",
"sha256:f90ba11136bfdd25cae3951af8da2e95121c9b9b93727b1b896e3fa105b2f586"
],
"version": "==4.6.1"
"version": "==4.6.3"
},
"more-itertools": {
"hashes": [
"sha256:8e1a2a43b2f2727425f2b5839587ae37093f19153dc26c0927d1048ff6557330",
"sha256:b3a9005928e5bed54076e6e549c792b306fddfe72b2d1d22dd63d42d5d3899cf"
"sha256:5652a9ac72209ed7df8d9c15daf4e1aa0e3d2ccd3c87f8265a0673cd9cbc9ced",
"sha256:c5d6da9ca3ff65220c3bfd2a8db06d698f05d4d2b9be57e1deb2be5a45019713"
],
"version": "==8.6.0"
"version": "==8.7.0"
},
"netaddr": {
"hashes": [
@ -209,44 +266,49 @@
},
"pillow": {
"hashes": [
"sha256:006de60d7580d81f4a1a7e9f0173dc90a932e3905cc4d47ea909bc946302311a",
"sha256:0a2e8d03787ec7ad71dc18aec9367c946ef8ef50e1e78c71f743bc3a770f9fae",
"sha256:0eeeae397e5a79dc088d8297a4c2c6f901f8fb30db47795113a4a605d0f1e5ce",
"sha256:11c5c6e9b02c9dac08af04f093eb5a2f84857df70a7d4a6a6ad461aca803fb9e",
"sha256:2fb113757a369a6cdb189f8df3226e995acfed0a8919a72416626af1a0a71140",
"sha256:4b0ef2470c4979e345e4e0cc1bbac65fda11d0d7b789dbac035e4c6ce3f98adb",
"sha256:59e903ca800c8cfd1ebe482349ec7c35687b95e98cefae213e271c8c7fffa021",
"sha256:5abd653a23c35d980b332bc0431d39663b1709d64142e3652890df4c9b6970f6",
"sha256:5f9403af9c790cc18411ea398a6950ee2def2a830ad0cfe6dc9122e6d528b302",
"sha256:6b4a8fd632b4ebee28282a9fef4c341835a1aa8671e2770b6f89adc8e8c2703c",
"sha256:6c1aca8231625115104a06e4389fcd9ec88f0c9befbabd80dc206c35561be271",
"sha256:795e91a60f291e75de2e20e6bdd67770f793c8605b553cb6e4387ce0cb302e09",
"sha256:7ba0ba61252ab23052e642abdb17fd08fdcfdbbf3b74c969a30c58ac1ade7cd3",
"sha256:7c9401e68730d6c4245b8e361d3d13e1035cbc94db86b49dc7da8bec235d0015",
"sha256:81f812d8f5e8a09b246515fac141e9d10113229bc33ea073fec11403b016bcf3",
"sha256:895d54c0ddc78a478c80f9c438579ac15f3e27bf442c2a9aa74d41d0e4d12544",
"sha256:8de332053707c80963b589b22f8e0229f1be1f3ca862a932c1bcd48dafb18dd8",
"sha256:92c882b70a40c79de9f5294dc99390671e07fc0b0113d472cbea3fde15db1792",
"sha256:95edb1ed513e68bddc2aee3de66ceaf743590bf16c023fb9977adc4be15bd3f0",
"sha256:b63d4ff734263ae4ce6593798bcfee6dbfb00523c82753a3a03cbc05555a9cc3",
"sha256:bd7bf289e05470b1bc74889d1466d9ad4a56d201f24397557b6f65c24a6844b8",
"sha256:cc3ea6b23954da84dbee8025c616040d9aa5eaf34ea6895a0a762ee9d3e12e11",
"sha256:cc9ec588c6ef3a1325fa032ec14d97b7309db493782ea8c304666fb10c3bd9a7",
"sha256:d3d07c86d4efa1facdf32aa878bd508c0dc4f87c48125cc16b937baa4e5b5e11",
"sha256:d8a96747df78cda35980905bf26e72960cba6d355ace4780d4bdde3b217cdf1e",
"sha256:e38d58d9138ef972fceb7aeec4be02e3f01d383723965bfcef14d174c8ccd039",
"sha256:eb472586374dc66b31e36e14720747595c2b265ae962987261f044e5cce644b5",
"sha256:fbd922f702582cb0d71ef94442bfca57624352622d75e3be7a1e7e9360b07e72"
"sha256:01425106e4e8cee195a411f729cff2a7d61813b0b11737c12bd5991f5f14bcd5",
"sha256:031a6c88c77d08aab84fecc05c3cde8414cd6f8406f4d2b16fed1e97634cc8a4",
"sha256:083781abd261bdabf090ad07bb69f8f5599943ddb539d64497ed021b2a67e5a9",
"sha256:0d19d70ee7c2ba97631bae1e7d4725cdb2ecf238178096e8c82ee481e189168a",
"sha256:0e04d61f0064b545b989126197930807c86bcbd4534d39168f4aa5fda39bb8f9",
"sha256:12e5e7471f9b637762453da74e390e56cc43e486a88289995c1f4c1dc0bfe727",
"sha256:22fd0f42ad15dfdde6c581347eaa4adb9a6fc4b865f90b23378aa7914895e120",
"sha256:238c197fc275b475e87c1453b05b467d2d02c2915fdfdd4af126145ff2e4610c",
"sha256:3b570f84a6161cf8865c4e08adf629441f56e32f180f7aa4ccbd2e0a5a02cba2",
"sha256:463822e2f0d81459e113372a168f2ff59723e78528f91f0bd25680ac185cf797",
"sha256:4d98abdd6b1e3bf1a1cbb14c3895226816e666749ac040c4e2554231068c639b",
"sha256:5afe6b237a0b81bd54b53f835a153770802f164c5570bab5e005aad693dab87f",
"sha256:5b70110acb39f3aff6b74cf09bb4169b167e2660dabc304c1e25b6555fa781ef",
"sha256:5cbf3e3b1014dddc45496e8cf38b9f099c95a326275885199f427825c6522232",
"sha256:624b977355cde8b065f6d51b98497d6cd5fbdd4f36405f7a8790e3376125e2bb",
"sha256:63728564c1410d99e6d1ae8e3b810fe012bc440952168af0a2877e8ff5ab96b9",
"sha256:66cc56579fd91f517290ab02c51e3a80f581aba45fd924fcdee01fa06e635812",
"sha256:6c32cc3145928c4305d142ebec682419a6c0a8ce9e33db900027ddca1ec39178",
"sha256:8bb1e155a74e1bfbacd84555ea62fa21c58e0b4e7e6b20e4447b8d07990ac78b",
"sha256:95d5ef984eff897850f3a83883363da64aae1000e79cb3c321915468e8c6add5",
"sha256:a013cbe25d20c2e0c4e85a9daf438f85121a4d0344ddc76e33fd7e3965d9af4b",
"sha256:a787ab10d7bb5494e5f76536ac460741788f1fbce851068d73a87ca7c35fc3e1",
"sha256:a7d5e9fad90eff8f6f6106d3b98b553a88b6f976e51fce287192a5d2d5363713",
"sha256:aac00e4bc94d1b7813fe882c28990c1bc2f9d0e1aa765a5f2b516e8a6a16a9e4",
"sha256:b91c36492a4bbb1ee855b7d16fe51379e5f96b85692dc8210831fbb24c43e484",
"sha256:c03c07ed32c5324939b19e36ae5f75c660c81461e312a41aea30acdd46f93a7c",
"sha256:c5236606e8570542ed424849f7852a0ff0bce2c4c8d0ba05cc202a5a9c97dee9",
"sha256:c6b39294464b03457f9064e98c124e09008b35a62e3189d3513e5148611c9388",
"sha256:cb7a09e173903541fa888ba010c345893cd9fc1b5891aaf060f6ca77b6a3722d",
"sha256:d68cb92c408261f806b15923834203f024110a2e2872ecb0bd2a110f89d3c602",
"sha256:dc38f57d8f20f06dd7c3161c59ca2c86893632623f33a42d592f097b00f720a9",
"sha256:e98eca29a05913e82177b3ba3d198b1728e164869c613d76d0de4bde6768a50e",
"sha256:f217c3954ce5fd88303fc0c317af55d5e0204106d86dea17eb8205700d47dec2"
],
"index": "pypi",
"version": "==8.0.1"
"version": "==8.2.0"
},
"portend": {
"hashes": [
"sha256:600dd54175e17e9347e5f3d4217aa8bcf4bf4fa5ffbc4df034e5ec1ba7cdaff5",
"sha256:62dd00b94a6a55fbf0320365fbdeba37f0d1fe14d613841037dc4780bedfda8f"
"sha256:986ed9a278e64a87b5b5f4c21e61c25bebdce9919a92238d9c14c37a7416482b",
"sha256:add53a9e65d4022885f97de7895da583d0ed57df3eadb0b4d2ada594268cc0e6"
],
"version": "==2.6"
"version": "==2.7.1"
},
"psycopg2": {
"hashes": [
@ -286,19 +348,19 @@
},
"pyparsing": {
"hashes": [
"sha256:1060635ca5ac864c2b7bc7b05a448df4e32d7d8c65e33cbe1514810d339672a2",
"sha256:56a551039101858c9e189ac9e66e330a03fb7079e97ba6b50193643905f450ce"
"sha256:1c6409312ce2ce2997896af5756753778d5f1603666dba5587804f09ad82ed27",
"sha256:f4896b4cc085a1f8f8ae53a1a90db5a86b3825ff73eb974dffee3d9e701007f4"
],
"index": "pypi",
"version": "==3.0.0a2"
"version": "==3.0.0b2"
},
"pytz": {
"hashes": [
"sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed",
"sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048"
"sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da",
"sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"
],
"index": "pypi",
"version": "==2020.1"
"version": "==2021.1"
},
"qrcode": {
"hashes": [
@ -318,36 +380,50 @@
},
"regex": {
"hashes": [
"sha256:03855ee22980c3e4863dc84c42d6d2901133362db5daf4c36b710dd895d78f0a",
"sha256:06b52815d4ad38d6524666e0d50fe9173533c9cc145a5779b89733284e6f688f",
"sha256:11116d424734fe356d8777f89d625f0df783251ada95d6261b4c36ad27a394bb",
"sha256:119e0355dbdd4cf593b17f2fc5dbd4aec2b8899d0057e4957ba92f941f704bf5",
"sha256:1ec66700a10e3c75f1f92cbde36cca0d3aaee4c73dfa26699495a3a30b09093c",
"sha256:2dc522e25e57e88b4980d2bdd334825dbf6fa55f28a922fc3bfa60cc09e5ef53",
"sha256:3a5f08039eee9ea195a89e180c5762bfb55258bfb9abb61a20d3abee3b37fd12",
"sha256:49461446b783945597c4076aea3f49aee4b4ce922bd241e4fcf62a3e7c61794c",
"sha256:4afa350f162551cf402bfa3cd8302165c8e03e689c897d185f16a167328cc6dd",
"sha256:4b5a9bcb56cc146c3932c648603b24514447eafa6ce9295234767bf92f69b504",
"sha256:625116aca6c4b57c56ea3d70369cacc4d62fead4930f8329d242e4fe7a58ce4b",
"sha256:654c1635f2313d0843028487db2191530bca45af61ca85d0b16555c399625b0e",
"sha256:8092a5a06ad9a7a247f2a76ace121183dc4e1a84c259cf9c2ce3bbb69fac3582",
"sha256:832339223b9ce56b7b15168e691ae654d345ac1635eeb367ade9ecfe0e66bee0",
"sha256:8ca9dca965bd86ea3631b975d63b0693566d3cc347e55786d5514988b6f5b84c",
"sha256:a62162be05edf64f819925ea88d09d18b09bebf20971b363ce0c24e8b4aa14c0",
"sha256:b88fa3b8a3469f22b4f13d045d9bd3eda797aa4e406fde0a2644bc92bbdd4bdd",
"sha256:c13d311a4c4a8d671f5860317eb5f09591fbe8259676b86a85769423b544451e",
"sha256:c2c6c56ee97485a127555c9595c069201b5161de9d05495fbe2132b5ac104786",
"sha256:c3466a84fce42c2016113101018a9981804097bacbab029c2d5b4fcb224b89de",
"sha256:c8a2b7ccff330ae4c460aff36626f911f918555660cc28163417cb84ffb25789",
"sha256:cb905f3d2e290a8b8f1579d3984f2cfa7c3a29cc7cba608540ceeed18513f520",
"sha256:cfcf28ed4ce9ced47b9b9670a4f0d3d3c0e4d4779ad4dadb1ad468b097f808aa",
"sha256:dd3e6547ecf842a29cf25123fbf8d2461c53c8d37aa20d87ecee130c89b7079b",
"sha256:ea37320877d56a7f0a1e6a625d892cf963aa7f570013499f5b8d5ab8402b5625",
"sha256:f1fce1e4929157b2afeb4bb7069204d4370bab9f4fc03ca1fbec8bd601f8c87d",
"sha256:f43109822df2d3faac7aad79613f5f02e4eab0fc8ad7932d2e70e2a83bd49c26"
"sha256:01afaf2ec48e196ba91b37451aa353cb7eda77efe518e481707e0515025f0cd5",
"sha256:11d773d75fa650cd36f68d7ca936e3c7afaae41b863b8c387a22aaa78d3c5c79",
"sha256:18c071c3eb09c30a264879f0d310d37fe5d3a3111662438889ae2eb6fc570c31",
"sha256:1e1c20e29358165242928c2de1482fb2cf4ea54a6a6dea2bd7a0e0d8ee321500",
"sha256:281d2fd05555079448537fe108d79eb031b403dac622621c78944c235f3fcf11",
"sha256:314d66636c494ed9c148a42731b3834496cc9a2c4251b1661e40936814542b14",
"sha256:32e65442138b7b76dd8173ffa2cf67356b7bc1768851dded39a7a13bf9223da3",
"sha256:339456e7d8c06dd36a22e451d58ef72cef293112b559010db3d054d5560ef439",
"sha256:3916d08be28a1149fb97f7728fca1f7c15d309a9f9682d89d79db75d5e52091c",
"sha256:3a9cd17e6e5c7eb328517969e0cb0c3d31fd329298dd0c04af99ebf42e904f82",
"sha256:47bf5bf60cf04d72bf6055ae5927a0bd9016096bf3d742fa50d9bf9f45aa0711",
"sha256:4c46e22a0933dd783467cf32b3516299fb98cfebd895817d685130cc50cd1093",
"sha256:4c557a7b470908b1712fe27fb1ef20772b78079808c87d20a90d051660b1d69a",
"sha256:52ba3d3f9b942c49d7e4bc105bb28551c44065f139a65062ab7912bef10c9afb",
"sha256:563085e55b0d4fb8f746f6a335893bda5c2cef43b2f0258fe1020ab1dd874df8",
"sha256:598585c9f0af8374c28edd609eb291b5726d7cbce16be6a8b95aa074d252ee17",
"sha256:619d71c59a78b84d7f18891fe914446d07edd48dc8328c8e149cbe0929b4e000",
"sha256:67bdb9702427ceddc6ef3dc382455e90f785af4c13d495f9626861763ee13f9d",
"sha256:6d1b01031dedf2503631d0903cb563743f397ccaf6607a5e3b19a3d76fc10480",
"sha256:741a9647fcf2e45f3a1cf0e24f5e17febf3efe8d4ba1281dcc3aa0459ef424dc",
"sha256:7c2a1af393fcc09e898beba5dd59196edaa3116191cc7257f9224beaed3e1aa0",
"sha256:7d9884d86dd4dd489e981d94a65cd30d6f07203d90e98f6f657f05170f6324c9",
"sha256:90f11ff637fe8798933fb29f5ae1148c978cccb0452005bf4c69e13db951e765",
"sha256:919859aa909429fb5aa9cf8807f6045592c85ef56fdd30a9a3747e513db2536e",
"sha256:96fcd1888ab4d03adfc9303a7b3c0bd78c5412b2bfbe76db5b56d9eae004907a",
"sha256:97f29f57d5b84e73fbaf99ab3e26134e6687348e95ef6b48cfd2c06807005a07",
"sha256:980d7be47c84979d9136328d882f67ec5e50008681d94ecc8afa8a65ed1f4a6f",
"sha256:a91aa8619b23b79bcbeb37abe286f2f408d2f2d6f29a17237afda55bb54e7aac",
"sha256:ade17eb5d643b7fead300a1641e9f45401c98eee23763e9ed66a43f92f20b4a7",
"sha256:b9c3db21af35e3b3c05764461b262d6f05bbca08a71a7849fd79d47ba7bc33ed",
"sha256:bd28bc2e3a772acbb07787c6308e00d9626ff89e3bfcdebe87fa5afbfdedf968",
"sha256:bf5824bfac591ddb2c1f0a5f4ab72da28994548c708d2191e3b87dd207eb3ad7",
"sha256:c0502c0fadef0d23b128605d69b58edb2c681c25d44574fc673b0e52dce71ee2",
"sha256:c38c71df845e2aabb7fb0b920d11a1b5ac8526005e533a8920aea97efb8ec6a4",
"sha256:ce15b6d103daff8e9fee13cf7f0add05245a05d866e73926c358e871221eae87",
"sha256:d3029c340cfbb3ac0a71798100ccc13b97dddf373a4ae56b6a72cf70dfd53bc8",
"sha256:e512d8ef5ad7b898cdb2d8ee1cb09a8339e4f8be706d27eaa180c2f177248a10",
"sha256:e8e5b509d5c2ff12f8418006d5a90e9436766133b564db0abaec92fd27fcee29",
"sha256:ee54ff27bf0afaf4c3b3a62bcd016c12c3fdb4ec4f413391a90bd38bc3624605",
"sha256:fa4537fb4a98fe8fde99626e4681cc644bdcf2a795038533f9f711513a862ae6",
"sha256:fd45ff9293d9274c5008a2054ecef86a9bfe819a67c7be1afb65e69b405b3042"
],
"index": "pypi",
"version": "==2020.10.28"
"version": "==2021.4.4"
},
"repoze.lru": {
"hashes": [
@ -359,11 +435,11 @@
},
"requests": {
"hashes": [
"sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b",
"sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898"
"sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804",
"sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e"
],
"index": "pypi",
"version": "==2.24.0"
"version": "==2.25.1"
},
"requests-oauthlib": {
"hashes": [
@ -442,62 +518,67 @@
},
"sqlalchemy": {
"hashes": [
"sha256:009e8388d4d551a2107632921320886650b46332f61dc935e70c8bcf37d8e0d6",
"sha256:0157c269701d88f5faf1fa0e4560e4d814f210c01a5b55df3cab95e9346a8bcc",
"sha256:0a92745bb1ebbcb3985ed7bda379b94627f0edbc6c82e9e4bac4fb5647ae609a",
"sha256:0cca1844ba870e81c03633a99aa3dc62256fb96323431a5dec7d4e503c26372d",
"sha256:166917a729b9226decff29416f212c516227c2eb8a9c9f920d69ced24e30109f",
"sha256:1f5f369202912be72fdf9a8f25067a5ece31a2b38507bb869306f173336348da",
"sha256:2909dffe5c9a615b7e6c92d1ac2d31e3026dc436440a4f750f4749d114d88ceb",
"sha256:2b5dafed97f778e9901b79cc01b88d39c605e0545b4541f2551a2fd785adc15b",
"sha256:2e9bd5b23bba8ae8ce4219c9333974ff5e103c857d9ff0e4b73dc4cb244c7d86",
"sha256:3aa6d45e149a16aa1f0c46816397e12313d5e37f22205c26e06975e150ffcf2a",
"sha256:4bdbdb8ca577c6c366d15791747c1de6ab14529115a2eb52774240c412a7b403",
"sha256:53fd857c6c8ffc0aa6a5a3a2619f6a74247e42ec9e46b836a8ffa4abe7aab327",
"sha256:5cdfe54c1e37279dc70d92815464b77cd8ee30725adc9350f06074f91dbfeed2",
"sha256:5d92c18458a4aa27497a986038d5d797b5279268a2de303cd00910658e8d149c",
"sha256:632b32183c0cb0053194a4085c304bc2320e5299f77e3024556fa2aa395c2a8b",
"sha256:7c735c7a6db8ee9554a3935e741cf288f7dcbe8706320251eb38c412e6a4281d",
"sha256:7cd40cb4bc50d9e87b3540b23df6e6b24821ba7e1f305c1492b0806c33dbdbec",
"sha256:84f0ac4a09971536b38cc5d515d6add7926a7e13baa25135a1dbb6afa351a376",
"sha256:8dcbf377529a9af167cbfc5b8acec0fadd7c2357fc282a1494c222d3abfc9629",
"sha256:950f0e17ffba7a7ceb0dd056567bc5ade22a11a75920b0e8298865dc28c0eff6",
"sha256:9e379674728f43a0cd95c423ac0e95262500f9bfd81d33b999daa8ea1756d162",
"sha256:b15002b9788ffe84e42baffc334739d3b68008a973d65fad0a410ca5d0531980",
"sha256:b6f036ecc017ec2e2cc2a40615b41850dc7aaaea6a932628c0afc73ab98ba3fb",
"sha256:bad73f9888d30f9e1d57ac8829f8a12091bdee4949b91db279569774a866a18e",
"sha256:bbc58fca72ce45a64bb02b87f73df58e29848b693869e58bd890b2ddbb42d83b",
"sha256:bca4d367a725694dae3dfdc86cf1d1622b9f414e70bd19651f5ac4fb3aa96d61",
"sha256:be41d5de7a8e241864189b7530ca4aaf56a5204332caa70555c2d96379e18079",
"sha256:bf53d8dddfc3e53a5bda65f7f4aa40fae306843641e3e8e701c18a5609471edf",
"sha256:c092fe282de83d48e64d306b4bce03114859cdbfe19bf8a978a78a0d44ddadb1",
"sha256:c3ab23ee9674336654bf9cac30eb75ac6acb9150dc4b1391bec533a7a4126471",
"sha256:ce64a44c867d128ab8e675f587aae7f61bd2db836a3c4ba522d884cd7c298a77",
"sha256:d05cef4a164b44ffda58200efcb22355350979e000828479971ebca49b82ddb1",
"sha256:d2f25c7f410338d31666d7ddedfa67570900e248b940d186b48461bd4e5569a1",
"sha256:d3b709d64b5cf064972b3763b47139e4a0dc4ae28a36437757f7663f67b99710",
"sha256:e32e3455db14602b6117f0f422f46bc297a3853ae2c322ecd1e2c4c04daf6ed5",
"sha256:ed53209b5f0f383acb49a927179fa51a6e2259878e164273ebc6815f3a752465",
"sha256:f605f348f4e6a2ba00acb3399c71d213b92f27f2383fc4abebf7a37368c12142",
"sha256:fcdb3755a7c355bc29df1b5e6fb8226d5c8b90551d202d69d0076a8a5649d68b"
"sha256:0140f6dac2659fa6783e7029085ab0447d8eb23cf4d831fb907588d27ba158f7",
"sha256:034b42a6a59bf4ddc57e5a38a9dbac83ccd94c0b565ba91dba4ff58149706028",
"sha256:03a503ecff0cc2be3ad4dafd220eaff13721edb11c191670b7662932fb0a5c3a",
"sha256:069de3a701d33709236efe0d06f38846b738b19c63d45cc47f54590982ba7802",
"sha256:1735e06a3d5b0793d5ee2d952df8a5c63edaff6383c2210c9b5c93dc2ea4c315",
"sha256:19633df6be629200ff3c026f2837e1dd17908fb1bcea860290a5a45e6fa5148e",
"sha256:1e14fa32969badef9c309f55352e5c46f321bd29f7c600556caacdaa3eddfcf6",
"sha256:31e941d6db8b026bc63e46ef71e877913f128bd44260b90c645432626b7f9a47",
"sha256:452c4e002be727cb6f929dbd32bbc666a0921b86555b8af09709060ed3954bd3",
"sha256:45a720029756800628359192630fffdc9660ab6f27f0409bd24d9e09d75d6c18",
"sha256:4a2e7f037d3ca818d6d0490e3323fd451545f580df30d62b698da2f247015a34",
"sha256:4a7d4da2acf6d5d068fb41c48950827c49c3c68bfb46a1da45ea8fbf7ed4b471",
"sha256:4ad4044eb86fbcbdff2106e44f479fbdac703d77860b3e19988c8a8786e73061",
"sha256:4f631edf45a943738fa77612e85fc5c5d3fb637c4f5a530f7eedd1a7cd7a70a7",
"sha256:6389b10e23329dc8b5600c1a84e3da2628d0f437d8a5cd05aefd1470ec571dd1",
"sha256:6ebd58e73b7bd902688c0bb8dbabb0c36b756f02cc7b27ad5efa2f380c611f95",
"sha256:7180830ea1082b96b94884bc352b274e29b45151b6ee911bf1fd79cba2de659b",
"sha256:789be639501445d85fd4ca41d04f0f5c6cbb6deb0c6826aaa6f22774fe84ef94",
"sha256:7d89add44938ea4f52c7641d5805c9e154fed4381e874ef3221483eeb191a96d",
"sha256:842b0d4698381aac047f8ae57409c90b7e63ebabf5bc02814ddc8eaefd13499e",
"sha256:8f96d4b6a49d3f0f109365bb6303ae5d266d3f90280ca68cf8b2c46032491038",
"sha256:961b089e64c2ad29ad367487dd3ba1aa3eeba56bc82037ce91732baaa0f6ca90",
"sha256:96de1d4a2e05d4a017087cb29cd6a8ebfeecfd0e9f872880b1a589f011c1c02e",
"sha256:98214f04802a3fc740038744d8981a8f2fdca710f791ca125fc4792737d9f3a7",
"sha256:9cf94161cb55507cee147bf8abcfd3c076b353ad18743296764dd81108ea74f8",
"sha256:9fdf0713166f33e5e6ea98cf59deb305cb323131277f6880de6c509f468076f8",
"sha256:a41ab83ecfadf38a47bdfaf4e488f71579df47a711e1ab1dce30d34c7c25bd00",
"sha256:ac14fee167653ec6dee32d6aa4d501d90ae1bfbbc3eb5816940bccf227f0d617",
"sha256:b8b7d66ee8b8ac272adce0af1342a60854f0d89686e6d3318127a6a82a2f765c",
"sha256:bb1072fdf48ba870c0fe81bee8babe4ba2f096fb56bb4f3e0c2386a7626e405c",
"sha256:cd823071b97c1a6ac3af9e43b5d861126a1304033dcd18dfe354a02ec45642fe",
"sha256:d08173144aebdf30c21a331b532db16535cfa83deed12e8703fa6c67c0894ffc",
"sha256:e7d76312e904aa4ea221a92c0bc2e299ad46e4580e2d72ca1f7e6d31dce5bfab",
"sha256:f772e4428d413c0affe2a34836278fbe9df9a9c0940705860c2d3a4b50af1a66"
],
"index": "pypi",
"version": "==1.3.20"
"version": "==1.4.11"
},
"tempora": {
"hashes": [
"sha256:599a3a910b377f2b544c7b221582ecf4cb049b017c994b37f2b1a9ed1099716e",
"sha256:9f46de767be7dd21d9602a8a5b0978fd55abc70af3e2a7814c85c00d7a8fffa3"
"sha256:10fdc29bf85fa0df39a230a225bb6d093982fc0825b648a414bbc06bddd79909",
"sha256:d44aec6278b27d34a47471ead01b710351076eb5d61181551158f1613baf6bc8"
],
"version": "==4.0.0"
"version": "==4.0.2"
},
"typing-extensions": {
"hashes": [
"sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918",
"sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c",
"sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f"
],
"markers": "python_version < '3.8'",
"version": "==3.7.4.3"
},
"urllib3": {
"hashes": [
"sha256:8d7eaa5a82a1cac232164990f04874c594c9453ec55eef02eab885aa02fc17a2",
"sha256:f5321fbe4bf3fefa0efd0bfe7fb14e90909eb62a48ccda331726b4319897dd5e"
"sha256:2f4da4594db7e1e110a944bb1b551fdf4e6c136ad42e4234131391e21eb5b0df",
"sha256:e7b021f7241115872f92f43c6508082facffbd1c048e3c6e2bb9c2a157e28937"
],
"index": "pypi",
"version": "==1.25.11"
"version": "==1.26.4"
},
"webencodings": {
"hashes": [
@ -515,11 +596,11 @@
},
"zipp": {
"hashes": [
"sha256:102c24ef8f171fd729d46599845e95c7ab894a4cf45f5de11a44cc7444fb1108",
"sha256:ed5eee1974372595f9e416cc7bbeeb12335201d8081ca8a0743c954d4446e5cb"
"sha256:3607921face881ba3e026887d8150cca609d517579abe052ac81fc5aeffdbd76",
"sha256:51cb66cc54621609dd593d1787f286ee42a5c0adbb4b29abea5a63edc3e03098"
],
"markers": "python_version < '3.8'",
"version": "==3.4.0"
"version": "==3.4.1"
}
},
"develop": {}

View File

@ -1,43 +0,0 @@
# will submit a PR to CherryPy project - if it gets merged we can remove it. ESH 8/15/2019
import cherrypy
from cherrypy.lib.sessions import RamSession as cpRamSession
class RamSession(cpRamSession):
def clean_up(self):
"""Clean up expired sessions."""
now = self.now()
try:
cache_items_copy = self.cache.copy().items()
except RuntimeError as re:
"""Under heavy load, list(self.cache.items()) will occasionally raise this error
for large session caches with message "dictionary changed size during iteration"
Better to pause the cleanup than to let the cleanup thread die.
"""
cherrypy.log(f'Runtime Error happened while copying the cache entries: {re}')
cherrypy.log('Ref: https://github.com/cherrypy/cherrypy/pull/1804')
return
for _id, (data, expiration_time) in cache_items_copy:
if expiration_time <= now:
try:
del self.cache[_id]
except KeyError:
pass
try:
if self.locks[_id].acquire(blocking=False):
lock = self.locks.pop(_id)
lock.release()
except KeyError:
pass
# added to remove obsolete lock objects
for _id in list(self.locks):
locked = (
_id not in self.cache
and self.locks[_id].acquire(blocking=False)
)
if locked:
lock = self.locks.pop(_id)
lock.release()

186
templates/advresults.html Normal file
View File

@ -0,0 +1,186 @@
<?xml version="1.0" encoding="utf-8"?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:py="http://genshi.edgewall.org/"
xmlns:i18n="http://genshi.edgewall.org/i18n"
xmlns:dcterms="http://purl.org/dc/terms/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:ebook="http://www.gutenberg.org/ebooks/"
xmlns:marcrel="http://www.loc.gov/loc.terms/relators/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:og="http://opengraphprotocol.org/schema/"
xmlns:fb="http://www.facebook.com/2008/fbml"
xml:lang="${os.lang}">
<?python
from itertools import cycle
from libgutenberg.DublinCore import DublinCore
?>
<xi:include href="site-layout.html" />
<xi:include href="social-functions.html" />
<head >
<!--<base href="https://www.gutenberg.org/" />-->
<link rel="stylesheet" href="/gutenberg/collapsible.css?1.1" />
${site_head()}
<title>${os.title} - ${os.pg}</title>
<link rel="self"
i18n:comment="Link pointing to the same page the user is viewing."
title="This Page"
href="${os.url(pageno=os.pageno)}" />
<link py:if="os.prevpage"
rel="first"
title="First Page"
href="${os.url(pageno=1)}" />
<link py:if="os.prevpage"
rel="previous"
title="Previous Page"
href="${os.url(pageno=os.prevpage)}" />
<link py:if="os.nextpage"
rel="next"
title="Next Page"
href="${os.url(pageno=os.nextpage)}" />
<meta name="totalResults" content="${os.total_results}" />
<meta name="startIndex" content="${os.start_index}" />
<meta name="itemsPerPage" content="${os.items_per_page}" />
</head>
<body>
<div class="container">
<div id="mw-head-dummy" class="noprint" />
<div id="content" class="page_content" i18n:comment="On the page of results of a search.">
<!-- start content -->
<py:if test='os.search_terms'>
<p>You selected:</p>
<ul>
<py:for each="term, value, count in os.search_terms">
<li>${term} = ${value} (${count} items match)</li>
</py:for>
</ul>
<p>${os.total_results} books found. </p>
</py:if>
<py:if test='os.total_results &gt; 1000'>
<p>More than 1000 books matched your search. Please refine your query to see results.</p>
</py:if>
<py:if test='os.total_results and (os.total_results &lt;= 1000)'>
<py:if test="os.total_results &gt; os.items_per_page">
<p class="center resultpages">
<a py:if="os.prevpage" href="${os.url(pageno=os.prevpage)}">previous</a>
<py:for each="page in range(1, os.lastpage + 1)">
<a href="${os.url(pageno=page)}">
<span class="${'red' if page == os.pageno else 'black'}">${page}</span>
</a>
</py:for>
<a py:if="os.nextpage" href="${os.url(pageno=os.nextpage)}">next</a>
</p>
</py:if>
<table cellspacing="0" class="pgdbfiles" py:with="cls=cycle(('evenrow', 'oddrow'))">
<caption>Titles</caption>
<colgroup>
<col class="narrow right" />
<col class="narrow" />
<col class="pgdbdataauthor" />
<col class="pgdbdatatitle" />
<col class="narrow" />
</colgroup>
<tr>
<th class="narrow right">Etext-No.</th>
<th class="narrow"><img src="/pics/stock_volume-16.png" width="16" height="16" alt="Audio" title="Audio Book" /></th>
<th class="pgdbdataauthor">Author</th>
<th class="pgdbdatatitle">Title</th>
<th class="narrow">Language</th>
</tr>
<py:for each="book in os.entries">
<tr class="${next(cls)}">
<td>${book.pk}</td>
<td>
<py:if test="book.is_audiobook"><img src="/pics/stock_volume-16.png" width="16" height="16" alt="Audio" title="Audio Book" /></py:if>
&nbsp;
</td>
<td>
<ul>
<py:for each="author in book.authors">
<li><a href="/browse/authors/${author.first_letter}#a${author.id}">${DublinCore.format_author_date_role(author)}</a></li>
</py:for>
</ul>
</td>
<td><a href="/ebooks/${book.pk}">${book.title}</a></td>
<td>${[lang.language for lang in book.langs]}</td>
</tr>
</py:for>
</table>
<py:if test="os.total_results &gt; os.items_per_page">
<p class="center resultpages">
<a py:if="os.prevpage" href="${os.url(pageno=os.prevpage)}">previous</a>
<py:for each="page in range(1, os.lastpage + 1)" >
<a href="${os.url(pageno=page)}">
<span class="${'red' if page == os.pageno else 'black'}">${page}</span>
</a>
</py:for>
<a py:if="os.nextpage" href="${os.url(pageno=os.nextpage)}">next</a>
</p>
</py:if>
</py:if>
<div id="popup2" class="overlay">
<div class="popup">
<a class="close" href="#">&times;</a>
<div class="content">
<ul>
<li>Advanced Search is case insensitive.</li>
<li>Fill in as many fields you like.</li>
<li>Enter one or more space separated words in each field.
Avoid punctuation characters.</li>
<li>The result will match all of the words you entered in all
of the fields. Eg. Author: <i>Jules Verne</i>, Title: <i>20</i>,
Language: <i>French</i> will get <i>20.000 Leagues Under The Sea</i>
in French.</li>
<li>Select Language: <i>English</i> only if you explicitly want to
exclude works in languages other than English.
Eg. Author: <i>Molière</i> Language: <i>English</i>
will get all the works of Molière translated into English.</li>
</ul>
</div>
</div>
</div>
<div id="popup4" class="overlay">
<div class="popup">
<a class="close" href="#">&times;</a>
<div class="content">
<p>These are different ways to browse through the collection.</p>
</div>
</div>
</div>
<div id="popup5" class="overlay">
<div class="popup">
<a class="close" href="#">&times;</a>
<div class="content">
</div>
</div>
</div>
<xi:include href="advsearch.html" />
</div>
</div>
${site_footer ()}
<xi:include href="menu.html" />
</body>
</html>

620
templates/advsearch.html Normal file
View File

@ -0,0 +1,620 @@
<div xmlns:py="http://genshi.edgewall.org/" class="box">
<a class="button" href="#popup2">Help</a>
<!-- Advanced search form begins here -->
<form method="post" action="/ebooks/results/" accept-charset="utf-8" enctype="multipart/form-data">
<input id="collapsible1" class="toggle" type="checkbox" checked="${'true' if os.params else 'false'}"/>
<label for="collapsible1" class="lbl-toggle">Advanced Search</label>
<div class="collapsible-content">
<div class="content-inner">
<p>
<label for="author">Author:</label>
<input type="text" name="author" id="author" value="" />
</p>
<p>
<label for="title">Title:</label>
<input type="text" name="title" id="title" value="" />
</p>
<p>
<label for="subject">Subject:</label>
<input type="text" name="subject" id="subject" value="" />
</p>
<p>
<label for="language">Language:</label>
<select id="lang" name="lang" title="Language">
<option value="">Any</option>
<option value="af">Afrikaans</option>
<option value="ale">Aleut</option>
<option value="ar">Arabic</option>
<option value="arp">Arapaho</option>
<option value="brx">Bodo</option>
<option value="br">Breton</option>
<option value="bg">Bulgarian</option>
<option value="rmr">Caló</option>
<option value="ca">Catalan</option>
<option value="ceb">Cebuano</option>
<option value="zh">Chinese</option>
<option value="cs">Czech</option>
<option value="da">Danish</option>
<option value="nl">Dutch</option>
<option value="en">English</option>
<option value="eo">Esperanto</option>
<option value="et">Estonian</option>
<option value="fa">Farsi</option>
<option value="fi">Finnish</option>
<option value="fr">French</option>
<option value="fy">Frisian</option>
<option value="fur">Friulian</option>
<option value="gla">Gaelic, Scottish</option>
<option value="gl">Galician</option>
<option value="kld">Gamilaraay</option>
<option value="de">German</option>
<option value="el">Greek</option>
<option value="grc">Greek, Ancient</option>
<option value="he">Hebrew</option>
<option value="hu">Hungarian</option>
<option value="is">Icelandic</option>
<option value="ilo">Iloko</option>
<option value="ia">Interlingua</option>
<option value="iu">Inuktitut</option>
<option value="ga">Irish</option>
<option value="it">Italian</option>
<option value="ja">Japanese</option>
<option value="csb">Kashubian</option>
<option value="kha">Khasi</option>
<option value="ko">Korean</option>
<option value="la">Latin</option>
<option value="lt">Lithuanian</option>
<option value="mi">Maori</option>
<option value="myn">Mayan Languages</option>
<option value="enm">Middle English</option>
<option value="nah">Nahuatl</option>
<option value="nap">Napoletano-Calabrese</option>
<option value="nav">Navajo</option>
<option value="nai">North American Indian</option>
<option value="no">Norwegian</option>
<option value="oc">Occitan</option>
<option value="oji">Ojibwa</option>
<option value="ang">Old English</option>
<option value="pl">Polish</option>
<option value="pt">Portuguese</option>
<option value="ro">Romanian</option>
<option value="ru">Russian</option>
<option value="sa">Sanskrit</option>
<option value="sr">Serbian</option>
<option value="sl">Slovenian</option>
<option value="es">Spanish</option>
<option value="sv">Swedish</option>
<option value="bgs">Tagabawa</option>
<option value="tl">Tagalog</option>
<option value="te">Telugu</option>
<option value="cy">Welsh</option>
<option value="yi">Yiddish</option>
</select>
</p>
<p>
<label for="category" accesskey="c">Category:</label>
<select id="category" name="category" title="Category (Book Count)">
<option selected="" value="">Any</option>
<option value="1">Audio Book, human-read</option>
<option value="2">Audio Book, computer-generated</option>
<option value="3">Music, recorded</option>
<option value="4">Music, Sheet</option>
<option value="5">Pictures, still</option>
<option value="6">Other recordings</option>
<option value="7">Pictures, moving</option>
<option value="8">Data</option>
<option value="9">Compilations</option>
</select>
</p>
<p>
<label for="locc" accesskey="o">LoCC:</label>
<select id="locc" name="locc" title="Please choose a Library of Congress Class.">
<option selected="" value="">Any</option>
<option value="AC">AC General Works: Collections, Series, Collected works, Pamphlets</option>
<option value="AE">AE General Works: Encyclopedias</option>
<option value="AG">AG General Works: Dictionaries and other general reference books</option>
<option value="AM">AM General Works: Museums, Collectors and collecting</option>
<option value="AP">AP General Works: Periodicals</option>
<option value="AS">AS General Works: Academies and International Associations, Congresses</option>
<option value="AY">AY General Works: Yearbooks, Almanacs, Directories</option>
<option value="AZ">AZ General Works: History of scholarship and learning, The humanities</option>
<option value="B">B Philosophy, Psychology, Religion</option>
<option value="BC">BC Philosophy, Psychology, Religion: Logic</option>
<option value="BD">BD Philosophy, Psychology, Religion: Speculative Philosophy, General Philosophical works</option>
<option value="BF">BF Philosophy, Psychology, Religion: Psychology, Philosophy, Psychoanalysis</option>
<option value="BH">BH Philosophy, Psychology, Religion: Aesthetics</option>
<option value="BJ">BJ Philosophy, Psychology, Religion: Ethics, Social usages, Etiquette, Religion</option>
<option value="BL">BL Philosophy, Psychology, Religion: Religion: General, Miscellaneous and Atheism</option>
<option value="BM">BM Philosophy, Psychology, Religion: Judaism</option>
<option value="BP">BP Philosophy, Psychology, Religion: Islam, Bahaism, Theosophy, Other and new beliefs</option>
<option value="BQ">BQ Philosophy, Psychology, Religion: Buddhism</option>
<option value="BR">BR Philosophy, Psychology, Religion: Christianity</option>
<option value="BS">BS Philosophy, Psychology, Religion: Christianity: The Bible, Old and New Testament</option>
<option value="BT">BT Philosophy, Psychology, Religion: Christianity: Doctrinal theology, God, Christology</option>
<option value="BV">BV Philosophy, Psychology, Religion: Christianity: Practical theology, Worship</option>
<option value="BX">BX Philosophy, Psychology, Religion: Christianity: Churches, Church movements</option>
<option value="CB">CB History: History of civilization</option>
<option value="CC">CC History: Archaeology</option>
<option value="CE">CE History: Technical Chronology, Calendar</option>
<option value="CJ">CJ History: Numismatics</option>
<option value="CN">CN History: Inscriptions, Epigraphy</option>
<option value="CR">CR History: Heraldry</option>
<option value="CS">CS History: Genealogy</option>
<option value="CT">CT History: Biography</option>
<option value="D">D History: General and Eastern Hemisphere</option>
<option value="D501">D501 History: General and Eastern Hemisphere: World War I</option>
<option value="D731">D731 History: General and Eastern Hemisphere: World War II</option>
<option value="DA">DA History: General and Eastern Hemisphere: Great Britain, Ireland, Central Europe</option>
<option value="DB">DB History: General and Eastern Hemisphere: Austria, Hungary, Czech Republic, Slovakia</option>
<option value="DC">DC History: General and Eastern Hemisphere: France, Andorra, Monaco</option>
<option value="DD">DD History: General and Eastern Hemisphere: Germany</option>
<option value="DE">DE History: General and Eastern Hemisphere: The Mediterranean Region, The Greco-Roman World</option>
<option value="DF">DF History: General and Eastern Hemisphere: Greece</option>
<option value="DG">DG History: General and Eastern Hemisphere: Italy, Vatican City, Malta</option>
<option value="DH">DH History: General and Eastern Hemisphere: Netherlands, Belgium, Luxemburg</option>
<option value="DJ">DJ History: General and Eastern Hemisphere: Netherlands</option>
<option value="DJK">DJK History: General and Eastern Hemisphere: Eastern Europe</option>
<option value="DK">DK History: General and Eastern Hemisphere: Russia, Former Soviet Republics, Poland</option>
<option value="DL">DL History: General and Eastern Hemisphere: Northern Europe, Scandinavia</option>
<option value="DP">DP History: General and Eastern Hemisphere: Spain, Portugal</option>
<option value="DQ">DQ History: General and Eastern Hemisphere: Switzerland</option>
<option value="DR">DR History: General and Eastern Hemisphere: Balkan Peninsula, Turkey</option>
<option value="DS">DS History: General and Eastern Hemisphere: Asia</option>
<option value="DT">DT History: General and Eastern Hemisphere: Africa</option>
<option value="DU">DU History: General and Eastern Hemisphere: History of Oceania (South Seas)</option>
<option value="DX">DX History: General and Eastern Hemisphere: History of Romanies</option>
<option value="E011">E011 History: America: America</option>
<option value="E151">E151 History: America: United States</option>
<option value="E186">E186 History: America: Colonial History</option>
<option value="E201">E201 History: America: Revolution</option>
<option value="E300">E300 History: America: Revolution to the Civil War</option>
<option value="E456">E456 History: America: Civil War period</option>
<option value="E660">E660 History: America: Late nineteenth century</option>
<option value="E740">E740 History: America: Twentieth century</option>
<option value="E838">E838 History: America: Later twentieth century</option>
<option value="E895">E895 History: America: Twenty-first century</option>
<option value="F001">F001 United States local history: New England</option>
<option value="F1001">F1001 North America local history: Canada</option>
<option value="F106">F106 United States local history: Atlantic coast. Middle Atlantic States</option>
<option value="F1201">F1201 North America local history: Mexico</option>
<option value="F1401">F1401 Latin America local history: General</option>
<option value="F1461">F1461 Latin America local history: Guatemala</option>
<option value="F1481">F1481 Latin America local history: El Salvador</option>
<option value="F1501">F1501 Latin America local history: Honduras</option>
<option value="F1521">F1521 Latin America local history: Nicaragua</option>
<option value="F1541">F1541 Latin America local history: Costa Rica</option>
<option value="F1561">F1561 Latin America local history: Panama</option>
<option value="F1601">F1601 History of the Americas: West Indies</option>
<option value="F1751">F1751 History of the Americas: West Indies. Cuba</option>
<option value="F1861">F1861 History of the Americas: West Indies. Jamaica</option>
<option value="F1900">F1900 West Indies local history: Hispaniola (Haiti and Dominican Republic)</option>
<option value="F1951">F1951 West Indies local history: Puerto Rico</option>
<option value="F2001">F2001 History of the Americas: Lesser Antilles</option>
<option value="F206">F206 United States local history: The South. South Atlantic States</option>
<option value="F2131">F2131 History of the Americas: West Indies. British West Indies</option>
<option value="F2155">F2155 History of the Americas: Caribbean area. Caribbean sea</option>
<option value="F2201">F2201 Latin America local history: South America. General</option>
<option value="F2251">F2251 Latin America local history: Colombia</option>
<option value="F2301">F2301 Latin America local history: Venezuela</option>
<option value="F2351">F2351 Latin America local history: Guiana</option>
<option value="F2501">F2501 Latin America local history: Brazil</option>
<option value="F2661">F2661 Latin America local history: Paraguay</option>
<option value="F2701">F2701 Latin America local history: Uruguay</option>
<option value="F2801">F2801 Latin America local history: Argentina</option>
<option value="F296">F296 United States local history: Gulf States. West Florida</option>
<option value="F3051">F3051 Latin America local history: Chile</option>
<option value="F3301">F3301 Latin America local history: Bolivia</option>
<option value="F3401">F3401 Latin America local history: Peru</option>
<option value="F350.5">F350.5 United States local history: Mississippi River and Valley. Middle West</option>
<option value="F3701">F3701 Latin America local history: Ecuador</option>
<option value="F396">F396 United States local history: Old Southwest. Lower Mississippi Valley</option>
<option value="F476">F476 United States local history: Old Northwest. Northwest Territory</option>
<option value="F516">F516 United States local history: Ohio River and Valley.</option>
<option value="F590.3">F590.3 United States local history: The West. Trans-Mississippi Region. Great Plains</option>
<option value="F721">F721 United States local history: Rocky Mountains. Yellowstone National Park</option>
<option value="F786">F786 United States local history: New Southwest. Colorado River, Canyon, and Valley</option>
<option value="F850.5">F850.5 United States local history: Pacific States</option>
<option value="F975">F975 United States local history: Central American, West Indian, and other countries protected by and having close political affiliations with the United States</option>
<option value="G">G Geography, Anthropology, Recreation</option>
<option value="GA">GA Geography, Anthropology, Recreation: Mathematical geography, Cartography</option>
<option value="GB">GB Geography, Anthropology, Recreation: Physical geography</option>
<option value="GC">GC Geography, Anthropology, Recreation: Oceanography</option>
<option value="GF">GF Geography, Anthropology, Recreation: Human ecology, Anthropogeography</option>
<option value="GN">GN Geography, Anthropology, Recreation: Anthropology</option>
<option value="GR">GR Geography, Anthropology, Recreation: Folklore</option>
<option value="GT">GT Geography, Anthropology, Recreation: Manners and customs</option>
<option value="GV">GV Geography, Anthropology, Recreation: Recreation, Leisure</option>
<option value="H">H Social sciences</option>
<option value="HA">HA Social sciences: Statistics</option>
<option value="HB">HB Social sciences: Economic theory, Demography</option>
<option value="HC">HC Social sciences: Economic history and conditions, Special topics</option>
<option value="HD">HD Social sciences: Economic history and conditions, Production</option>
<option value="HE">HE Social sciences: Transportation and communications</option>
<option value="HF">HF Social sciences: Commerce</option>
<option value="HG">HG Social sciences: Finance</option>
<option value="HJ">HJ Social sciences: Public finance</option>
<option value="HM">HM Social sciences: Sociology</option>
<option value="HN">HN Social sciences: Social history and conditions, Social problems</option>
<option value="HQ">HQ Social sciences: The family, Marriage, Sex and Gender</option>
<option value="HS">HS Social sciences: Societies: secret, benevolent, etc.</option>
<option value="HT">HT Social sciences: Communities, Classes, Races</option>
<option value="HV">HV Social sciences: Social pathology, Social and Public Welfare</option>
<option value="HX">HX Social sciences: Socialism, Communism, Anarchism</option>
<option value="J">J Political science</option>
<option value="JA">JA Political science: Political science</option>
<option value="JC">JC Political science: Political theory</option>
<option value="JF">JF Political science: Political institutions and public administration</option>
<option value="JK">JK Political science: Political inst. and pub. Admin.: United States</option>
<option value="JL">JL Political science: Political inst. and pub. Admin.: America</option>
<option value="JN">JN Political science: Political inst. and pub. Admin.: Europe</option>
<option value="JQ">JQ Political science: Political inst. and pub. Admin.: Asia, Africa and Oceania</option>
<option value="JS">JS Political science: Local government, Municipal government</option>
<option value="JV">JV Political science: Colonies and colonization, International migration</option>
<option value="JX">JX Political science: International law</option>
<option value="JZ">JZ Political science: International relations</option>
<option value="K">K Law in general, Comparative and uniform law, Jurisprudence</option>
<option value="KBM">KBM Law in general, Comparative and uniform law, Jurisprudence: Jewish law</option>
<option value="KBR">KBR Law in general, Comparative and uniform law, Jurisprudence: History of canon law</option>
<option value="KD">KD Law in general, Comparative and uniform law, Jurisprudence: United Kingdom and Ireland</option>
<option value="KDZ">KDZ Law in general, Comparative and uniform law, Jurisprudence: America, North America</option>
<option value="KE">KE Law in general, Comparative and uniform law, Jurisprudence: Canada</option>
<option value="KF">KF Law in general, Comparative and uniform law, Jurisprudence: United States</option>
<option value="KH">KH Law in general, Comparative and uniform law, Jurisprudence: South America</option>
<option value="KJ">KJ Law in general, Comparative and uniform law, Jurisprudence: Europe</option>
<option value="KL">KL Law in general, Comparative and uniform law, Jurisprudence: Asia and Eurasia, Africa, Pacific Area, and Antarctica</option>
<option value="KN">KN Law in general, Comparative and uniform law, Jurisprudence: South Asia, Southeast Asia, East Asia</option>
<option value="KNX">KNX Law in general, Comparative and uniform law, Jurisprudence: Japan</option>
<option value="KP">KP Law in general, Comparative and uniform law, Jurisprudence: South Asia, Southeast Asia, East Asia</option>
<option value="KZ">KZ Law in general, Comparative and uniform law, Jurisprudence: Law of nations</option>
<option value="L">L Education</option>
<option value="LA">LA Education: History of education</option>
<option value="LB">LB Education: Theory and practice of education</option>
<option value="LC">LC Education: Special aspects of education</option>
<option value="LD">LD Education: Individual institutions: United States</option>
<option value="LE">LE Education: Individual institutions: America (except US)</option>
<option value="LF">LF Education: Individual institutions: Europe</option>
<option value="LH">LH Education: College and school magazines and papers</option>
<option value="LT">LT Education: Textbooks</option>
<option value="M">M Music</option>
<option value="ML">ML Music: Literature of music</option>
<option value="MT">MT Music: Musical instruction and study, Composition</option>
<option value="N">N Fine Arts</option>
<option value="NA">NA Fine Arts: Architecture</option>
<option value="NB">NB Fine Arts: Sculpture</option>
<option value="NC">NC Fine Arts: Drawing, Design, Illustration</option>
<option value="ND">ND Fine Arts: Painting</option>
<option value="NE">NE Fine Arts: Print media</option>
<option value="NK">NK Fine Arts: Decorative and Applied Arts, Decoration and Ornament</option>
<option value="NX">NX Fine Arts: Arts in general</option>
<option value="P">P Language and Literatures</option>
<option value="PA">PA Language and Literatures: Classical Languages and Literature</option>
<option value="PB">PB Language and Literatures: General works</option>
<option value="PC">PC Language and Literatures: Romance languages: Italian, French, Spanish, Portuguese</option>
<option value="PD">PD Language and Literatures: Germanic and Scandinavian languages</option>
<option value="PE">PE Language and Literatures: English</option>
<option value="PF">PF Language and Literatures: West Germanic</option>
<option value="PG">PG Language and Literatures: Slavic (including Russian), Languages and Literature</option>
<option value="PH">PH Language and Literatures: Finno-Ugrian and Basque languages and literatures</option>
<option value="PJ">PJ Language and Literatures: Oriental languages and literatures</option>
<option value="PK">PK Language and Literatures: Indo-Iranian literatures</option>
<option value="PL">PL Language and Literatures: Languages and literatures of Eastern Asia, Africa, Oceania</option>
<option value="PM">PM Language and Literatures: Indigenous American and Artificial Languages</option>
<option value="PN">PN Language and Literatures: Literature: General, Criticism, Collections</option>
<option value="PQ">PQ Language and Literatures: Romance literatures: French, Italian, Spanish, Portuguese</option>
<option value="PR">PR Language and Literatures: English literature</option>
<option value="PS">PS Language and Literatures: American and Canadian literature</option>
<option value="PT">PT Language and Literatures: Germanic, Scandinavian, and Icelandic literatures</option>
<option value="PZ">PZ Language and Literatures: Juvenile belles lettres</option>
<option value="Q">Q Science</option>
<option value="QA">QA Science: Mathematics</option>
<option value="QB">QB Science: Astronomy</option>
<option value="QC">QC Science: Physics</option>
<option value="QD">QD Science: Chemistry</option>
<option value="QE">QE Science: Geology</option>
<option value="QH">QH Science: Natural history</option>
<option value="QH301">QH301 Science: Biology</option>
<option value="QK">QK Science: Botany</option>
<option value="QL">QL Science: Zoology</option>
<option value="QM">QM Science: Human anatomy</option>
<option value="QP">QP Science: Physiology</option>
<option value="QR">QR Science: Microbiology</option>
<option value="R">R Medicine</option>
<option value="RA">RA Medicine: Public aspects of medicine</option>
<option value="RB">RB Medicine: Pathology</option>
<option value="RC">RC Medicine: Internal medicine</option>
<option value="RD">RD Medicine: Surgery</option>
<option value="RE">RE Medicine: Ophthalmology</option>
<option value="RF">RF Medicine: Otorhinolaryngology</option>
<option value="RG">RG Medicine: Gynecology and obstetrics</option>
<option value="RJ">RJ Medicine: Pediatrics</option>
<option value="RK">RK Medicine: Dentistry</option>
<option value="RL">RL Medicine: Dermatology</option>
<option value="RM">RM Medicine: Therapeutics, Pharmacology</option>
<option value="RS">RS Medicine: Pharmacy and materia medica</option>
<option value="RT">RT Medicine: Nursing</option>
<option value="RV">RV Medicine: Botanic, Thomsonian, and eclectic medicine</option>
<option value="RX">RX Medicine: Homeopathy</option>
<option value="RZ">RZ Medicine: Other systems of medicine</option>
<option value="S">S Agriculture</option>
<option value="SB">SB Agriculture: Plant culture</option>
<option value="SD">SD Agriculture: Forestry</option>
<option value="SF">SF Agriculture: Animal culture</option>
<option value="SH">SH Agriculture: Aquaculture, Fisheries, Angling</option>
<option value="SK">SK Agriculture: Hunting sports</option>
<option value="T">T Technology</option>
<option value="TA">TA Technology: Engineering and Civil engineering</option>
<option value="TC">TC Technology: Ocean engineering</option>
<option value="TD">TD Technology: Environmental technology, Sanitary engineering</option>
<option value="TE">TE Technology: Highway engineering, Roads and pavements</option>
<option value="TF">TF Technology: Railroad engineering and operation</option>
<option value="TG">TG Technology: Bridge engineering</option>
<option value="TH">TH Technology: Building construction</option>
<option value="TJ">TJ Technology: Mechanical engineering and machinery</option>
<option value="TK">TK Technology: Electrical, Electronics and Nuclear engineering</option>
<option value="TL">TL Technology: Motor vehicles, Aeronautics, Astronautics</option>
<option value="TN">TN Technology: Mining engineering, Metallurgy</option>
<option value="TP">TP Technology: Chemical technology</option>
<option value="TR">TR Technology: Photography</option>
<option value="TS">TS Technology: Manufactures</option>
<option value="TT">TT Technology: Handicrafts, Arts and crafts</option>
<option value="TX">TX Technology: Home economics</option>
<option value="U">U Military science</option>
<option value="UA">UA Military science: Armies: Organization, distribution, military situation</option>
<option value="UB">UB Military science: Military administration</option>
<option value="UC">UC Military science: Maintenance and transportation</option>
<option value="UD">UD Military science: Infantry</option>
<option value="UE">UE Military science: Cavalry, Armor</option>
<option value="UF">UF Military science: Artillery</option>
<option value="UG">UG Military science: Military engineering</option>
<option value="UH">UH Military science: Other services</option>
<option value="V">V Naval science</option>
<option value="VA">VA Naval science: Navies: Organization, distribution, naval situation</option>
<option value="VB">VB Naval science: Naval administration</option>
<option value="VE">VE Naval science: Marines</option>
<option value="VF">VF Naval science: Naval ordnance</option>
<option value="VG">VG Naval science: Minor services of navies</option>
<option value="VK">VK Naval science: Navigation, Merchant marine</option>
<option value="VM">VM Naval science: Naval architecture, Shipbuilding, Marine engineering</option>
<option value="Z">Z Bibliography, Library science</option>
</select>
</p>
<p>
<label for="filetype" accesskey="f">Filetype:</label>
<select id="filetype" name="filetype" title="Please choose a file type.">
<option selected="" value="">Any</option>
<option value="readme">Readme (readme)</option>
<option value="license">License (license)</option>
<option value="index">Audio Book Index (index)</option>
<option value="html">HTML (html)</option>
<option value="html.gen">Generated HTML (html.gen)</option>
<option value="html.noimages">Generated HTML (no images) (html.noimages)</option>
<option value="html.images">Generated HTML (with images) (html.images)</option>
<option value="iso">ISO CD/DVD Image (iso)</option>
<option value="epub.dp">EPUB (hand-crafted) (epub.dp)</option>
<option value="epub.noimages">EPUB (no images) (epub.noimages)</option>
<option value="epub.images">EPUB (with images) (epub.images)</option>
<option value="pdf.gen">Generated PDF (pdf.gen)</option>
<option value="pdf.noimages">Generated PDF (no images) (pdf.noimages)</option>
<option value="pdf.images">Generated PDF (with images) (pdf.images)</option>
<option value="kindle.noimages">Kindle (no images) (kindle.noimages)</option>
<option value="kindle.images">Kindle (with images) (kindle.images)</option>
<option value="md5">MD5 Checksum (md5)</option>
<option value="iso.split">Part of ISO CD/DVD Image (iso.split)</option>
<option value="pdf">PDF (pdf)</option>
<option value="css">CSS Stylesheet (css)</option>
<option value="eps">Encapsulated PostScript (eps)</option>
<option value="mus">Finale (mus)</option>
<option value="fen">ForsythEdwards Notation (fen)</option>
<option value="gif">GIF Picture (gif)</option>
<option value="jpg">JPEG Picture (jpg)</option>
<option value="ly">LilyPond (ly)</option>
<option value="mid">MIDI (mid)</option>
<option value="mpg">MPEG Video (mpg)</option>
<option value="lit">MS Lit for PocketPC (lit)</option>
<option value="rtf">MS Rich Text Format (rtf)</option>
<option value="avi">MS Video (avi)</option>
<option value="wav">MS Wave Audio (wav)</option>
<option value="doc">MS Word Document (doc)</option>
<option value="ogg">Ogg Vorbis Audio (ogg)</option>
<option value="pdb">Palm Database (pdb)</option>
<option value="prc">Palm Database (prc)</option>
<option value="plucker">Plucker (plucker)</option>
<option value="png">PNG Picture (png)</option>
<option value="ps">PostScript (ps)</option>
<option value="ps2">PostScript Level 2 (ps2)</option>
<option value="qioo">QiOO Mobile (qioo)</option>
<option value="mov">Quicktime Video (mov)</option>
<option value="qt">Quicktime Video (qt)</option>
<option value="sib">Sibelius (sib)</option>
<option value="svg">SVG (svg)</option>
<option value="dvi">TeX Device Independent (dvi)</option>
<option value="tiff">TIFF Picture (tiff)</option>
<option value="tr">Tome Raider (tr)</option>
<option value="xsl">XSLT Stylesheet (xsl)</option>
<option value="m4b">Apple iTunes Audiobook (m4b)</option>
<option value="m4a">Apple iTunes Audiobook (m4a)</option>
<option value="mp4">MPEG 4 Part 14 (mp4)</option>
<option value="mp3">MP3 Audio (mp3)</option>
<option value="spx">Speex Audio (spx)</option>
<option value="txt.utf-8">Plain Text UTF-8 (txt.utf-8)</option>
<option value="txt">Plain Text (txt)</option>
<option value="aac">AAC (Advanced Audio Coding) (aac)</option>
<option value="flv">Flash Video (flv)</option>
<option value="xls">Microsoft Excel (xls)</option>
<option value="nfo">Proprietary `Folio' format (nfo)</option>
<option value="pageimages">Raw Page Images (pageimages)</option>
<option value="rdf">RDF (rdf)</option>
<option value="rst.gen">reStructuredText (rst.gen)</option>
<option value="tei">TEI Text Encoding Initiative (tei)</option>
<option value="tex">TeX (tex)</option>
<option value="wma">Windows Media Audio (wma)</option>
<option value="xml">XML (xml)</option>
<option value="rst">reStructuredText (rst)</option>
<option value="cover.medium">Cover Medium (cover.medium)</option>
<option value="cover.small">Cover Thumbnail (cover.small)</option>
<option value="rst.master">reStructuredText Master (rst.master)</option>
<option value="?">Unspecified (?)</option>
</select>
</p>
<p>
<input type="submit" id="submit" name="submit_search" value="Search" />
</p>
</div>
</div>
<!-- Advanced search form ends here -->
</form>
<a class="button" href="#popup4">Help</a><input id="collapsible5" class="toggle" type="checkbox" /> <label for="collapsible5" class="lbl-toggle">Browsing Options </label>
<div class="collapsible-content">
<div class="content-inner">
<div class="pgdbnavbar">
<p>Authors:
<a href="/browse/authors/a">A</a>&nbsp;
<a href="/browse/authors/b">B</a>&nbsp;
<a href="/browse/authors/c">C</a>&nbsp;
<a href="/browse/authors/d">D</a>&nbsp;
<a href="/browse/authors/e">E</a>&nbsp;
<a href="/browse/authors/f">F</a>&nbsp;
<a href="/browse/authors/g">G</a>&nbsp;
<a href="/browse/authors/h">H</a>&nbsp;
<a href="/browse/authors/i">I</a>&nbsp;
<a href="/browse/authors/j">J</a>&nbsp;
<a href="/browse/authors/k">K</a>&nbsp;
<a href="/browse/authors/l">L</a>&nbsp;
<a href="/browse/authors/m">M</a>&nbsp;
<a href="/browse/authors/n">N</a>&nbsp;
<a href="/browse/authors/o">O</a>&nbsp;
<a href="/browse/authors/p">P</a>&nbsp;
<a href="/browse/authors/q">Q</a>&nbsp;
<a href="/browse/authors/r">R</a>&nbsp;
<a href="/browse/authors/s">S</a>&nbsp;
<a href="/browse/authors/t">T</a>&nbsp;
<a href="/browse/authors/u">U</a>&nbsp;
<a href="/browse/authors/v">V</a>&nbsp;
<a href="/browse/authors/w">W</a>&nbsp;
<a href="/browse/authors/x">X</a>&nbsp;
<a href="/browse/authors/y">Y</a>&nbsp;
<a href="/browse/authors/z">Z</a>&nbsp;
<a href="/browse/authors/other">other</a>&nbsp;
</p>
<p>Titles:
<a href="/browse/titles/a">A</a>&nbsp;
<a href="/browse/titles/b">B</a>&nbsp;
<a href="/browse/titles/c">C</a>&nbsp;
<a href="/browse/titles/d">D</a>&nbsp;
<a href="/browse/titles/e">E</a>&nbsp;
<a href="/browse/titles/f">F</a>&nbsp;
<a href="/browse/titles/g">G</a>&nbsp;
<a href="/browse/titles/h">H</a>&nbsp;
<a href="/browse/titles/i">I</a>&nbsp;
<a href="/browse/titles/j">J</a>&nbsp;
<a href="/browse/titles/k">K</a>&nbsp;
<a href="/browse/titles/l">L</a>&nbsp;
<a href="/browse/titles/m">M</a>&nbsp;
<a href="/browse/titles/n">N</a>&nbsp;
<a href="/browse/titles/o">O</a>&nbsp;
<a href="/browse/titles/p">P</a>&nbsp;
<a href="/browse/titles/q">Q</a>&nbsp;
<a href="/browse/titles/r">R</a>&nbsp;
<a href="/browse/titles/s">S</a>&nbsp;
<a href="/browse/titles/t">T</a>&nbsp;
<a href="/browse/titles/u">U</a>&nbsp;
<a href="/browse/titles/v">V</a>&nbsp;
<a href="/browse/titles/w">W</a>&nbsp;
<a href="/browse/titles/x">X</a>&nbsp;
<a href="/browse/titles/y">Y</a>&nbsp;
<a href="/browse/titles/z">Z</a>&nbsp;
<a href="/browse/titles/other">other</a>&nbsp;
</p>
<p>Languages with more than 50 books:
<a href="/browse/languages/zh" title="Chinese (441)">Chinese</a>&nbsp;
<a href="/browse/languages/da" title="Danish (68)">Danish</a>&nbsp;
<a href="/browse/languages/nl" title="Dutch (800)">Dutch</a>&nbsp;
<a href="/browse/languages/en" title="English (48426)">English</a>&nbsp;
<a href="/browse/languages/eo" title="Esperanto (118)">Esperanto</a>&nbsp;
<a href="/browse/languages/fi" title="Finnish (2006)">Finnish</a>&nbsp;
<a href="/browse/languages/fr" title="French (2964)">French</a>&nbsp;
<a href="/browse/languages/de" title="German (1756)">German</a>&nbsp;
<a href="/browse/languages/el" title="Greek (220)">Greek</a>&nbsp;
<a href="/browse/languages/hu" title="Hungarian (183)">Hungarian</a>&nbsp;
<a href="/browse/languages/it" title="Italian (759)">Italian</a>&nbsp;
<a href="/browse/languages/la" title="Latin (122)">Latin</a>&nbsp;
<a href="/browse/languages/pt" title="Portuguese (552)">Portuguese</a>&nbsp;
<a href="/browse/languages/es" title="Spanish (630)">Spanish</a>&nbsp;
<a href="/browse/languages/sv" title="Swedish (193)">Swedish</a>&nbsp;
<a href="/browse/languages/tl" title="Tagalog (60)">Tagalog</a>&nbsp;
</p>
<p>Languages with up to 50 books:
<a href="/browse/languages/af" title="Afrikaans (4)">Afrikaans</a>&nbsp;
<a href="/browse/languages/ale" title="Aleut (1)">Aleut</a>&nbsp;
<a href="/browse/languages/ar" title="Arabic (1)">Arabic</a>&nbsp;
<a href="/browse/languages/arp" title="Arapaho (2)">Arapaho</a>&nbsp;
<a href="/browse/languages/brx" title="Bodo (2)">Bodo</a>&nbsp;
<a href="/browse/languages/br" title="Breton (1)">Breton</a>&nbsp;
<a href="/browse/languages/bg" title="Bulgarian (6)">Bulgarian</a>&nbsp;
<a href="/browse/languages/rmr" title="Caló (1)">Caló</a>&nbsp;
<a href="/browse/languages/ca" title="Catalan (33)">Catalan</a>&nbsp;
<a href="/browse/languages/ceb" title="Cebuano (3)">Cebuano</a>&nbsp;
<a href="/browse/languages/cs" title="Czech (10)">Czech</a>&nbsp;
<a href="/browse/languages/et" title="Estonian (1)">Estonian</a>&nbsp;
<a href="/browse/languages/fa" title="Farsi (1)">Farsi</a>&nbsp;
<a href="/browse/languages/fy" title="Frisian (2)">Frisian</a>&nbsp;
<a href="/browse/languages/fur" title="Friulian (7)">Friulian</a>&nbsp;
<a href="/browse/languages/gla" title="Gaelic, Scottish (2)">Gaelic, Scottish</a>&nbsp;
<a href="/browse/languages/gl" title="Galician (2)">Galician</a>&nbsp;
<a href="/browse/languages/kld" title="Gamilaraay (1)">Gamilaraay</a>&nbsp;
<a href="/browse/languages/grc" title="Greek, Ancient (3)">Greek, Ancient</a>&nbsp;
<a href="/browse/languages/he" title="Hebrew (6)">Hebrew</a>&nbsp;
<a href="/browse/languages/is" title="Icelandic (7)">Icelandic</a>&nbsp;
<a href="/browse/languages/ilo" title="Iloko (3)">Iloko</a>&nbsp;
<a href="/browse/languages/ia" title="Interlingua (1)">Interlingua</a>&nbsp;
<a href="/browse/languages/iu" title="Inuktitut (1)">Inuktitut</a>&nbsp;
<a href="/browse/languages/ga" title="Irish (2)">Irish</a>&nbsp;
<a href="/browse/languages/ja" title="Japanese (22)">Japanese</a>&nbsp;
<a href="/browse/languages/csb" title="Kashubian (1)">Kashubian</a>&nbsp;
<a href="/browse/languages/kha" title="Khasi (1)">Khasi</a>&nbsp;
<a href="/browse/languages/ko" title="Korean (1)">Korean</a>&nbsp;
<a href="/browse/languages/lt" title="Lithuanian (1)">Lithuanian</a>&nbsp;
<a href="/browse/languages/mi" title="Maori (2)">Maori</a>&nbsp;
<a href="/browse/languages/myn" title="Mayan Languages (2)">Mayan Languages</a>&nbsp;
<a href="/browse/languages/enm" title="Middle English (6)">Middle English</a>&nbsp;
<a href="/browse/languages/nah" title="Nahuatl (3)">Nahuatl</a>&nbsp;
<a href="/browse/languages/nap" title="Napoletano-Calabrese (1)">Napoletano-Calabrese</a>&nbsp;
<a href="/browse/languages/nav" title="Navajo (3)">Navajo</a>&nbsp;
<a href="/browse/languages/nai" title="North American Indian (3)">North American Indian</a>&nbsp;
<a href="/browse/languages/no" title="Norwegian (19)">Norwegian</a>&nbsp;
<a href="/browse/languages/oc" title="Occitan (1)">Occitan</a>&nbsp;
<a href="/browse/languages/oji" title="Ojibwa (1)">Ojibwa</a>&nbsp;
<a href="/browse/languages/ang" title="Old English (4)">Old English</a>&nbsp;
<a href="/browse/languages/pl" title="Polish (31)">Polish</a>&nbsp;
<a href="/browse/languages/ro" title="Romanian (2)">Romanian</a>&nbsp;
<a href="/browse/languages/ru" title="Russian (9)">Russian</a>&nbsp;
<a href="/browse/languages/sa" title="Sanskrit (1)">Sanskrit</a>&nbsp;
<a href="/browse/languages/sr" title="Serbian (4)">Serbian</a>&nbsp;
<a href="/browse/languages/sl" title="Slovenian (1)">Slovenian</a>&nbsp;
<a href="/browse/languages/bgs" title="Tagabawa (1)">Tagabawa</a>&nbsp;
<a href="/browse/languages/te" title="Telugu (6)">Telugu</a>&nbsp;
<a href="/browse/languages/cy" title="Welsh (13)">Welsh</a>&nbsp;
<a href="/browse/languages/yi" title="Yiddish (1)">Yiddish</a>&nbsp;
</p>
<p>Special Categories:
<a href="/browse/categories/2" title="Audio Book, computer-generated (370)">Audio Book, computer-generated</a>&nbsp;
<a href="/browse/categories/1" title="Audio Book, human-read (576)">Audio Book, human-read</a>&nbsp;
<a href="/browse/categories/9" title="Compilations (3)">Compilations</a>&nbsp;
<a href="/browse/categories/8" title="Data (87)">Data</a>&nbsp;
<a href="/browse/categories/3" title="Music, recorded (137)">Music, recorded</a>&nbsp;
<a href="/browse/categories/4" title="Music, Sheet (33)">Music, Sheet</a>&nbsp;
<a href="/browse/categories/6" title="Other recordings (31)">Other recordings</a>&nbsp;
<a href="/browse/categories/7" title="Pictures, moving (8)">Pictures, moving</a>&nbsp;
<a href="/browse/categories/5" title="Pictures, still (3)">Pictures, still</a>&nbsp;
</p>
<p>Recent:
<a href="/browse/recent/last1">last 24 hours</a>&nbsp;
<a href="/browse/recent/last7">last 7 days</a>&nbsp;
<a href="/browse/recent/last30">last 30 days</a>&nbsp;
</p>
</div>
</div>
</div>
</div>

View File

@ -31,7 +31,7 @@ Gutenberg metadata much faster than by scraping.
old_header = os.entries[0].header # suppress first header as already in <h1>
def help_page (s = ''):
s = s.replace (' ', '_')
return '%s#%s' % ('/wiki/Gutenberg:Help_on_Bibliographic_Record_Page', s)
return '%s#%s' % ('/help/bibliographic_record.html', s)
def explain (s):
return _('Explain {topic}.').format (topic = _(s))
def _ (s):
@ -66,8 +66,7 @@ Gutenberg metadata much faster than by scraping.
<body>
<div class="container">
${site_top()}
<xi:include href="menu.html" />
<div class="page_content" id="content" itemscope="itemscope" itemtype="http://schema.org/Book" i18n:comment="On the 'bibrec' page.">
<div class="breadcrumbs noprint">
@ -182,9 +181,6 @@ ${site_top()}
title="Send to Google Drive." rel="nofollow"><span class="icon icon_gdrive" /></a>
</td>
<td class="noprint">
<a py:if="file_.honeypot_url"
href="${file_.honeypot_url}"
title="Send to MegaUpload." rel="nofollow" />
<a py:if="file_.msdrive_url"
href="${file_.msdrive_url}"
title="Send to OneDrive." rel="nofollow"><span class="icon icon_msdrive" /></a>

View File

@ -13,28 +13,22 @@
<head>
<style>
.icon { background: transparent url(/pics/sprite.png?${cherrypy.config['css_mtime']}) 0 0 no-repeat; }
.icon { background: transparent url(/pics/sprite.png) 0 0 no-repeat; }
</style>
<link rel="stylesheet" type="text/css"
href="/gutenberg/pg-desktop-one.css?${cherrypy.config['css_mtime']}" />
<link rel="stylesheet" type="text/css"
href="/gutenberg/new_nav.css?${cherrypy.config['css_mtime']}"/>
<link rel="stylesheet" type="text/css"
href="/gutenberg/style.css?${cherrypy.config['css_mtime']}"/>
<link rel="stylesheet" type="text/css" href="/gutenberg/pg-desktop-one.css" />
<link rel="stylesheet" type="text/css" href="/gutenberg/new_nav.css"/>
<link rel="stylesheet" type="text/css" href="/gutenberg/style.css"/>
<script type="text/javascript">//<![CDATA[
//<![CDATA[
var json_search = "/ebooks/suggest/";
var canonical_url = "https://www.gutenberg.org/ebooks/";
var lang = "en";
var fb_lang = "en_US"; /* FB accepts only xx_XX */
var msg_load_more = "Load More Results…";
var page_mode = "screen";
var dialog_title = "";
var dialog_message = "";
//]]></script>
<script type="text/javascript"
src="/js/pg-desktop-one.js?${cherrypy.config['js_mtime']}" />
<script type="text/javascript" src="/js/pg-desktop-one.js" />
<link rel="shortcut icon" href="/gutenberg/favicon.ico" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
@ -45,7 +39,7 @@
</head>
<body>
<div class="container">
${site_top()}
<xi:include href="menu.html" />
<div id="page_content" i18n:comment="error page." style="margin-top: 4em">
<h1>${os.message}</h1>

View File

@ -134,7 +134,7 @@ which contains *all* Project Gutenberg metadata in one RDF/XML file.
${site_footer ()}
${site_top ()}
<xi:include href="menu.html" />
</body>
</html>

View File

@ -12,30 +12,24 @@
?>
<py:def function="site_head">
<style >
.icon { background: transparent url(/pics/sprite.png?${cherrypy.config['css_mtime']}) 0 0 no-repeat; }
.icon { background: transparent url(/pics/sprite.png) 0 0 no-repeat; }
</style>
<link rel="stylesheet" type="text/css"
href="/gutenberg/pg-desktop-one.css?${cherrypy.config['css_mtime']}" />
<link rel="stylesheet" type="text/css"
href="/gutenberg/new_nav.css?${cherrypy.config['css_mtime']}"/>
<link rel="stylesheet" type="text/css"
href="/gutenberg/style.css?${cherrypy.config['css_mtime']}"/>
<link rel="stylesheet" type="text/css" href="/gutenberg/pg-desktop-one.css" />
<link rel="stylesheet" type="text/css" href="/gutenberg/new_nav.css"/>
<link rel="stylesheet" type="text/css" href="/gutenberg/style.css"/>
<!--! IE8 does not recognize application/javascript -->
<script>//<![CDATA[
var json_search = "${os.json_search}";
var canonical_url = "${os.canonical_url}";
var lang = "${os.lang}";
var fb_lang = "${os.fb_lang}"; /* FB accepts only xx_XX */
var msg_load_more = "${_('Load More Results…')}";
var page_mode = "${os.page_mode}";
var dialog_title = "${os.user_dialog[1]}";
var dialog_message = "${os.user_dialog[0]}";
//]]></script>
<script
src="/js/pg-desktop-one.js?${cherrypy.config['js_mtime']}" />
<script src="/js/pg-desktop-one.js" />
<link rel="shortcut icon" href="/gutenberg/favicon.ico" />
<link rel="canonical" href="${os.canonical_url}" />
@ -117,10 +111,6 @@
</div>
</py:def>
<py:def function="site_top">
<xi:include href="menu.html" />
</py:def>
<py:def function="site_footer">
<div class="footer" i18n:comment="On the footer of every page.">
<xi:include href="footer.html" />