mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Implement a check setup command that uses PyFlakes to check for various errors
This commit is contained in:
parent
792c6b0b22
commit
f9ff180347
@ -1,5 +1,5 @@
|
||||
*_ui.py
|
||||
moc_*.cpp
|
||||
.check-cache.pickle
|
||||
src/calibre/plugins
|
||||
resources/images.qrc
|
||||
src/calibre/manual/.build/
|
||||
|
3
setup.py
3
setup.py
@ -6,7 +6,6 @@ __license__ = 'GPL v3'
|
||||
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
|
||||
import sys, os, optparse
|
||||
|
||||
sys.path.insert(0, os.path.abspath(os.path.dirname(__file__)))
|
||||
@ -70,7 +69,7 @@ def main(args=sys.argv):
|
||||
command.clean()
|
||||
return 0
|
||||
|
||||
if opts.clean_all():
|
||||
if opts.clean_all:
|
||||
for cmd in commands.__all__:
|
||||
prints('Cleaning', cmd)
|
||||
getattr(commands, cmd).clean()
|
||||
|
75
setup/check.py
Normal file
75
setup/check.py
Normal file
@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env python
|
||||
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
|
||||
from __future__ import with_statement
|
||||
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import sys, os, cPickle, subprocess
|
||||
from operator import attrgetter
|
||||
from setup import Command
|
||||
|
||||
def check_for_python_errors(filename, builtins):
|
||||
from pyflakes import checker, ast
|
||||
|
||||
contents = open(filename, 'rb').read()
|
||||
|
||||
try:
|
||||
tree = ast.parse(contents, filename)
|
||||
except:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
try:
|
||||
value = sys.exc_info()[1]
|
||||
lineno, offset, line = value[1][1:]
|
||||
except IndexError:
|
||||
lineno, offset, line = 1, 0, ''
|
||||
if line.endswith("\n"):
|
||||
line = line[:-1]
|
||||
|
||||
return [SyntaxError(filename, lineno, offset, str(value))]
|
||||
else:
|
||||
w = checker.Checker(tree, filename, builtins = builtins)
|
||||
w.messages.sort(key = attrgetter('lineno'))
|
||||
return w.messages
|
||||
|
||||
|
||||
class Check(Command):
|
||||
|
||||
BUILTINS = ['_', '__', 'dynamic_property', 'I', 'P']
|
||||
CACHE = '.check-cache.pickle'
|
||||
|
||||
def run(self, opts):
|
||||
cache = {}
|
||||
if os.path.exists(self.CACHE):
|
||||
cache = cPickle.load(open(self.CACHE, 'rb'))
|
||||
for x in os.walk(self.j(self.SRC, 'calibre')):
|
||||
for f in x[-1]:
|
||||
f = self.j(x[0], f)
|
||||
mtime = os.stat(f).st_mtime
|
||||
if f.endswith('.py') and cache.get(f, 0) != mtime and \
|
||||
self.b(f) not in ('ptempfile.py', 'feedparser.py',
|
||||
'pyparsing.py', 'markdown.py') and 'genshi' not in f and \
|
||||
'prs500/driver.py' not in f:
|
||||
self.info('\tChecking', f)
|
||||
w = check_for_python_errors(f, self.BUILTINS)
|
||||
if w:
|
||||
self.report_errors(w)
|
||||
cPickle.dump(cache, open(self.CACHE, 'wb'), -1)
|
||||
subprocess.call(['gvim', '-f', f])
|
||||
raise SystemExit(1)
|
||||
cache[f] = mtime
|
||||
cPickle.dump(cache, open(self.CACHE, 'wb'), -1)
|
||||
|
||||
|
||||
def report_errors(self, errors):
|
||||
for err in errors:
|
||||
if isinstance(err, SyntaxError):
|
||||
print '\t\tSyntax Error'
|
||||
else:
|
||||
col = getattr(err, 'col', 0) if getattr(err, 'col', 0) else 0
|
||||
lineno = err.lineno if err.lineno else 0
|
||||
self.info('\t\t%d:%d:'%(lineno, col),
|
||||
err.message%err.message_args)
|
||||
|
@ -11,6 +11,7 @@ __all__ = [
|
||||
'build',
|
||||
'gui',
|
||||
'develop',
|
||||
'check',
|
||||
]
|
||||
|
||||
|
||||
@ -29,6 +30,8 @@ develop = Develop()
|
||||
from setup.gui import GUI
|
||||
gui = GUI()
|
||||
|
||||
from setup.check import Check
|
||||
check = Check()
|
||||
|
||||
commands = {}
|
||||
for x in __all__:
|
||||
|
@ -78,9 +78,10 @@ class GUI(Command):
|
||||
dat = pat.sub(sub, dat)
|
||||
|
||||
if form.endswith('viewer%smain.ui'%os.sep):
|
||||
self.inf('\t\tPromoting WebView')
|
||||
self.info('\t\tPromoting WebView')
|
||||
dat = dat.replace('self.view = QtWebKit.QWebView(', 'self.view = DocumentView(')
|
||||
dat += '\n\nfrom calibre.gui2.viewer.documentview import DocumentView'
|
||||
dat += '\nQtWebKit'
|
||||
|
||||
open(compiled_form, 'wb').write(dat)
|
||||
|
||||
|
@ -21,6 +21,11 @@ from calibre.constants import iswindows, isosx, islinux, isfrozen, \
|
||||
filesystem_encoding
|
||||
import mechanize
|
||||
|
||||
if False:
|
||||
winutil, winutilerror, __appname__, islinux, __version__
|
||||
fcntl, win32event, isfrozen, __author__, terminal_controller
|
||||
winerror, win32api
|
||||
|
||||
mimetypes.add_type('application/epub+zip', '.epub')
|
||||
mimetypes.add_type('text/x-sony-bbeb+xml', '.lrs')
|
||||
mimetypes.add_type('application/xhtml+xml', '.xhtml')
|
||||
|
@ -25,7 +25,7 @@
|
||||
# 02110-1301 USA
|
||||
######################### END LICENSE BLOCK #########################
|
||||
|
||||
from constants import eStart, eError, eItsMe
|
||||
from constants import eStart
|
||||
|
||||
class CodingStateMachine:
|
||||
def __init__(self, sm):
|
||||
|
@ -25,7 +25,7 @@
|
||||
# 02110-1301 USA
|
||||
######################### END LICENSE BLOCK #########################
|
||||
|
||||
import constants, sys
|
||||
import constants
|
||||
from escsm import HZSMModel, ISO2022CNSMModel, ISO2022JPSMModel, ISO2022KRSMModel
|
||||
from charsetprober import CharSetProber
|
||||
from codingstatemachine import CodingStateMachine
|
||||
|
@ -26,7 +26,7 @@
|
||||
# 02110-1301 USA
|
||||
######################### END LICENSE BLOCK #########################
|
||||
|
||||
import constants, sys
|
||||
import constants
|
||||
from charsetgroupprober import CharSetGroupProber
|
||||
from sbcharsetprober import SingleByteCharSetProber
|
||||
from langcyrillicmodel import Win1251CyrillicModel, Koi8rModel, Latin5CyrillicModel, MacCyrillicModel, Ibm866Model, Ibm855Model
|
||||
|
@ -25,7 +25,7 @@
|
||||
# 02110-1301 USA
|
||||
######################### END LICENSE BLOCK #########################
|
||||
|
||||
import constants, sys
|
||||
import constants
|
||||
from constants import eStart, eError, eItsMe
|
||||
from charsetprober import CharSetProber
|
||||
from codingstatemachine import CodingStateMachine
|
||||
|
@ -8,11 +8,10 @@ __license__ = 'GPL v3'
|
||||
__copyright__ = '2008, Marshall T. Vandegrift <llasram@gmail.com>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import os, re
|
||||
from itertools import count, chain
|
||||
from calibre.ebooks.oeb.base import XHTML, XHTML_NS
|
||||
import re
|
||||
from itertools import count
|
||||
from calibre.ebooks.oeb.base import XHTML_NS
|
||||
from calibre.ebooks.oeb.base import OEBBook
|
||||
from lxml import etree, html
|
||||
from lxml.etree import XPath
|
||||
|
||||
NSMAP = {'h': XHTML_NS, 'html': XHTML_NS, 'xhtml': XHTML_NS}
|
||||
@ -55,5 +54,5 @@ def add_page_map(opfpath, opts):
|
||||
id = elem.attrib['id'] = idgen.next()
|
||||
href = '#'.join((item.href, id))
|
||||
oeb.pages.add(name, href)
|
||||
writer = DirWriter(version='2.0', page_map=True)
|
||||
writer = None#DirWriter(version='2.0', page_map=True)
|
||||
writer.dump(oeb, opfpath)
|
||||
|
@ -6,7 +6,6 @@ from __future__ import with_statement
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2008, Marshall T. Vandegrift <llasram@gmail.com>'
|
||||
|
||||
import sys
|
||||
from calibre import plugins
|
||||
|
||||
_lzx, _error = plugins['lzx']
|
||||
|
@ -7,3 +7,5 @@ Microsoft LIT tag and attribute tables.
|
||||
|
||||
from calibre.ebooks.lit.maps.opf import MAP as OPF_MAP
|
||||
from calibre.ebooks.lit.maps.html import MAP as HTML_MAP
|
||||
|
||||
OPF_MAP, HTML_MAP
|
||||
|
@ -1,11 +1,11 @@
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
import sys, os
|
||||
from calibre import iswindows
|
||||
import os
|
||||
from calibre.ptempfile import PersistentTemporaryFile
|
||||
|
||||
try:
|
||||
from PIL import ImageFont
|
||||
ImageFont
|
||||
except ImportError:
|
||||
import ImageFont
|
||||
|
||||
|
@ -10,7 +10,7 @@ from calibre.ebooks.lrf.lrfparser import LRFDocument
|
||||
from calibre.ebooks.metadata.opf import OPFCreator
|
||||
|
||||
from calibre.ebooks.lrf.objects import PageAttr, BlockAttr, TextAttr
|
||||
|
||||
from calibre.ebooks.lrf.pylrs.pylrs import TextStyle
|
||||
|
||||
class BlockStyle(object):
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
pylrf.py -- very low level interface to create lrf files. See pylrs for
|
||||
higher level interface that can use this module to render books to lrf.
|
||||
"""
|
||||
|
||||
import struct
|
||||
import zlib
|
||||
import StringIO
|
||||
|
@ -41,6 +41,7 @@ from xml.sax.saxutils import escape
|
||||
from datetime import date
|
||||
try:
|
||||
from elementtree.ElementTree import (Element, SubElement)
|
||||
Element, SubElement
|
||||
except ImportError:
|
||||
from xml.etree.ElementTree import (Element, SubElement)
|
||||
|
||||
|
@ -3,3 +3,5 @@
|
||||
from calibre.ebooks.markdown import mdx_footnotes
|
||||
from calibre.ebooks.markdown import mdx_tables
|
||||
from calibre.ebooks.markdown import mdx_toc
|
||||
|
||||
mdx_footnotes, mdx_tables, mdx_toc
|
||||
|
@ -8,8 +8,6 @@ My markdown extensions for adding:
|
||||
Table of Contents (aka toc)
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
import markdown
|
||||
|
||||
|
@ -2,7 +2,7 @@ __license__ = 'GPL v3'
|
||||
__copyright__ = '2008, Ashish Kulkarni <kulkarni.ashish@gmail.com>'
|
||||
'''Read meta information from IMP files'''
|
||||
|
||||
import sys, os
|
||||
import sys
|
||||
|
||||
from calibre.ebooks.metadata import MetaInformation, string_to_authors
|
||||
|
||||
|
@ -7,7 +7,7 @@ __docformat__ = 'restructuredtext en'
|
||||
Read metadata from LRX files
|
||||
'''
|
||||
|
||||
import sys, struct
|
||||
import struct
|
||||
from zlib import decompress
|
||||
from lxml import etree
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
import zipfile, sys, re
|
||||
import zipfile, re
|
||||
import xml.sax.saxutils
|
||||
from cStringIO import StringIO
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
'''
|
||||
Writer content to palmdoc pdb file.
|
||||
'''
|
||||
import os
|
||||
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2009, John Schember <john@nachtimwald.com>'
|
||||
|
@ -4,7 +4,6 @@ __license__ = 'GPL v3'
|
||||
__copyright__ = '2009, John Schember <john@nachtimwald.com>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import os
|
||||
|
||||
class zTXTError(Exception):
|
||||
pass
|
||||
|
@ -12,8 +12,6 @@ Decrypt content of PDF.
|
||||
import os, sys
|
||||
from optparse import OptionGroup, Option
|
||||
|
||||
from calibre.ebooks.metadata.meta import metadata_from_formats
|
||||
from calibre.ebooks.metadata import authors_to_string
|
||||
from calibre.utils.config import OptionParser
|
||||
from calibre.utils.logging import Log
|
||||
from calibre.constants import preferred_encoding
|
||||
@ -36,7 +34,7 @@ OPTIONS = set([
|
||||
|
||||
class DecryptionError(Exception):
|
||||
def __init__(self, pdf_path):
|
||||
self.value = 'Unable to decrypt file `%s`.' % value
|
||||
self.value = 'Unable to decrypt file `%s`.' % pdf_path
|
||||
|
||||
def __str__(self):
|
||||
return repr(self.value)
|
||||
|
@ -17,6 +17,8 @@ from calibre.utils.logging import Log
|
||||
from calibre.constants import preferred_encoding
|
||||
from calibre.customize.conversion import OptionRecommendation
|
||||
from calibre.ebooks.pdf.verify import is_valid_pdf, is_encrypted
|
||||
from calibre.ebooks.metadata import authors_to_string
|
||||
from calibre.ebooks.metadata.meta import metadata_from_formats
|
||||
|
||||
from pyPdf import PdfFileWriter, PdfFileReader
|
||||
|
||||
|
@ -11,7 +11,7 @@ Verify PDF files.
|
||||
|
||||
import os
|
||||
|
||||
from pyPdf import PdfFileWriter, PdfFileReader
|
||||
from pyPdf import PdfFileReader
|
||||
|
||||
def is_valid_pdf(pdf_path):
|
||||
'''
|
||||
|
@ -4,7 +4,6 @@ __license__ = 'GPL 3'
|
||||
__copyright__ = '2009, John Schember <john@nachtimwald.com>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import os
|
||||
import struct
|
||||
import zlib
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
# #
|
||||
# #
|
||||
#########################################################################
|
||||
import sys, os, shutil
|
||||
import os, shutil
|
||||
|
||||
class Copy:
|
||||
"""Copy each changed file to a directory for debugging purposes"""
|
||||
|
@ -1,5 +1,4 @@
|
||||
import sys
|
||||
from calibre.ebooks import rtf2xml
|
||||
class ParseOptions:
|
||||
"""
|
||||
Requires:
|
||||
|
@ -16,7 +16,6 @@
|
||||
# #
|
||||
#########################################################################
|
||||
import sys, os, codecs
|
||||
from calibre.ebooks import rtf2xml
|
||||
class Output:
|
||||
"""
|
||||
Output file
|
||||
|
@ -15,8 +15,6 @@
|
||||
# #
|
||||
# #
|
||||
#########################################################################
|
||||
import sys,os
|
||||
from calibre.ebooks import rtf2xml
|
||||
class OverrideTable:
|
||||
"""
|
||||
Parse a line of text to make the override table. Return a string
|
||||
|
@ -23,5 +23,3 @@ class ChooseFormatDialog(QDialog, Ui_ChooseFormatDialog):
|
||||
|
||||
def format(self):
|
||||
return self._formats[self.formats.currentRow()]
|
||||
|
||||
|
@ -8,7 +8,7 @@ __docformat__ = 'restructuredtext en'
|
||||
import os, math, re
|
||||
from PyQt4.Qt import QWidget, QSize, QSizePolicy, QUrl, SIGNAL, Qt, QTimer, \
|
||||
QPainter, QPalette, QBrush, QFontDatabase, QDialog, \
|
||||
QByteArray, QColor, QWheelEvent, QPoint, QImage, QRegion, \
|
||||
QByteArray, QColor, QPoint, QImage, QRegion, \
|
||||
QFont, QObject, QApplication, pyqtSignature
|
||||
from PyQt4.QtWebKit import QWebPage, QWebView, QWebSettings
|
||||
|
||||
|
@ -4,17 +4,14 @@ __license__ = 'GPL v3'
|
||||
__copyright__ = '2009, John Schember <john@nachtimwald.com>'
|
||||
|
||||
|
||||
import os, sys, traceback, urlparse
|
||||
import os, sys, urlparse
|
||||
|
||||
from BeautifulSoup import BeautifulSoup, Tag
|
||||
|
||||
from calibre.ebooks.oeb.iterator import EbookIterator
|
||||
from calibre.ptempfile import TemporaryDirectory
|
||||
|
||||
from PyQt4 import QtCore
|
||||
from PyQt4.Qt import QUrl, QEventLoop, SIGNAL, QObject, QApplication, Qt, \
|
||||
QPrinter, QPrintPreviewDialog, QPrintDialog, QDialog, QMetaObject, Q_ARG
|
||||
from PyQt4 import QtCore
|
||||
from PyQt4.QtWebKit import QWebView
|
||||
|
||||
PRINTCSS = 'body{width:100%;margin:0;padding:0;font-family:Arial;color:#000;background:none;font-size:12pt;text-align:left;}h1,h2,h3,h4,h5,h6{font-family:Helvetica;}h1{font-size:19pt;}h2{font-size:17pt;}h3{font-size:15pt;}h4,h5,h6{font-size:12pt;}pre,code,samp{font:10ptCourier,monospace;white-space:pre-wrap;page-break-inside:avoid;}blockquote{margin:1.3em;padding:1em;font-size:10pt;}hr{background-color:#ccc;}aimg{border:none;}a:link,a:visited{background:transparent;font-weight:700;text-decoration:underline;color:#333;}a:link:after,a{color:#000;}table{margin:1px;text-align:left;}th{border-bottom:1pxsolid#333;font-weight:bold;}td{border-bottom:1pxsolid#333;}th,td{padding:4px10px4px0;}tfoot{font-style:italic;}caption{background:#fff;margin-bottom:2em;text-align:left;}thead{display:table-header-group;}tr{page-break-inside:avoid;}#header,.header,#footer,.footer,#navbar,.navbar,#navigation,.navigation,#rightSideBar,.rightSideBar,#leftSideBar,.leftSideBar{display:none;}'
|
||||
|
@ -18,7 +18,7 @@ sys.path.append(os.path.abspath('../../../'))
|
||||
sys.path.append(os.path.abspath('.'))
|
||||
from calibre import __appname__, __version__
|
||||
import custom
|
||||
|
||||
custom
|
||||
# General configuration
|
||||
# ---------------------
|
||||
|
||||
|
@ -1,970 +0,0 @@
|
||||
""" path.py - An object representing a path to a file or directory.
|
||||
|
||||
Example:
|
||||
|
||||
from path import path
|
||||
d = path('/home/guido/bin')
|
||||
for f in d.files('*.py'):
|
||||
f.chmod(0755)
|
||||
|
||||
This module requires Python 2.2 or later.
|
||||
|
||||
|
||||
URL: http://www.jorendorff.com/articles/python/path
|
||||
Author: Jason Orendorff <jason.orendorff\x40gmail\x2ecom> (and others - see the url!)
|
||||
Date: 9 Mar 2007
|
||||
"""
|
||||
|
||||
|
||||
# TODO
|
||||
# - Tree-walking functions don't avoid symlink loops. Matt Harrison
|
||||
# sent me a patch for this.
|
||||
# - Bug in write_text(). It doesn't support Universal newline mode.
|
||||
# - Better error message in listdir() when self isn't a
|
||||
# directory. (On Windows, the error message really sucks.)
|
||||
# - Make sure everything has a good docstring.
|
||||
# - Add methods for regex find and replace.
|
||||
# - guess_content_type() method?
|
||||
# - Perhaps support arguments to touch().
|
||||
|
||||
from __future__ import generators
|
||||
|
||||
import sys, warnings, os, fnmatch, glob, shutil, codecs, hashlib
|
||||
|
||||
__version__ = '2.2'
|
||||
__all__ = ['path']
|
||||
|
||||
# Platform-specific support for path.owner
|
||||
if os.name == 'nt':
|
||||
try:
|
||||
import win32security
|
||||
except ImportError:
|
||||
win32security = None
|
||||
else:
|
||||
try:
|
||||
import pwd
|
||||
except ImportError:
|
||||
pwd = None
|
||||
|
||||
# Pre-2.3 support. Are unicode filenames supported?
|
||||
_base = str
|
||||
_getcwd = os.getcwd
|
||||
try:
|
||||
if os.path.supports_unicode_filenames:
|
||||
_base = unicode
|
||||
_getcwd = os.getcwdu
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
# Pre-2.3 workaround for booleans
|
||||
try:
|
||||
True, False
|
||||
except NameError:
|
||||
True, False = 1, 0
|
||||
|
||||
# Pre-2.3 workaround for basestring.
|
||||
try:
|
||||
basestring
|
||||
except NameError:
|
||||
basestring = (str, unicode)
|
||||
|
||||
# Universal newline support
|
||||
_textmode = 'r'
|
||||
if hasattr(file, 'newlines'):
|
||||
_textmode = 'U'
|
||||
|
||||
|
||||
class TreeWalkWarning(Warning):
|
||||
pass
|
||||
|
||||
class path(_base):
|
||||
""" Represents a filesystem path.
|
||||
|
||||
For documentation on individual methods, consult their
|
||||
counterparts in os.path.
|
||||
"""
|
||||
|
||||
# --- Special Python methods.
|
||||
|
||||
def __repr__(self):
|
||||
return 'path(%s)' % _base.__repr__(self)
|
||||
|
||||
# Adding a path and a string yields a path.
|
||||
def __add__(self, more):
|
||||
try:
|
||||
resultStr = _base.__add__(self, more)
|
||||
except TypeError: #Python bug
|
||||
resultStr = NotImplemented
|
||||
if resultStr is NotImplemented:
|
||||
return resultStr
|
||||
return self.__class__(resultStr)
|
||||
|
||||
def __radd__(self, other):
|
||||
if isinstance(other, basestring):
|
||||
return self.__class__(other.__add__(self))
|
||||
else:
|
||||
return NotImplemented
|
||||
|
||||
# The / operator joins paths.
|
||||
def __div__(self, rel):
|
||||
""" fp.__div__(rel) == fp / rel == fp.joinpath(rel)
|
||||
|
||||
Join two path components, adding a separator character if
|
||||
needed.
|
||||
"""
|
||||
return self.__class__(os.path.join(self, rel))
|
||||
|
||||
# Make the / operator work even when true division is enabled.
|
||||
__truediv__ = __div__
|
||||
|
||||
def getcwd(cls):
|
||||
""" Return the current working directory as a path object. """
|
||||
return cls(_getcwd())
|
||||
getcwd = classmethod(getcwd)
|
||||
|
||||
|
||||
# --- Operations on path strings.
|
||||
|
||||
isabs = os.path.isabs
|
||||
def abspath(self): return self.__class__(os.path.abspath(self))
|
||||
def normcase(self): return self.__class__(os.path.normcase(self))
|
||||
def normpath(self): return self.__class__(os.path.normpath(self))
|
||||
def realpath(self): return self.__class__(os.path.realpath(self))
|
||||
def expanduser(self): return self.__class__(os.path.expanduser(self))
|
||||
def expandvars(self): return self.__class__(os.path.expandvars(self))
|
||||
def dirname(self): return self.__class__(os.path.dirname(self))
|
||||
basename = os.path.basename
|
||||
|
||||
def expand(self):
|
||||
""" Clean up a filename by calling expandvars(),
|
||||
expanduser(), and normpath() on it.
|
||||
|
||||
This is commonly everything needed to clean up a filename
|
||||
read from a configuration file, for example.
|
||||
"""
|
||||
return self.expandvars().expanduser().normpath()
|
||||
|
||||
def _get_namebase(self):
|
||||
base, ext = os.path.splitext(self.name)
|
||||
return base
|
||||
|
||||
def _get_ext(self):
|
||||
f, ext = os.path.splitext(_base(self))
|
||||
return ext
|
||||
|
||||
def _get_drive(self):
|
||||
drive, r = os.path.splitdrive(self)
|
||||
return self.__class__(drive)
|
||||
|
||||
parent = property(
|
||||
dirname, None, None,
|
||||
""" This path's parent directory, as a new path object.
|
||||
|
||||
For example, path('/usr/local/lib/libpython.so').parent == path('/usr/local/lib')
|
||||
""")
|
||||
|
||||
name = property(
|
||||
basename, None, None,
|
||||
""" The name of this file or directory without the full path.
|
||||
|
||||
For example, path('/usr/local/lib/libpython.so').name == 'libpython.so'
|
||||
""")
|
||||
|
||||
namebase = property(
|
||||
_get_namebase, None, None,
|
||||
""" The same as path.name, but with one file extension stripped off.
|
||||
|
||||
For example, path('/home/guido/python.tar.gz').name == 'python.tar.gz',
|
||||
but path('/home/guido/python.tar.gz').namebase == 'python.tar'
|
||||
""")
|
||||
|
||||
ext = property(
|
||||
_get_ext, None, None,
|
||||
""" The file extension, for example '.py'. """)
|
||||
|
||||
drive = property(
|
||||
_get_drive, None, None,
|
||||
""" The drive specifier, for example 'C:'.
|
||||
This is always empty on systems that don't use drive specifiers.
|
||||
""")
|
||||
|
||||
def splitpath(self):
|
||||
""" p.splitpath() -> Return (p.parent, p.name). """
|
||||
parent, child = os.path.split(self)
|
||||
return self.__class__(parent), child
|
||||
|
||||
def splitdrive(self):
|
||||
""" p.splitdrive() -> Return (p.drive, <the rest of p>).
|
||||
|
||||
Split the drive specifier from this path. If there is
|
||||
no drive specifier, p.drive is empty, so the return value
|
||||
is simply (path(''), p). This is always the case on Unix.
|
||||
"""
|
||||
drive, rel = os.path.splitdrive(self)
|
||||
return self.__class__(drive), rel
|
||||
|
||||
def splitext(self):
|
||||
""" p.splitext() -> Return (p.stripext(), p.ext).
|
||||
|
||||
Split the filename extension from this path and return
|
||||
the two parts. Either part may be empty.
|
||||
|
||||
The extension is everything from '.' to the end of the
|
||||
last path segment. This has the property that if
|
||||
(a, b) == p.splitext(), then a + b == p.
|
||||
"""
|
||||
filename, ext = os.path.splitext(self)
|
||||
return self.__class__(filename), ext
|
||||
|
||||
def stripext(self):
|
||||
""" p.stripext() -> Remove one file extension from the path.
|
||||
|
||||
For example, path('/home/guido/python.tar.gz').stripext()
|
||||
returns path('/home/guido/python.tar').
|
||||
"""
|
||||
return self.splitext()[0]
|
||||
|
||||
if hasattr(os.path, 'splitunc'):
|
||||
def splitunc(self):
|
||||
unc, rest = os.path.splitunc(self)
|
||||
return self.__class__(unc), rest
|
||||
|
||||
def _get_uncshare(self):
|
||||
unc, r = os.path.splitunc(self)
|
||||
return self.__class__(unc)
|
||||
|
||||
uncshare = property(
|
||||
_get_uncshare, None, None,
|
||||
""" The UNC mount point for this path.
|
||||
This is empty for paths on local drives. """)
|
||||
|
||||
def joinpath(self, *args):
|
||||
""" Join two or more path components, adding a separator
|
||||
character (os.sep) if needed. Returns a new path
|
||||
object.
|
||||
"""
|
||||
return self.__class__(os.path.join(self, *args))
|
||||
|
||||
def splitall(self):
|
||||
r""" Return a list of the path components in this path.
|
||||
|
||||
The first item in the list will be a path. Its value will be
|
||||
either os.curdir, os.pardir, empty, or the root directory of
|
||||
this path (for example, '/' or 'C:\\'). The other items in
|
||||
the list will be strings.
|
||||
|
||||
path.path.joinpath(*result) will yield the original path.
|
||||
"""
|
||||
parts = []
|
||||
loc = self
|
||||
while loc != os.curdir and loc != os.pardir:
|
||||
prev = loc
|
||||
loc, child = prev.splitpath()
|
||||
if loc == prev:
|
||||
break
|
||||
parts.append(child)
|
||||
parts.append(loc)
|
||||
parts.reverse()
|
||||
return parts
|
||||
|
||||
def relpath(self):
|
||||
""" Return this path as a relative path,
|
||||
based from the current working directory.
|
||||
"""
|
||||
cwd = self.__class__(os.getcwd())
|
||||
return cwd.relpathto(self)
|
||||
|
||||
def relpathto(self, dest):
|
||||
""" Return a relative path from self to dest.
|
||||
|
||||
If there is no relative path from self to dest, for example if
|
||||
they reside on different drives in Windows, then this returns
|
||||
dest.abspath().
|
||||
"""
|
||||
origin = self.abspath()
|
||||
dest = self.__class__(dest).abspath()
|
||||
|
||||
orig_list = origin.normcase().splitall()
|
||||
# Don't normcase dest! We want to preserve the case.
|
||||
dest_list = dest.splitall()
|
||||
|
||||
if orig_list[0] != os.path.normcase(dest_list[0]):
|
||||
# Can't get here from there.
|
||||
return dest
|
||||
|
||||
# Find the location where the two paths start to differ.
|
||||
i = 0
|
||||
for start_seg, dest_seg in zip(orig_list, dest_list):
|
||||
if start_seg != os.path.normcase(dest_seg):
|
||||
break
|
||||
i += 1
|
||||
|
||||
# Now i is the point where the two paths diverge.
|
||||
# Need a certain number of "os.pardir"s to work up
|
||||
# from the origin to the point of divergence.
|
||||
segments = [os.pardir] * (len(orig_list) - i)
|
||||
# Need to add the diverging part of dest_list.
|
||||
segments += dest_list[i:]
|
||||
if len(segments) == 0:
|
||||
# If they happen to be identical, use os.curdir.
|
||||
relpath = os.curdir
|
||||
else:
|
||||
relpath = os.path.join(*segments)
|
||||
return self.__class__(relpath)
|
||||
|
||||
# --- Listing, searching, walking, and matching
|
||||
|
||||
def listdir(self, pattern=None):
|
||||
""" D.listdir() -> List of items in this directory.
|
||||
|
||||
Use D.files() or D.dirs() instead if you want a listing
|
||||
of just files or just subdirectories.
|
||||
|
||||
The elements of the list are path objects.
|
||||
|
||||
With the optional 'pattern' argument, this only lists
|
||||
items whose names match the given pattern.
|
||||
"""
|
||||
names = os.listdir(self)
|
||||
if pattern is not None:
|
||||
names = fnmatch.filter(names, pattern)
|
||||
return [self / child for child in names]
|
||||
|
||||
def dirs(self, pattern=None):
|
||||
""" D.dirs() -> List of this directory's subdirectories.
|
||||
|
||||
The elements of the list are path objects.
|
||||
This does not walk recursively into subdirectories
|
||||
(but see path.walkdirs).
|
||||
|
||||
With the optional 'pattern' argument, this only lists
|
||||
directories whose names match the given pattern. For
|
||||
example, d.dirs('build-*').
|
||||
"""
|
||||
return [p for p in self.listdir(pattern) if p.isdir()]
|
||||
|
||||
def files(self, pattern=None):
|
||||
""" D.files() -> List of the files in this directory.
|
||||
|
||||
The elements of the list are path objects.
|
||||
This does not walk into subdirectories (see path.walkfiles).
|
||||
|
||||
With the optional 'pattern' argument, this only lists files
|
||||
whose names match the given pattern. For example,
|
||||
d.files('*.pyc').
|
||||
"""
|
||||
|
||||
return [p for p in self.listdir(pattern) if p.isfile()]
|
||||
|
||||
def walk(self, pattern=None, errors='strict'):
|
||||
""" D.walk() -> iterator over files and subdirs, recursively.
|
||||
|
||||
The iterator yields path objects naming each child item of
|
||||
this directory and its descendants. This requires that
|
||||
D.isdir().
|
||||
|
||||
This performs a depth-first traversal of the directory tree.
|
||||
Each directory is returned just before all its children.
|
||||
|
||||
The errors= keyword argument controls behavior when an
|
||||
error occurs. The default is 'strict', which causes an
|
||||
exception. The other allowed values are 'warn', which
|
||||
reports the error via warnings.warn(), and 'ignore'.
|
||||
"""
|
||||
if errors not in ('strict', 'warn', 'ignore'):
|
||||
raise ValueError("invalid errors parameter")
|
||||
|
||||
try:
|
||||
childList = self.listdir()
|
||||
except Exception:
|
||||
if errors == 'ignore':
|
||||
return
|
||||
elif errors == 'warn':
|
||||
warnings.warn(
|
||||
"Unable to list directory '%s': %s"
|
||||
% (self, sys.exc_info()[1]),
|
||||
TreeWalkWarning)
|
||||
return
|
||||
else:
|
||||
raise
|
||||
|
||||
for child in childList:
|
||||
if pattern is None or child.fnmatch(pattern):
|
||||
yield child
|
||||
try:
|
||||
isdir = child.isdir()
|
||||
except Exception:
|
||||
if errors == 'ignore':
|
||||
isdir = False
|
||||
elif errors == 'warn':
|
||||
warnings.warn(
|
||||
"Unable to access '%s': %s"
|
||||
% (child, sys.exc_info()[1]),
|
||||
TreeWalkWarning)
|
||||
isdir = False
|
||||
else:
|
||||
raise
|
||||
|
||||
if isdir:
|
||||
for item in child.walk(pattern, errors):
|
||||
yield item
|
||||
|
||||
def walkdirs(self, pattern=None, errors='strict'):
|
||||
""" D.walkdirs() -> iterator over subdirs, recursively.
|
||||
|
||||
With the optional 'pattern' argument, this yields only
|
||||
directories whose names match the given pattern. For
|
||||
example, mydir.walkdirs('*test') yields only directories
|
||||
with names ending in 'test'.
|
||||
|
||||
The errors= keyword argument controls behavior when an
|
||||
error occurs. The default is 'strict', which causes an
|
||||
exception. The other allowed values are 'warn', which
|
||||
reports the error via warnings.warn(), and 'ignore'.
|
||||
"""
|
||||
if errors not in ('strict', 'warn', 'ignore'):
|
||||
raise ValueError("invalid errors parameter")
|
||||
|
||||
try:
|
||||
dirs = self.dirs()
|
||||
except Exception:
|
||||
if errors == 'ignore':
|
||||
return
|
||||
elif errors == 'warn':
|
||||
warnings.warn(
|
||||
"Unable to list directory '%s': %s"
|
||||
% (self, sys.exc_info()[1]),
|
||||
TreeWalkWarning)
|
||||
return
|
||||
else:
|
||||
raise
|
||||
|
||||
for child in dirs:
|
||||
if pattern is None or child.fnmatch(pattern):
|
||||
yield child
|
||||
for subsubdir in child.walkdirs(pattern, errors):
|
||||
yield subsubdir
|
||||
|
||||
def walkfiles(self, pattern=None, errors='strict'):
|
||||
""" D.walkfiles() -> iterator over files in D, recursively.
|
||||
|
||||
The optional argument, pattern, limits the results to files
|
||||
with names that match the pattern. For example,
|
||||
mydir.walkfiles('*.tmp') yields only files with the .tmp
|
||||
extension.
|
||||
"""
|
||||
if errors not in ('strict', 'warn', 'ignore'):
|
||||
raise ValueError("invalid errors parameter")
|
||||
|
||||
try:
|
||||
childList = self.listdir()
|
||||
except Exception:
|
||||
if errors == 'ignore':
|
||||
return
|
||||
elif errors == 'warn':
|
||||
warnings.warn(
|
||||
"Unable to list directory '%s': %s"
|
||||
% (self, sys.exc_info()[1]),
|
||||
TreeWalkWarning)
|
||||
return
|
||||
else:
|
||||
raise
|
||||
|
||||
for child in childList:
|
||||
try:
|
||||
isfile = child.isfile()
|
||||
isdir = not isfile and child.isdir()
|
||||
except:
|
||||
if errors == 'ignore':
|
||||
continue
|
||||
elif errors == 'warn':
|
||||
warnings.warn(
|
||||
"Unable to access '%s': %s"
|
||||
% (self, sys.exc_info()[1]),
|
||||
TreeWalkWarning)
|
||||
continue
|
||||
else:
|
||||
raise
|
||||
|
||||
if isfile:
|
||||
if pattern is None or child.fnmatch(pattern):
|
||||
yield child
|
||||
elif isdir:
|
||||
for f in child.walkfiles(pattern, errors):
|
||||
yield f
|
||||
|
||||
def fnmatch(self, pattern):
|
||||
""" Return True if self.name matches the given pattern.
|
||||
|
||||
pattern - A filename pattern with wildcards,
|
||||
for example '*.py'.
|
||||
"""
|
||||
return fnmatch.fnmatch(self.name, pattern)
|
||||
|
||||
def glob(self, pattern):
|
||||
""" Return a list of path objects that match the pattern.
|
||||
|
||||
pattern - a path relative to this directory, with wildcards.
|
||||
|
||||
For example, path('/users').glob('*/bin/*') returns a list
|
||||
of all the files users have in their bin directories.
|
||||
"""
|
||||
cls = self.__class__
|
||||
return [cls(s) for s in glob.glob(_base(self / pattern))]
|
||||
|
||||
|
||||
# --- Reading or writing an entire file at once.
|
||||
|
||||
def open(self, mode='r'):
|
||||
""" Open this file. Return a file object. """
|
||||
return file(self, mode)
|
||||
|
||||
def bytes(self):
|
||||
""" Open this file, read all bytes, return them as a string. """
|
||||
f = self.open('rb')
|
||||
try:
|
||||
return f.read()
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
def write_bytes(self, bytes, append=False):
|
||||
""" Open this file and write the given bytes to it.
|
||||
|
||||
Default behavior is to overwrite any existing file.
|
||||
Call p.write_bytes(bytes, append=True) to append instead.
|
||||
"""
|
||||
if append:
|
||||
mode = 'ab'
|
||||
else:
|
||||
mode = 'wb'
|
||||
f = self.open(mode)
|
||||
try:
|
||||
f.write(bytes)
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
def text(self, encoding=None, errors='strict'):
|
||||
r""" Open this file, read it in, return the content as a string.
|
||||
|
||||
This uses 'U' mode in Python 2.3 and later, so '\r\n' and '\r'
|
||||
are automatically translated to '\n'.
|
||||
|
||||
Optional arguments:
|
||||
|
||||
encoding - The Unicode encoding (or character set) of
|
||||
the file. If present, the content of the file is
|
||||
decoded and returned as a unicode object; otherwise
|
||||
it is returned as an 8-bit str.
|
||||
errors - How to handle Unicode errors; see help(str.decode)
|
||||
for the options. Default is 'strict'.
|
||||
"""
|
||||
if encoding is None:
|
||||
# 8-bit
|
||||
f = self.open(_textmode)
|
||||
try:
|
||||
return f.read()
|
||||
finally:
|
||||
f.close()
|
||||
else:
|
||||
# Unicode
|
||||
f = codecs.open(self, 'r', encoding, errors)
|
||||
# (Note - Can't use 'U' mode here, since codecs.open
|
||||
# doesn't support 'U' mode, even in Python 2.3.)
|
||||
try:
|
||||
t = f.read()
|
||||
finally:
|
||||
f.close()
|
||||
return (t.replace(u'\r\n', u'\n')
|
||||
.replace(u'\r\x85', u'\n')
|
||||
.replace(u'\r', u'\n')
|
||||
.replace(u'\x85', u'\n')
|
||||
.replace(u'\u2028', u'\n'))
|
||||
|
||||
def write_text(self, text, encoding=None, errors='strict', linesep=os.linesep, append=False):
|
||||
r""" Write the given text to this file.
|
||||
|
||||
The default behavior is to overwrite any existing file;
|
||||
to append instead, use the 'append=True' keyword argument.
|
||||
|
||||
There are two differences between path.write_text() and
|
||||
path.write_bytes(): newline handling and Unicode handling.
|
||||
See below.
|
||||
|
||||
Parameters:
|
||||
|
||||
- text - str/unicode - The text to be written.
|
||||
|
||||
- encoding - str - The Unicode encoding that will be used.
|
||||
This is ignored if 'text' isn't a Unicode string.
|
||||
|
||||
- errors - str - How to handle Unicode encoding errors.
|
||||
Default is 'strict'. See help(unicode.encode) for the
|
||||
options. This is ignored if 'text' isn't a Unicode
|
||||
string.
|
||||
|
||||
- linesep - keyword argument - str/unicode - The sequence of
|
||||
characters to be used to mark end-of-line. The default is
|
||||
os.linesep. You can also specify None; this means to
|
||||
leave all newlines as they are in 'text'.
|
||||
|
||||
- append - keyword argument - bool - Specifies what to do if
|
||||
the file already exists (True: append to the end of it;
|
||||
False: overwrite it.) The default is False.
|
||||
|
||||
|
||||
--- Newline handling.
|
||||
|
||||
write_text() converts all standard end-of-line sequences
|
||||
('\n', '\r', and '\r\n') to your platform's default end-of-line
|
||||
sequence (see os.linesep; on Windows, for example, the
|
||||
end-of-line marker is '\r\n').
|
||||
|
||||
If you don't like your platform's default, you can override it
|
||||
using the 'linesep=' keyword argument. If you specifically want
|
||||
write_text() to preserve the newlines as-is, use 'linesep=None'.
|
||||
|
||||
This applies to Unicode text the same as to 8-bit text, except
|
||||
there are three additional standard Unicode end-of-line sequences:
|
||||
u'\x85', u'\r\x85', and u'\u2028'.
|
||||
|
||||
(This is slightly different from when you open a file for
|
||||
writing with fopen(filename, "w") in C or file(filename, 'w')
|
||||
in Python.)
|
||||
|
||||
|
||||
--- Unicode
|
||||
|
||||
If 'text' isn't Unicode, then apart from newline handling, the
|
||||
bytes are written verbatim to the file. The 'encoding' and
|
||||
'errors' arguments are not used and must be omitted.
|
||||
|
||||
If 'text' is Unicode, it is first converted to bytes using the
|
||||
specified 'encoding' (or the default encoding if 'encoding'
|
||||
isn't specified). The 'errors' argument applies only to this
|
||||
conversion.
|
||||
|
||||
"""
|
||||
if isinstance(text, unicode):
|
||||
if linesep is not None:
|
||||
# Convert all standard end-of-line sequences to
|
||||
# ordinary newline characters.
|
||||
text = (text.replace(u'\r\n', u'\n')
|
||||
.replace(u'\r\x85', u'\n')
|
||||
.replace(u'\r', u'\n')
|
||||
.replace(u'\x85', u'\n')
|
||||
.replace(u'\u2028', u'\n'))
|
||||
text = text.replace(u'\n', linesep)
|
||||
if encoding is None:
|
||||
encoding = sys.getdefaultencoding()
|
||||
bytes = text.encode(encoding, errors)
|
||||
else:
|
||||
# It is an error to specify an encoding if 'text' is
|
||||
# an 8-bit string.
|
||||
assert encoding is None
|
||||
|
||||
if linesep is not None:
|
||||
text = (text.replace('\r\n', '\n')
|
||||
.replace('\r', '\n'))
|
||||
bytes = text.replace('\n', linesep)
|
||||
|
||||
self.write_bytes(bytes, append)
|
||||
|
||||
def lines(self, encoding=None, errors='strict', retain=True):
|
||||
r""" Open this file, read all lines, return them in a list.
|
||||
|
||||
Optional arguments:
|
||||
encoding - The Unicode encoding (or character set) of
|
||||
the file. The default is None, meaning the content
|
||||
of the file is read as 8-bit characters and returned
|
||||
as a list of (non-Unicode) str objects.
|
||||
errors - How to handle Unicode errors; see help(str.decode)
|
||||
for the options. Default is 'strict'
|
||||
retain - If true, retain newline characters; but all newline
|
||||
character combinations ('\r', '\n', '\r\n') are
|
||||
translated to '\n'. If false, newline characters are
|
||||
stripped off. Default is True.
|
||||
|
||||
This uses 'U' mode in Python 2.3 and later.
|
||||
"""
|
||||
if encoding is None and retain:
|
||||
f = self.open(_textmode)
|
||||
try:
|
||||
return f.readlines()
|
||||
finally:
|
||||
f.close()
|
||||
else:
|
||||
return self.text(encoding, errors).splitlines(retain)
|
||||
|
||||
def write_lines(self, lines, encoding=None, errors='strict',
|
||||
linesep=os.linesep, append=False):
|
||||
r""" Write the given lines of text to this file.
|
||||
|
||||
By default this overwrites any existing file at this path.
|
||||
|
||||
This puts a platform-specific newline sequence on every line.
|
||||
See 'linesep' below.
|
||||
|
||||
lines - A list of strings.
|
||||
|
||||
encoding - A Unicode encoding to use. This applies only if
|
||||
'lines' contains any Unicode strings.
|
||||
|
||||
errors - How to handle errors in Unicode encoding. This
|
||||
also applies only to Unicode strings.
|
||||
|
||||
linesep - The desired line-ending. This line-ending is
|
||||
applied to every line. If a line already has any
|
||||
standard line ending ('\r', '\n', '\r\n', u'\x85',
|
||||
u'\r\x85', u'\u2028'), that will be stripped off and
|
||||
this will be used instead. The default is os.linesep,
|
||||
which is platform-dependent ('\r\n' on Windows, '\n' on
|
||||
Unix, etc.) Specify None to write the lines as-is,
|
||||
like file.writelines().
|
||||
|
||||
Use the keyword argument append=True to append lines to the
|
||||
file. The default is to overwrite the file. Warning:
|
||||
When you use this with Unicode data, if the encoding of the
|
||||
existing data in the file is different from the encoding
|
||||
you specify with the encoding= parameter, the result is
|
||||
mixed-encoding data, which can really confuse someone trying
|
||||
to read the file later.
|
||||
"""
|
||||
if append:
|
||||
mode = 'ab'
|
||||
else:
|
||||
mode = 'wb'
|
||||
f = self.open(mode)
|
||||
try:
|
||||
for line in lines:
|
||||
isUnicode = isinstance(line, unicode)
|
||||
if linesep is not None:
|
||||
# Strip off any existing line-end and add the
|
||||
# specified linesep string.
|
||||
if isUnicode:
|
||||
if line[-2:] in (u'\r\n', u'\x0d\x85'):
|
||||
line = line[:-2]
|
||||
elif line[-1:] in (u'\r', u'\n',
|
||||
u'\x85', u'\u2028'):
|
||||
line = line[:-1]
|
||||
else:
|
||||
if line[-2:] == '\r\n':
|
||||
line = line[:-2]
|
||||
elif line[-1:] in ('\r', '\n'):
|
||||
line = line[:-1]
|
||||
line += linesep
|
||||
if isUnicode:
|
||||
if encoding is None:
|
||||
encoding = sys.getdefaultencoding()
|
||||
line = line.encode(encoding, errors)
|
||||
f.write(line)
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
def read_md5(self):
|
||||
""" Calculate the md5 hash for this file.
|
||||
|
||||
This reads through the entire file.
|
||||
"""
|
||||
f = self.open('rb')
|
||||
try:
|
||||
m = hashlib.md5()
|
||||
while True:
|
||||
d = f.read(8192)
|
||||
if not d:
|
||||
break
|
||||
m.update(d)
|
||||
finally:
|
||||
f.close()
|
||||
return m.digest()
|
||||
|
||||
# --- Methods for querying the filesystem.
|
||||
|
||||
exists = os.path.exists
|
||||
isdir = os.path.isdir
|
||||
isfile = os.path.isfile
|
||||
islink = os.path.islink
|
||||
ismount = os.path.ismount
|
||||
|
||||
if hasattr(os.path, 'samefile'):
|
||||
samefile = os.path.samefile
|
||||
|
||||
getatime = os.path.getatime
|
||||
atime = property(
|
||||
getatime, None, None,
|
||||
""" Last access time of the file. """)
|
||||
|
||||
getmtime = os.path.getmtime
|
||||
mtime = property(
|
||||
getmtime, None, None,
|
||||
""" Last-modified time of the file. """)
|
||||
|
||||
if hasattr(os.path, 'getctime'):
|
||||
getctime = os.path.getctime
|
||||
ctime = property(
|
||||
getctime, None, None,
|
||||
""" Creation time of the file. """)
|
||||
|
||||
getsize = os.path.getsize
|
||||
size = property(
|
||||
getsize, None, None,
|
||||
""" Size of the file, in bytes. """)
|
||||
|
||||
if hasattr(os, 'access'):
|
||||
def access(self, mode):
|
||||
""" Return true if current user has access to this path.
|
||||
|
||||
mode - One of the constants os.F_OK, os.R_OK, os.W_OK, os.X_OK
|
||||
"""
|
||||
return os.access(self, mode)
|
||||
|
||||
def stat(self):
|
||||
""" Perform a stat() system call on this path. """
|
||||
return os.stat(self)
|
||||
|
||||
def lstat(self):
|
||||
""" Like path.stat(), but do not follow symbolic links. """
|
||||
return os.lstat(self)
|
||||
|
||||
def get_owner(self):
|
||||
r""" Return the name of the owner of this file or directory.
|
||||
|
||||
This follows symbolic links.
|
||||
|
||||
On Windows, this returns a name of the form ur'DOMAIN\User Name'.
|
||||
On Windows, a group can own a file or directory.
|
||||
"""
|
||||
if os.name == 'nt':
|
||||
if win32security is None:
|
||||
raise Exception("path.owner requires win32all to be installed")
|
||||
desc = win32security.GetFileSecurity(
|
||||
self, win32security.OWNER_SECURITY_INFORMATION)
|
||||
sid = desc.GetSecurityDescriptorOwner()
|
||||
account, domain, typecode = win32security.LookupAccountSid(None, sid)
|
||||
return domain + u'\\' + account
|
||||
else:
|
||||
if pwd is None:
|
||||
raise NotImplementedError("path.owner is not implemented on this platform.")
|
||||
st = self.stat()
|
||||
return pwd.getpwuid(st.st_uid).pw_name
|
||||
|
||||
owner = property(
|
||||
get_owner, None, None,
|
||||
""" Name of the owner of this file or directory. """)
|
||||
|
||||
if hasattr(os, 'statvfs'):
|
||||
def statvfs(self):
|
||||
""" Perform a statvfs() system call on this path. """
|
||||
return os.statvfs(self)
|
||||
|
||||
if hasattr(os, 'pathconf'):
|
||||
def pathconf(self, name):
|
||||
return os.pathconf(self, name)
|
||||
|
||||
|
||||
# --- Modifying operations on files and directories
|
||||
|
||||
def utime(self, times):
|
||||
""" Set the access and modified times of this file. """
|
||||
os.utime(self, times)
|
||||
|
||||
def chmod(self, mode):
|
||||
os.chmod(self, mode)
|
||||
|
||||
if hasattr(os, 'chown'):
|
||||
def chown(self, uid, gid):
|
||||
os.chown(self, uid, gid)
|
||||
|
||||
def rename(self, new):
|
||||
os.rename(self, new)
|
||||
|
||||
def renames(self, new):
|
||||
os.renames(self, new)
|
||||
|
||||
|
||||
# --- Create/delete operations on directories
|
||||
|
||||
def mkdir(self, mode=0777):
|
||||
os.mkdir(self, mode)
|
||||
|
||||
def makedirs(self, mode=0777):
|
||||
os.makedirs(self, mode)
|
||||
|
||||
def rmdir(self):
|
||||
os.rmdir(self)
|
||||
|
||||
def removedirs(self):
|
||||
os.removedirs(self)
|
||||
|
||||
|
||||
# --- Modifying operations on files
|
||||
|
||||
def touch(self):
|
||||
""" Set the access/modified times of this file to the current time.
|
||||
Create the file if it does not exist.
|
||||
"""
|
||||
fd = os.open(self, os.O_WRONLY | os.O_CREAT, 0666)
|
||||
os.close(fd)
|
||||
os.utime(self, None)
|
||||
|
||||
def remove(self):
|
||||
os.remove(self)
|
||||
|
||||
def unlink(self):
|
||||
os.unlink(self)
|
||||
|
||||
|
||||
# --- Links
|
||||
|
||||
if hasattr(os, 'link'):
|
||||
def link(self, newpath):
|
||||
""" Create a hard link at 'newpath', pointing to this file. """
|
||||
os.link(self, newpath)
|
||||
|
||||
if hasattr(os, 'symlink'):
|
||||
def symlink(self, newlink):
|
||||
""" Create a symbolic link at 'newlink', pointing here. """
|
||||
os.symlink(self, newlink)
|
||||
|
||||
if hasattr(os, 'readlink'):
|
||||
def readlink(self):
|
||||
""" Return the path to which this symbolic link points.
|
||||
|
||||
The result may be an absolute or a relative path.
|
||||
"""
|
||||
return self.__class__(os.readlink(self))
|
||||
|
||||
def readlinkabs(self):
|
||||
""" Return the path to which this symbolic link points.
|
||||
|
||||
The result is always an absolute path.
|
||||
"""
|
||||
p = self.readlink()
|
||||
if p.isabs():
|
||||
return p
|
||||
else:
|
||||
return (self.parent / p).abspath()
|
||||
|
||||
|
||||
# --- High-level functions from shutil
|
||||
|
||||
copyfile = shutil.copyfile
|
||||
copymode = shutil.copymode
|
||||
copystat = shutil.copystat
|
||||
copy = shutil.copy
|
||||
copy2 = shutil.copy2
|
||||
copytree = shutil.copytree
|
||||
if hasattr(shutil, 'move'):
|
||||
move = shutil.move
|
||||
rmtree = shutil.rmtree
|
||||
|
||||
|
||||
# --- Special stuff from os
|
||||
|
||||
if hasattr(os, 'chroot'):
|
||||
def chroot(self):
|
||||
os.chroot(self)
|
||||
|
||||
if hasattr(os, 'startfile'):
|
||||
def startfile(self):
|
||||
os.startfile(self)
|
||||
|
@ -1,121 +0,0 @@
|
||||
|
||||
import sys, glob, re
|
||||
|
||||
import mechanize
|
||||
|
||||
URL = 'http://translate.google.com/translate_t?text=%(text)s&langpair=en|%(lang)s&oe=UTF8'
|
||||
|
||||
def browser():
|
||||
opener = mechanize.Browser()
|
||||
opener.set_handle_refresh(True)
|
||||
opener.set_handle_robots(False)
|
||||
opener.addheaders = [('User-agent', 'Mozilla/5.0 (X11; U; i686 Linux; en_US; rv:1.8.0.4) Gecko/20060508 Firefox/1.5.0.4')]
|
||||
return opener
|
||||
|
||||
|
||||
class PoFile(object):
|
||||
|
||||
SANITIZE = re.compile(r'&|<[^<>]+>|\%')
|
||||
STRING = re.compile(r'"(.*)"')
|
||||
|
||||
def __init__(self, po_file):
|
||||
self.po_file = open(po_file, 'r+b')
|
||||
self.browser = browser()
|
||||
self.entries = []
|
||||
self.read()
|
||||
|
||||
def sanitize_line(self, line):
|
||||
return self.SANITIZE.sub(line)
|
||||
|
||||
def read(self):
|
||||
translated_lines = []
|
||||
self.po_file.seek(0)
|
||||
|
||||
ID = 0
|
||||
STR = 1
|
||||
WHR = 2
|
||||
|
||||
mode = None
|
||||
where, msgid, msgstr, fuzzy = [], [], [], False
|
||||
|
||||
for line in self.po_file.readlines():
|
||||
prev_mode = mode
|
||||
if line.startswith('#:'):
|
||||
mode = WHR
|
||||
elif line.startswith('msgid'):
|
||||
mode = ID
|
||||
elif line.startswith('msgstr'):
|
||||
mode = STR
|
||||
elif line.startswith('#,'):
|
||||
fuzzy = True
|
||||
continue
|
||||
elif line.startswith('#') or not line.strip():
|
||||
mode = None
|
||||
|
||||
|
||||
if mode != prev_mode:
|
||||
if prev_mode == STR:
|
||||
self.add_entry(where, fuzzy, msgid, msgstr)
|
||||
where, msgid, msgstr, fuzzy = [], [], [], False
|
||||
|
||||
if mode == WHR:
|
||||
where.append(line[2:].strip())
|
||||
elif mode == ID:
|
||||
msgid.append(self.get_string(line))
|
||||
elif mode == STR:
|
||||
msgstr.append(self.get_string(line))
|
||||
elif mode == None:
|
||||
self.add_line(line)
|
||||
|
||||
def get_string(self, line):
|
||||
return self.STRING.search(line).group(1)
|
||||
|
||||
def add_line(self, line):
|
||||
self.entries.append(line.strip())
|
||||
|
||||
def add_entry(self, where, fuzzy, msgid, msgstr):
|
||||
self.entries.append(Entry(where, fuzzy, msgid, msgstr))
|
||||
|
||||
def __str__(self):
|
||||
return '\n'.join([str(i) for i in self.entries]) + '\n'
|
||||
|
||||
|
||||
class Entry(object):
|
||||
|
||||
def __init__(self, where, fuzzy, msgid, msgstr, encoding='utf-8'):
|
||||
self.fuzzy = fuzzy
|
||||
self.where = [i.decode(encoding) for i in where]
|
||||
self.msgid = [i.decode(encoding) for i in msgid]
|
||||
self.msgstr = [i.decode(encoding) for i in msgstr]
|
||||
self.encoding = encoding
|
||||
|
||||
def __str__(self):
|
||||
ans = []
|
||||
for line in self.where:
|
||||
ans.append('#: ' + line.encode(self.encoding))
|
||||
if self.fuzzy:
|
||||
ans.append('#, fuzzy')
|
||||
first = True
|
||||
for line in self.msgid:
|
||||
prefix = 'msgid ' if first else ''
|
||||
ans.append(prefix + '"%s"'%line.encode(self.encoding))
|
||||
first = False
|
||||
first = True
|
||||
for line in self.msgstr:
|
||||
prefix = 'msgstr ' if first else ''
|
||||
ans.append(prefix + '"%s"'%line.encode(self.encoding))
|
||||
first = False
|
||||
return '\n'.join(ans)
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
po_files = glob.glob('*.po')
|
||||
for po_file in po_files:
|
||||
PoFile(po_file)
|
||||
pass
|
||||
|
||||
if __name__ == '__main__':
|
||||
pof = PoFile('de.po')
|
||||
open('/tmp/de.po', 'wb').write(str(pof))
|
||||
#sys.exit(main())
|
@ -15,7 +15,10 @@ def available_translations():
|
||||
global _available_translations
|
||||
if _available_translations is None:
|
||||
stats = P('localization/stats.pickle')
|
||||
if os.path.exists(stats):
|
||||
stats = cPickle.load(open(stats, 'rb'))
|
||||
else:
|
||||
stats = {}
|
||||
_available_translations = [x for x in stats if stats[x] > 0.1]
|
||||
return _available_translations
|
||||
|
||||
|
@ -20,6 +20,7 @@ class WriteXmlMixin:
|
||||
def to_xml(self, encoding = "iso-8859-1"):
|
||||
try:
|
||||
import cStringIO as StringIO
|
||||
StringIO
|
||||
except ImportError:
|
||||
import StringIO
|
||||
f = StringIO.StringIO()
|
||||
|
@ -57,13 +57,13 @@ recipe_modules = ['recipe_' + r for r in (
|
||||
'monitor', 'republika', 'beta', 'beta_en', 'glasjavnosti',
|
||||
'esquire', 'livemint', 'thedgesingapore', 'darknet', 'rga',
|
||||
'intelligencer', 'theoldfoodie', 'hln_be', 'honvedelem',
|
||||
'the_new_republic',
|
||||
)]
|
||||
|
||||
|
||||
import re, imp, inspect, time, os
|
||||
from calibre.web.feeds.news import BasicNewsRecipe, CustomIndexRecipe, AutomaticNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup
|
||||
from calibre.path import path
|
||||
from calibre.ptempfile import PersistentTemporaryDirectory
|
||||
from calibre import __appname__, english_sort
|
||||
|
||||
@ -102,8 +102,8 @@ def compile_recipe(src):
|
||||
'''
|
||||
global _tdir, _crep
|
||||
if _tdir is None or not os.path.exists(_tdir):
|
||||
_tdir = path(PersistentTemporaryDirectory('_recipes'))
|
||||
temp = _tdir/('recipe%d.py'%_crep)
|
||||
_tdir = PersistentTemporaryDirectory('_recipes')
|
||||
temp = os.path.join(_tdir, 'recipe%d.py'%_crep)
|
||||
_crep += 1
|
||||
if not isinstance(src, unicode):
|
||||
match = re.search(r'coding[:=]\s*([-\w.]+)', src[:200])
|
||||
@ -118,8 +118,9 @@ def compile_recipe(src):
|
||||
src = src.replace('from libprs500', 'from calibre').encode('utf-8')
|
||||
f.write(src)
|
||||
f.close()
|
||||
module = imp.find_module(temp.namebase, [temp.dirname()])
|
||||
module = imp.load_module(temp.namebase, *module)
|
||||
module = imp.find_module(os.path.splitext(os.path.basename(temp))[0],
|
||||
[os.path.dirname(temp)])
|
||||
module = imp.load_module(os.path.splitext(os.path.basename(temp))[0], *module)
|
||||
classes = inspect.getmembers(module,
|
||||
lambda x : inspect.isclass(x) and \
|
||||
issubclass(x, (BasicNewsRecipe,)) and \
|
||||
@ -148,6 +149,7 @@ _titles.sort(cmp=english_sort)
|
||||
titles = _titles
|
||||
|
||||
def migrate_automatic_profile_to_automatic_recipe(profile):
|
||||
BeautifulSoup
|
||||
oprofile = profile
|
||||
profile = compile_recipe(profile)
|
||||
if 'BasicUserProfile' not in profile.__name__:
|
||||
@ -165,3 +167,4 @@ class BasicUserRecipe%d(AutomaticNewsRecipe):
|
||||
'''%(int(time.time()), repr(profile.title), profile.oldest_article,
|
||||
profile.max_articles_per_feed, profile.summary_length, repr(profile.feeds))
|
||||
|
||||
|
||||
|
@ -9,7 +9,7 @@ __copyright__ = '2009, Darko Miletic <darko.miletic at gmail.com>'
|
||||
|
||||
import re
|
||||
from calibre.web.feeds.recipes import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
from calibre.ebooks.BeautifulSoup import Tag
|
||||
|
||||
class Cro24Sata(BasicNewsRecipe):
|
||||
title = '24 Sata - Hr'
|
||||
|
@ -9,7 +9,7 @@ __copyright__ = '2009, Darko Miletic <darko.miletic at gmail.com>'
|
||||
|
||||
import re
|
||||
from calibre.web.feeds.recipes import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
from calibre.ebooks.BeautifulSoup import Tag
|
||||
|
||||
class Ser24Sata(BasicNewsRecipe):
|
||||
title = '24 Sata - Sr'
|
||||
|
@ -59,4 +59,3 @@ class Ambito(BasicNewsRecipe):
|
||||
return soup
|
||||
|
||||
language = 'es'
|
||||
|
@ -7,7 +7,7 @@ beta.rs
|
||||
'''
|
||||
import re
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
from calibre.ebooks.BeautifulSoup import Tag
|
||||
|
||||
class Danas(BasicNewsRecipe):
|
||||
title = 'BETA'
|
||||
|
@ -7,7 +7,6 @@ beta.rs
|
||||
'''
|
||||
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
|
||||
class Danas(BasicNewsRecipe):
|
||||
title = 'BETA - English'
|
||||
|
@ -8,7 +8,6 @@ blic.rs
|
||||
|
||||
import re
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
|
||||
class Blic(BasicNewsRecipe):
|
||||
title = 'Blic'
|
||||
|
@ -3,11 +3,7 @@ __license__ = 'GPL 3'
|
||||
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import re
|
||||
from urlparse import urlparse, urlunparse
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
from calibre.ptempfile import PersistentTemporaryFile
|
||||
from threading import RLock
|
||||
|
||||
class ChicagoTribune(BasicNewsRecipe):
|
||||
|
||||
|
@ -7,7 +7,7 @@ climateprogress.org
|
||||
'''
|
||||
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
from calibre.ebooks.BeautifulSoup import Tag
|
||||
|
||||
class ClimateProgress(BasicNewsRecipe):
|
||||
title = 'Climate Progress'
|
||||
|
@ -7,7 +7,6 @@ Courrier International
|
||||
'''
|
||||
|
||||
import re
|
||||
from datetime import date
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
|
||||
class CourrierInternational(BasicNewsRecipe):
|
||||
|
@ -7,7 +7,6 @@ newyorker.com
|
||||
'''
|
||||
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import Tag
|
||||
|
||||
class CubaDebate(BasicNewsRecipe):
|
||||
title = 'CubaDebate'
|
||||
|
@ -7,7 +7,7 @@ danas.rs
|
||||
'''
|
||||
import re
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
from calibre.ebooks.BeautifulSoup import Tag
|
||||
|
||||
class Danas(BasicNewsRecipe):
|
||||
title = 'Danas'
|
||||
|
@ -9,7 +9,7 @@ dnevniavaz.ba
|
||||
|
||||
import re
|
||||
from calibre.web.feeds.recipes import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
from calibre.ebooks.BeautifulSoup import Tag
|
||||
|
||||
class DnevniAvaz(BasicNewsRecipe):
|
||||
title = 'Dnevni Avaz'
|
||||
|
@ -9,7 +9,7 @@ dnevnik.hr
|
||||
|
||||
import re
|
||||
from calibre.web.feeds.recipes import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
from calibre.ebooks.BeautifulSoup import Tag
|
||||
|
||||
class DnevnikCro(BasicNewsRecipe):
|
||||
title = 'Dnevnik - Hr'
|
||||
|
@ -9,7 +9,7 @@ e-novine.com
|
||||
|
||||
import re
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
from calibre.ebooks.BeautifulSoup import Tag
|
||||
|
||||
class E_novine(BasicNewsRecipe):
|
||||
title = 'E-Novine'
|
||||
|
@ -59,4 +59,3 @@ class ElMercurio(BasicNewsRecipe):
|
||||
return soup
|
||||
|
||||
language = 'es'
|
||||
|
@ -58,4 +58,3 @@ class ElMundo(BasicNewsRecipe):
|
||||
return soup
|
||||
|
||||
language = 'es'
|
||||
|
@ -7,7 +7,7 @@ www.tiempo.hn
|
||||
'''
|
||||
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
from calibre.ebooks.BeautifulSoup import Tag
|
||||
|
||||
class ElTiempoHn(BasicNewsRecipe):
|
||||
title = 'El Tiempo - Honduras'
|
||||
|
@ -6,7 +6,6 @@ __copyright__ = '2008, Darko Miletic <darko.miletic at gmail.com>'
|
||||
engadget.com
|
||||
'''
|
||||
|
||||
import string,re
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
|
||||
class Engadget(BasicNewsRecipe):
|
||||
|
@ -6,7 +6,6 @@ __copyright__ = '2008, Darko Miletic <darko.miletic at gmail.com>'
|
||||
fudzilla.com
|
||||
'''
|
||||
|
||||
import string,re
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
|
||||
class Fudzilla(BasicNewsRecipe):
|
||||
|
@ -9,7 +9,7 @@ glassrpske.com
|
||||
|
||||
import re
|
||||
from calibre.web.feeds.recipes import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
from calibre.ebooks.BeautifulSoup import Tag
|
||||
|
||||
class GlasSrpske(BasicNewsRecipe):
|
||||
title = 'Glas Srpske'
|
||||
|
@ -5,7 +5,6 @@ __copyright__ = '2008-2009, Darko Miletic <darko.miletic at gmail.com>'
|
||||
'''
|
||||
granma.cubaweb.cu
|
||||
'''
|
||||
import urllib
|
||||
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
|
||||
|
@ -9,7 +9,7 @@ www.hrt.hr
|
||||
|
||||
import re
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
from calibre.ebooks.BeautifulSoup import Tag
|
||||
|
||||
class HRT(BasicNewsRecipe):
|
||||
title = 'HRT: Vesti'
|
||||
|
@ -8,7 +8,7 @@ jutarnji.hr
|
||||
|
||||
import re
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
from calibre.ebooks.BeautifulSoup import Tag
|
||||
|
||||
class Jutarnji(BasicNewsRecipe):
|
||||
title = 'Jutarnji'
|
||||
|
@ -42,4 +42,3 @@ class Juventudrebelde_english(BasicNewsRecipe):
|
||||
return soup
|
||||
|
||||
language = 'en'
|
||||
|
@ -51,4 +51,3 @@ class LaCuarta(BasicNewsRecipe):
|
||||
|
||||
|
||||
language = 'es'
|
||||
|
@ -62,4 +62,3 @@ class LaTercera(BasicNewsRecipe):
|
||||
return soup
|
||||
|
||||
language = 'es'
|
||||
|
@ -58,4 +58,3 @@ class Lanacion(BasicNewsRecipe):
|
||||
return soup
|
||||
|
||||
language = 'es'
|
||||
|
@ -52,4 +52,3 @@ class LaNacionChile(BasicNewsRecipe):
|
||||
return soup
|
||||
|
||||
language = 'es'
|
||||
|
@ -58,4 +58,3 @@ class LaPrensa(BasicNewsRecipe):
|
||||
return soup
|
||||
|
||||
language = 'es'
|
||||
|
@ -7,7 +7,7 @@ www.laprensahn.com
|
||||
'''
|
||||
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
from calibre.ebooks.BeautifulSoup import Tag
|
||||
|
||||
class LaPrensaHn(BasicNewsRecipe):
|
||||
title = 'La Prensa - Honduras'
|
||||
|
@ -7,7 +7,7 @@ www.latribuna.hn
|
||||
'''
|
||||
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
from calibre.ebooks.BeautifulSoup import Tag
|
||||
|
||||
class LaTribuna(BasicNewsRecipe):
|
||||
title = 'La Tribuna - Honduras'
|
||||
|
@ -7,7 +7,6 @@ Mediapart
|
||||
'''
|
||||
|
||||
import re, string
|
||||
from datetime import date
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
|
||||
|
@ -9,7 +9,7 @@ monitorcg.com
|
||||
|
||||
import re
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
from calibre.ebooks.BeautifulSoup import Tag
|
||||
|
||||
class MonitorCG(BasicNewsRecipe):
|
||||
title = 'Monitor online'
|
||||
|
@ -9,7 +9,7 @@ nacional.hr
|
||||
|
||||
import re
|
||||
from calibre.web.feeds.recipes import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
from calibre.ebooks.BeautifulSoup import Tag
|
||||
|
||||
class NacionalCro(BasicNewsRecipe):
|
||||
title = 'Nacional - Hr'
|
||||
|
@ -8,7 +8,7 @@ nin.co.rs
|
||||
|
||||
import re, urllib
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
from calibre.ebooks.BeautifulSoup import Tag
|
||||
|
||||
class Nin(BasicNewsRecipe):
|
||||
title = 'NIN online'
|
||||
|
@ -8,7 +8,7 @@ novosti.rs
|
||||
|
||||
import re
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
from calibre.ebooks.BeautifulSoup import Tag
|
||||
|
||||
class Novosti(BasicNewsRecipe):
|
||||
title = 'Vecernje Novosti'
|
||||
|
@ -8,7 +8,6 @@ nspm.rs
|
||||
|
||||
import re
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
|
||||
class Nspm(BasicNewsRecipe):
|
||||
title = 'Nova srpska politicka misao'
|
||||
|
@ -3,8 +3,6 @@
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2009, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
import re
|
||||
from calibre import strftime
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
|
||||
class OutlookIndia(BasicNewsRecipe):
|
||||
|
@ -8,7 +8,7 @@ pescanik.net
|
||||
|
||||
import re
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
from calibre.ebooks.BeautifulSoup import Tag
|
||||
|
||||
class Pescanik(BasicNewsRecipe):
|
||||
title = 'Pescanik'
|
||||
|
@ -10,7 +10,7 @@ pobjeda.co.me
|
||||
import re
|
||||
from calibre import strftime
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
from calibre.ebooks.BeautifulSoup import Tag
|
||||
|
||||
class Pobjeda(BasicNewsRecipe):
|
||||
title = 'Pobjeda Online'
|
||||
|
@ -7,7 +7,7 @@ politika.rs
|
||||
'''
|
||||
import re
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
from calibre.ebooks.BeautifulSoup import Tag
|
||||
|
||||
class Politika(BasicNewsRecipe):
|
||||
title = 'Politika Online'
|
||||
|
@ -9,7 +9,7 @@ pressonline.rs
|
||||
|
||||
import re
|
||||
from calibre.web.feeds.recipes import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
from calibre.ebooks.BeautifulSoup import Tag
|
||||
|
||||
class PressOnline(BasicNewsRecipe):
|
||||
title = 'Press Online'
|
||||
|
@ -9,7 +9,7 @@ www.rts.rs
|
||||
|
||||
import re
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
from calibre.ebooks.BeautifulSoup import Tag
|
||||
|
||||
class RTS(BasicNewsRecipe):
|
||||
title = 'RTS: Vesti'
|
||||
|
@ -6,8 +6,7 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
calibre recipe for slate.com
|
||||
'''
|
||||
|
||||
import string, re, sys
|
||||
from calibre import strftime
|
||||
import re
|
||||
from calibre.web.feeds.recipes import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, NavigableString, CData, Comment, Tag
|
||||
|
||||
@ -296,7 +295,7 @@ class PeriodicalNameHere(BasicNewsRecipe):
|
||||
found_excluded = excluded.search(str(soup))
|
||||
if found_excluded :
|
||||
print "no allowed content found, removing article"
|
||||
raise StringError
|
||||
raise Exception('String error')
|
||||
|
||||
# Articles from www.thebigmoney.com use different tagging for byline, dateline and body
|
||||
head = soup.find('head')
|
||||
|
@ -7,7 +7,7 @@ spiegel.de
|
||||
'''
|
||||
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
from calibre.ebooks.BeautifulSoup import Tag
|
||||
|
||||
class Spiegel_ger(BasicNewsRecipe):
|
||||
title = 'Spiegel Online - German'
|
||||
|
@ -7,7 +7,7 @@ tanjug.rs
|
||||
'''
|
||||
import re
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
from calibre.ebooks.BeautifulSoup import Tag
|
||||
|
||||
class Tanjug(BasicNewsRecipe):
|
||||
title = 'Tanjug'
|
||||
|
@ -7,7 +7,7 @@ economictimes.indiatimes.com
|
||||
'''
|
||||
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
from calibre.ebooks.BeautifulSoup import Tag
|
||||
|
||||
class TheEconomicTimes(BasicNewsRecipe):
|
||||
title = 'The Economic Times India'
|
||||
|
@ -7,7 +7,7 @@ timesonline.co.uk
|
||||
'''
|
||||
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
from calibre.ebooks.BeautifulSoup import Tag
|
||||
|
||||
class Timesonline(BasicNewsRecipe):
|
||||
title = 'The Times Online'
|
||||
|
@ -7,7 +7,6 @@ tomshardware.com/us
|
||||
'''
|
||||
|
||||
import urllib
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup
|
||||
from calibre.web.feeds.recipes import BasicNewsRecipe
|
||||
|
||||
class Tomshardware(BasicNewsRecipe):
|
||||
|
@ -6,7 +6,7 @@ __copyright__ = '2009, Darko Miletic <darko.miletic at gmail.com>'
|
||||
twitchfilm.net/site/
|
||||
'''
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
from calibre.ebooks.BeautifulSoup import Tag
|
||||
|
||||
class Twitchfilm(BasicNewsRecipe):
|
||||
title = 'Twitch Films'
|
||||
|
@ -7,7 +7,7 @@ www.uncrate.com
|
||||
'''
|
||||
|
||||
from calibre.web.feeds.recipes import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
from calibre.ebooks.BeautifulSoup import Tag
|
||||
|
||||
class Uncrate(BasicNewsRecipe):
|
||||
title = 'Uncrate'
|
||||
|
@ -9,7 +9,7 @@ www.vecernji.hr
|
||||
|
||||
import re
|
||||
from calibre.web.feeds.recipes import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
from calibre.ebooks.BeautifulSoup import Tag
|
||||
|
||||
class VecernjiList(BasicNewsRecipe):
|
||||
title = 'Vecernji List'
|
||||
|
@ -9,7 +9,7 @@ vijesti.me
|
||||
|
||||
import re
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
from calibre.ebooks.BeautifulSoup import Tag
|
||||
|
||||
class Vijesti(BasicNewsRecipe):
|
||||
title = 'Vijesti'
|
||||
|
@ -9,7 +9,7 @@ vreme.com
|
||||
import re
|
||||
from calibre import strftime
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||
from calibre.ebooks.BeautifulSoup import Tag
|
||||
|
||||
class Vreme(BasicNewsRecipe):
|
||||
title = 'Vreme'
|
||||
|
Loading…
x
Reference in New Issue
Block a user