1
0
mirror of https://github.com/gryf/ebook-converter.git synced 2026-01-20 03:24:12 +01:00

Removed Windows bits.

This commit is contained in:
2020-06-17 19:23:52 +02:00
parent cd93b85eb0
commit 1a09e3db84
34 changed files with 147 additions and 820 deletions

View File

@@ -38,6 +38,10 @@ modifications from third parties (external modules copied into Calibre project
for instance), and make a huge cleanup. I'm not sure if I find time and
strength for doing it completely, but I'll try.
Windows is not currently supported, because of the original spaghetti code.
This may change in the future, after cleanup of mentioned pasta would be
completed.
Input formats
~~~~~~~~~~~~~

View File

@@ -16,18 +16,16 @@ except EnvironmentError:
from ebook_converter import constants_old
from ebook_converter.constants_old import islinux, isfrozen, \
isbsd, __appname__, __version__, __author__, \
win32event, win32api, winerror, fcntl, \
config_dir
from ebook_converter.startup import winutil, winutilerror
from ebook_converter.utils.icu import safe_chr
from ebook_converter.utils.terminal import Detect
if False:
# Prevent pyflakes from complaining
winutil, winutilerror, __appname__, islinux, __version__
fcntl, win32event, isfrozen, __author__
winerror, win32api, isbsd, config_dir
isfrozen, __author__
isbsd, config_dir
def init_mimetypes():

View File

@@ -18,7 +18,6 @@ Various run time constants.
_plat = sys.platform.lower()
iswindows = 'win32' in _plat or 'win64' in _plat
isosx = 'darwin' in _plat
isnewosx = isosx and getattr(sys, 'new_app_bundle', False)
isfreebsd = 'freebsd' in _plat
@@ -26,15 +25,11 @@ isnetbsd = 'netbsd' in _plat
isdragonflybsd = 'dragonfly' in _plat
isbsd = isfreebsd or isnetbsd or isdragonflybsd
ishaiku = 'haiku1' in _plat
islinux = not(iswindows or isosx or isbsd or ishaiku)
islinux = True
isfrozen = hasattr(sys, 'frozen')
isunix = isosx or islinux or ishaiku
isportable = os.getenv('CALIBRE_PORTABLE_BUILD') is not None
isxp = isoldvista = False
if iswindows:
wver = sys.getwindowsversion()
isxp = wver.major < 6
isoldvista = wver.build < 6002
is64bit = sys.maxsize > (1 << 32)
FAKE_PROTOCOL, FAKE_HOST = 'clbr', 'internal.invalid'
VIEWER_APP_UID = 'com.calibre-ebook.viewer'
@@ -48,10 +43,7 @@ try:
except:
preferred_encoding = 'utf-8'
win32event = importlib.import_module('win32event') if iswindows else None
winerror = importlib.import_module('winerror') if iswindows else None
win32api = importlib.import_module('win32api') if iswindows else None
fcntl = None if iswindows else importlib.import_module('fcntl')
fcntl = importlib.import_module('fcntl')
dark_link_color = '#6cb4ee'
_osx_ver = None
@@ -116,23 +108,14 @@ def _get_cache_dir():
if err.errno == errno.EEXIST:
return ans
if iswindows:
w = plugins['winutil'][0]
candidate = os.getenv('XDG_CACHE_HOME', '~/.cache')
candidate = os.path.join(os.path.expanduser(candidate),
__appname__)
if isinstance(candidate, bytes):
try:
candidate = os.path.join(w.special_folder_path(w.CSIDL_LOCAL_APPDATA), '%s-cache'%__appname__)
candidate = candidate.decode(filesystem_encoding)
except ValueError:
return confcache
elif isosx:
candidate = os.path.join(os.path.expanduser('~/Library/Caches'), __appname__)
else:
candidate = os.getenv('XDG_CACHE_HOME', '~/.cache')
candidate = os.path.join(os.path.expanduser(candidate),
__appname__)
if isinstance(candidate, bytes):
try:
candidate = candidate.decode(filesystem_encoding)
except ValueError:
candidate = confcache
candidate = confcache
try:
os.makedirs(candidate)
except EnvironmentError as err:
@@ -200,39 +183,27 @@ CONFIG_DIR_MODE = 0o700
cconfd = os.getenv('CALIBRE_CONFIG_DIRECTORY')
if cconfd is not None:
config_dir = os.path.abspath(cconfd)
elif iswindows:
if plugins['winutil'][0] is None:
raise Exception(plugins['winutil'][1])
try:
config_dir = plugins['winutil'][0].special_folder_path(plugins['winutil'][0].CSIDL_APPDATA)
except ValueError:
config_dir = None
if not config_dir or not os.access(config_dir, os.W_OK|os.X_OK):
config_dir = os.path.expanduser('~')
config_dir = os.path.join(config_dir, 'calibre')
elif isosx:
config_dir = os.path.expanduser('~/Library/Preferences/calibre')
else:
bdir = os.path.abspath(os.path.expanduser(os.getenv('XDG_CONFIG_HOME', '~/.config')))
config_dir = os.path.join(bdir, 'calibre')
try:
os.makedirs(config_dir, mode=CONFIG_DIR_MODE)
except:
pass
if not os.path.exists(config_dir) or \
not os.access(config_dir, os.W_OK) or not \
os.access(config_dir, os.X_OK):
print('No write acces to', config_dir, 'using a temporary dir instead')
import tempfile, atexit
config_dir = tempfile.mkdtemp(prefix='calibre-config-')
def cleanup_cdir():
try:
import shutil
shutil.rmtree(config_dir)
except:
pass
atexit.register(cleanup_cdir)
bdir = os.path.abspath(os.path.expanduser(os.getenv('XDG_CONFIG_HOME', '~/.config')))
config_dir = os.path.join(bdir, 'calibre')
try:
os.makedirs(config_dir, mode=CONFIG_DIR_MODE)
except:
pass
if not os.path.exists(config_dir) or \
not os.access(config_dir, os.W_OK) or not \
os.access(config_dir, os.X_OK):
print('No write acces to', config_dir, 'using a temporary dir instead')
import tempfile, atexit
config_dir = tempfile.mkdtemp(prefix='calibre-config-')
def cleanup_cdir():
try:
import shutil
shutil.rmtree(config_dir)
except:
pass
atexit.register(cleanup_cdir)
# }}}
@@ -251,8 +222,6 @@ def get_version():
v = v[:-2]
if is_running_from_develop:
v += '*'
if iswindows and is64bit:
v += ' [64bit]'
return v
@@ -261,33 +230,3 @@ def get_portable_base():
'Return path to the directory that contains calibre-portable.exe or None'
if isportable:
return os.path.dirname(os.path.dirname(os.getenv('CALIBRE_PORTABLE_BUILD')))
def get_windows_username():
'''
Return the user name of the currently logged in user as a unicode string.
Note that usernames on windows are case insensitive, the case of the value
returned depends on what the user typed into the login box at login time.
'''
username = plugins['winutil'][0].username
return username()
def get_windows_temp_path():
temp_path = plugins['winutil'][0].temp_path
return temp_path()
def get_windows_user_locale_name():
locale_name = plugins['winutil'][0].locale_name
return locale_name()
def get_windows_number_formats():
ans = getattr(get_windows_number_formats, 'ans', None)
if ans is None:
localeconv = plugins['winutil'][0].localeconv
d = localeconv()
thousands_sep, decimal_point = d['thousands_sep'], d['decimal_point']
ans = get_windows_number_formats.ans = thousands_sep, decimal_point
return ans

View File

@@ -2,14 +2,13 @@ import importlib
import sys
import zipfile
from ebook_converter.constants_old import numeric_version, iswindows, isosx
from ebook_converter.constants_old import numeric_version, isosx
from ebook_converter.ptempfile import PersistentTemporaryFile
platform = 'linux'
if iswindows:
platform = 'windows'
elif isosx:
if isosx:
platform = 'osx'
@@ -331,7 +330,7 @@ class MetadataReaderPlugin(Plugin):
#: For example: ``set(['lit', 'mobi', 'prc'])``
file_types = set()
supported_platforms = ['windows', 'osx', 'linux']
supported_platforms = ['osx', 'linux']
version = numeric_version
author = 'Kovid Goyal'
@@ -363,7 +362,7 @@ class MetadataWriterPlugin(Plugin):
#: For example: ``set(['lit', 'mobi', 'prc'])``
file_types = set()
supported_platforms = ['windows', 'osx', 'linux']
supported_platforms = ['osx', 'linux']
version = numeric_version
author = 'Kovid Goyal'
@@ -509,7 +508,7 @@ class CatalogPlugin(Plugin):
class InterfaceActionBase(Plugin):
supported_platforms = ['windows', 'osx', 'linux']
supported_platforms = ['osx', 'linux']
author = 'Kovid Goyal'
type = 'User interface action'
can_be_disabled = False
@@ -542,7 +541,7 @@ class PreferencesPlugin(Plugin):
various fields of the plugin control how it is categorized in the UI.
"""
supported_platforms = ['windows', 'osx', 'linux']
supported_platforms = ['osx', 'linux']
author = 'Kovid Goyal'
type = 'Preferences'
can_be_disabled = False
@@ -594,7 +593,7 @@ class PreferencesPlugin(Plugin):
class StoreBase(Plugin):
supported_platforms = ['windows', 'osx', 'linux']
supported_platforms = ['osx', 'linux']
author = 'John Schember'
type = 'Store'
# Information about the store. Should be in the primary language

View File

@@ -28,7 +28,7 @@ class PML2PMLZ(FileTypePlugin):
'a PML file to the library.')
version = numeric_version
file_types = {'pml'}
supported_platforms = ['windows', 'osx', 'linux']
supported_platforms = ['osx', 'linux']
on_import = True
def run(self, pmlfile):
@@ -60,7 +60,7 @@ class TXT2TXTZ(FileTypePlugin):
'the archive.')
version = numeric_version
file_types = {'txt', 'text'}
supported_platforms = ['windows', 'osx', 'linux']
supported_platforms = ['osx', 'linux']
on_import = True
def _get_image_references(self, txt, base_dir):

View File

@@ -103,7 +103,7 @@ class InputFormatPlugin(Plugin):
type = 'Conversion input'
can_be_disabled = False
supported_platforms = ['windows', 'osx', 'linux']
supported_platforms = ['osx', 'linux']
commit_name = None # unique name under which options for this plugin are saved
ui_data = None
@@ -241,7 +241,7 @@ class OutputFormatPlugin(Plugin):
type = 'Conversion output'
can_be_disabled = False
supported_platforms = ['windows', 'osx', 'linux']
supported_platforms = ['osx', 'linux']
commit_name = None # unique name under which options for this plugin are saved
ui_data = None

View File

@@ -41,7 +41,7 @@ class Plugin(_Plugin):
class InputProfile(Plugin):
author = 'Kovid Goyal'
supported_platforms = {'windows', 'osx', 'linux'}
supported_platforms = {'osx', 'linux'}
can_be_disabled = False
type = 'Input profile'
@@ -239,7 +239,7 @@ input_profiles.sort(key=lambda x: x.name.lower())
class OutputProfile(Plugin):
author = 'Kovid Goyal'
supported_platforms = {'windows', 'osx', 'linux'}
supported_platforms = {'osx', 'linux'}
can_be_disabled = False
type = 'Output profile'

View File

@@ -2,7 +2,6 @@ import os
from collections import namedtuple
from ebook_converter import prints
from ebook_converter.constants_old import iswindows
from ebook_converter.customize import Plugin
@@ -153,7 +152,7 @@ class DevicePlugin(Plugin):
else:
products = self.PRODUCT_ID if hasattr(self.PRODUCT_ID, '__len__') else [self.PRODUCT_ID]
ch = self.can_handle_windows if iswindows else self.can_handle
ch = self.can_handle
for vid in vendors_on_system.intersection(vendors):
for dev in devices_on_system:
cvid, pid, bcd = dev[:3]
@@ -226,23 +225,6 @@ class DevicePlugin(Plugin):
"""
raise NotImplementedError()
def can_handle_windows(self, usbdevice, debug=False):
'''
Optional method to perform further checks on a device to see if this driver
is capable of handling it. If it is not it should return False. This method
is only called after the vendor, product ids and the bcd have matched, so
it can do some relatively time intensive checks. The default implementation
returns True. This method is called only on Windows. See also
:meth:`can_handle`.
Note that for devices based on USBMS this method by default delegates
to :meth:`can_handle`. So you only need to override :meth:`can_handle`
in your subclass of USBMS.
:param usbdevice: A usbdevice as returned by :func:`calibre.devices.winusb.scan_usb_devices`
'''
return True
def can_handle(self, device_info, debug=False):
'''
Unix version of :meth:`can_handle_windows`.

View File

@@ -2,7 +2,6 @@ import os
from lxml.html.builder import IMG, HR
from ebook_converter.constants_old import iswindows
from ebook_converter.ebooks.docx.names import barename
from ebook_converter.utils.filenames import ascii_filename
from ebook_converter.utils.img import resize_to_fit, image_to_data
@@ -123,8 +122,6 @@ class Images(object):
def read_image_data(self, fname, base=None):
if fname.startswith('file://'):
src = fname[len('file://'):]
if iswindows and src and src[0] == '/':
src = src[1:]
if not src or not os.path.exists(src):
raise LinkedImageNotFound(src)
with open(src, 'rb') as rawsrc:

View File

@@ -9,7 +9,6 @@ import urllib.parse
from ebook_converter.ebooks.oeb.base import urlunquote
from ebook_converter.ebooks.chardet import detect_xml_encoding
from ebook_converter.constants_old import iswindows
from ebook_converter import unicode_path, replace_entities
@@ -22,9 +21,6 @@ class Link(object):
def url_to_local_path(cls, url, base):
path = url.path
isabs = False
if iswindows and path.startswith('/'):
path = path[1:]
isabs = True
path = urllib.parse.urlunparse(('', '', path, url.params, url.query,
''))
path = urlunquote(path)

View File

@@ -19,7 +19,7 @@ class HTML2ZIP(FileTypePlugin):
''')
version = numeric_version
file_types = {'html', 'htm', 'xhtml', 'xhtm', 'shtm', 'shtml'}
supported_platforms = ['windows', 'osx', 'linux']
supported_platforms = ['osx', 'linux']
on_import = True
def run(self, htmlfile):

View File

@@ -44,7 +44,7 @@ class KPFExtract(FileTypePlugin):
'KPF files. Note this will not contain any edits made in '
'the Kindle Create program itself.')
file_types = {'kpf'}
supported_platforms = ['windows', 'osx', 'linux']
supported_platforms = ['osx', 'linux']
on_import = True
def run(self, archive):
@@ -67,7 +67,7 @@ class ArchiveExtract(FileTypePlugin):
'RAR). Also try to autodetect if they are actually CBZ/CBR '
'files.')
file_types = {'zip', 'rar'}
supported_platforms = ['windows', 'osx', 'linux']
supported_platforms = ['osx', 'linux']
on_import = True
def run(self, archive):

View File

@@ -5,7 +5,6 @@ import os, subprocess, shutil, re
from functools import partial
from ebook_converter import prints
from ebook_converter.constants_old import iswindows
from ebook_converter.ptempfile import TemporaryDirectory
from ebook_converter.ebooks.metadata import (
MetaInformation, string_to_authors, check_isbn, check_doi)
@@ -18,7 +17,7 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
def get_tools():
from ebook_converter.ebooks.pdf.pdftohtml import PDFTOHTML
base = os.path.dirname(PDFTOHTML)
suffix = '.exe' if iswindows else ''
suffix = ''
pdfinfo = os.path.join(base, 'pdfinfo') + suffix
pdftoppm = os.path.join(base, 'pdftoppm') + suffix
return pdfinfo, pdftoppm
@@ -87,9 +86,6 @@ def page_images(pdfpath, outputdir='.', first=1, last=1, image_format='jpeg', pr
pdftoppm = get_tools()[1]
outputdir = os.path.abspath(outputdir)
args = {}
if iswindows:
import win32process as w
args['creationflags'] = w.HIGH_PRIORITY_CLASS | w.CREATE_NO_WINDOW
try:
subprocess.check_call([
pdftoppm, '-cropbox', '-' + image_format, '-f', str(first),

View File

@@ -3,7 +3,7 @@ from struct import pack
from io import BytesIO
from ebook_converter.ebooks.oeb import base
from ebook_converter.constants_old import iswindows, isosx
from ebook_converter.constants_old import isosx
from ebook_converter.ebooks.mobi.utils import (utf8_text, to_base)
from ebook_converter.utils.localization import lang_as_iso639_1
from ebook_converter.ebooks.metadata import authors_to_sort_string
@@ -150,8 +150,8 @@ def build_exth(metadata, prefer_author_sort=False, is_periodical=False,
nrecs += 1
if be_kindlegen2:
mv = 200 if iswindows else 202 if isosx else 201
vals = {204:mv, 205:2, 206:9, 207:0}
mv = 201
vals = {204: mv, 205: 2, 206: 9, 207: 0}
elif is_periodical:
# Pretend to be amazon's super secret periodical generator
vals = {204:201, 205:2, 206:0, 207:101}

View File

@@ -8,7 +8,6 @@ import os
import re
import shutil
import sys
import time
import unicodedata
import urllib.parse
import uuid
@@ -18,7 +17,6 @@ from lxml import etree
from ebook_converter import constants as const
from ebook_converter import CurrentDir, walk
from ebook_converter.constants_old import iswindows
from ebook_converter.customize.ui import plugin_for_input_format, plugin_for_output_format
from ebook_converter.ebooks import escape_xpath_attr
from ebook_converter.ebooks.chardet import xml_to_unicode
@@ -109,10 +107,7 @@ def href_to_name(href, root, base=None):
if purl.scheme or not purl.path:
return None
href = oeb_base.urlunquote(purl.path)
if iswindows and ':' in href:
# path manipulations on windows fail for paths with : in them, so we
# assume all such paths are invalid/absolute paths.
return None
fullpath = os.path.join(base, *href.split('/'))
return unicodedata.normalize('NFC', abspath_to_name(fullpath, root))
@@ -1040,10 +1035,8 @@ class Container(ContainerBase): # {{{
try:
os.unlink(path)
except EnvironmentError:
if not iswindows:
raise
time.sleep(1) # Wait for whatever has locked the file to release it
os.unlink(path)
raise
os.rename(temp, path)
return path

View File

@@ -9,7 +9,6 @@ from xml.sax import saxutils
from ebook_converter import constants as const
from ebook_converter.utils import date
from ebook_converter.constants_old import iswindows
from ebook_converter.ebooks.oeb import base
from ebook_converter.ebooks.oeb.base import XPath, xml2text, urlnormalize
from ebook_converter.library.comments import comments_to_html, markdown
@@ -419,7 +418,5 @@ def referenced_images(root):
src = img.get('src')
if src.startswith('file://'):
path = src[7:]
if iswindows and path.startswith('/'):
path = path[1:]
if os.path.exists(path):
yield img, path

View File

@@ -8,7 +8,7 @@ import sys
from lxml import etree
from ebook_converter import CurrentDir, xml_replace_entities, prints
from ebook_converter.constants_old import isbsd, islinux, isosx, iswindows
from ebook_converter.constants_old import isbsd, islinux, isosx
from ebook_converter.ebooks import ConversionError, DRMError
from ebook_converter.ebooks.chardet import xml_to_unicode
from ebook_converter.ptempfile import PersistentTemporaryFile
@@ -20,8 +20,6 @@ PDFTOHTML = 'pdftohtml'
def popen(cmd, **kw):
if iswindows:
kw['creationflags'] = 0x08
return subprocess.Popen(cmd, **kw)
@@ -29,11 +27,6 @@ if isosx and hasattr(sys, 'frameworks_dir'):
base = os.path.join(os.path.dirname(sys.frameworks_dir), 'utils.app',
'Contents', 'MacOS')
PDFTOHTML = os.path.join(base, PDFTOHTML)
if iswindows and hasattr(sys, 'frozen'):
base = os.path.dirname(sys.executable)
if hasattr(sys, 'new_app_layout'):
base = sys.extensions_location
PDFTOHTML = os.path.join(base, 'pdftohtml.exe')
if (islinux or isbsd) and getattr(sys, 'frozen', False):
PDFTOHTML = os.path.join(sys.executables_location, 'bin', 'pdftohtml')

View File

@@ -20,7 +20,7 @@ class BIBTEX(CatalogPlugin):
name = 'Catalog_BIBTEX'
description = 'BIBTEX catalog generator'
supported_platforms = ['windows', 'osx', 'linux']
supported_platforms = ['osx', 'linux']
author = 'Sengian'
version = (1, 0, 0)
file_types = {'bib'}

View File

@@ -19,7 +19,7 @@ class CSV_XML(CatalogPlugin):
name = 'Catalog_CSV_XML'
description = 'CSV/XML catalog generator'
supported_platforms = ['windows', 'osx', 'linux']
supported_platforms = ['osx', 'linux']
author = 'Greg Riker'
version = (1, 0, 0)
file_types = {'csv', 'xml'}

View File

@@ -19,7 +19,7 @@ class EPUB_MOBI(CatalogPlugin):
name = 'Catalog_EPUB_MOBI'
description = 'AZW3/EPUB/MOBI catalog generator'
supported_platforms = ['windows', 'osx', 'linux']
supported_platforms = ['osx', 'linux']
minimum_calibre_version = (0, 7, 40)
author = 'Greg Riker'
version = (1, 0, 0)

View File

@@ -6,8 +6,8 @@ being closed.
"""
import tempfile, os, atexit
from ebook_converter.constants_old import (__version__, __appname__, filesystem_encoding,
iswindows, get_windows_temp_path, isosx)
from ebook_converter.constants_old import __version__, __appname__, \
filesystem_encoding, isosx
def cleanup(path):
@@ -52,9 +52,7 @@ def determined_remove_dir(x):
def app_prefix(prefix):
if iswindows:
return '%s_'%__appname__
return '%s_%s_%s'%(__appname__, __version__, prefix)
return '%s_%s_%s' % (__appname__, __version__, prefix)
_osx_cache_dir = None
@@ -99,19 +97,9 @@ def base_dir():
_base_dir = td
else:
base = os.environ.get('CALIBRE_TEMP_DIR', None)
if base is not None and iswindows:
base = os.getenv('CALIBRE_TEMP_DIR')
prefix = app_prefix('tmp_')
if base is None:
if iswindows:
# On windows, if the TMP env var points to a path that
# cannot be encoded using the mbcs encoding, then the
# python 2 tempfile algorithm for getting the temporary
# directory breaks. So we use the win32 api to get a
# unicode temp path instead. See
# https://bugs.launchpad.net/bugs/937389
base = get_windows_temp_path()
elif isosx:
if isosx:
# Use the cache dir rather than the temp dir for temp files as Apple
# thinks deleting unused temp files is a good idea. See note under
# _CS_DARWIN_USER_TEMP_DIR here
@@ -119,7 +107,7 @@ def base_dir():
base = osx_cache_dir()
_base_dir = tempfile.mkdtemp(prefix=prefix, dir=base)
atexit.register(determined_remove_dir if iswindows else remove_dir, _base_dir)
atexit.register(remove_dir, _base_dir)
try:
tempfile.gettempdir()

View File

@@ -1,12 +1,8 @@
__license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
__docformat__ = 'restructuredtext en'
'''
"""
Perform various initialization tasks.
'''
"""
import builtins
import fcntl
import locale
import sys
@@ -16,7 +12,6 @@ from ebook_converter import constants_old
builtins.__dict__['dynamic_property'] = lambda func: func(None)
_run_once = False
winutil = winutilerror = None
@@ -36,18 +31,8 @@ if not _run_once:
spec = m.__spec__
return spec
sys.meta_path.insert(0, DeVendor())
#
# Platform specific modules
if constants_old.iswindows:
winutil, winutilerror = constants_old.plugins['winutil']
if not winutil:
raise RuntimeError('Failed to load the winutil plugin: %s'%winutilerror)
if len(sys.argv) > 1 and not isinstance(sys.argv[1], str):
sys.argv[1:] = winutil.argv()[1-len(sys.argv):]
# Ensure that all temp files/dirs are created under a calibre tmp dir
from ebook_converter.ptempfile import base_dir
try:
@@ -66,20 +51,16 @@ if not _run_once:
#
# Ensure that the max number of open files is at least 1024
if constants_old.iswindows:
# See https://msdn.microsoft.com/en-us/library/6e3b887c.aspx
if hasattr(winutil, 'setmaxstdio'):
winutil.setmaxstdio(max(1024, winutil.getmaxstdio()))
else:
import resource
soft, hard = resource.getrlimit(resource.RLIMIT_NOFILE)
if soft < 1024:
try:
resource.setrlimit(resource.RLIMIT_NOFILE, (min(1024, hard), hard))
except Exception:
if constants_old.DEBUG:
import traceback
traceback.print_exc()
import resource
soft, hard = resource.getrlimit(resource.RLIMIT_NOFILE)
if soft < 1024:
try:
resource.setrlimit(resource.RLIMIT_NOFILE, (min(1024, hard), hard))
except Exception:
if constants_old.DEBUG:
import traceback
traceback.print_exc()
#
# Setup resources
@@ -152,18 +133,9 @@ def test_lopen():
n = 'f\xe4llen'
print('testing open()')
if constants_old.iswindows:
import msvcrt, win32api
def assert_not_inheritable(f):
if win32api.GetHandleInformation(msvcrt.get_osfhandle(f.fileno())) & 0b1:
raise SystemExit('File handle is inheritable!')
else:
import fcntl
def assert_not_inheritable(f):
if not fcntl.fcntl(f, fcntl.F_GETFD) & fcntl.FD_CLOEXEC:
raise SystemExit('File handle is inheritable!')
def assert_not_inheritable(f):
if not fcntl.fcntl(f, fcntl.F_GETFD) & fcntl.FD_CLOEXEC:
raise SystemExit('File handle is inheritable!')
def copen(*args):
ans = open(*args)

View File

@@ -88,9 +88,7 @@ class OptionParser(optparse.OptionParser):
fg='cyan')
usage += ('\n\nWhenever you pass arguments to %prog that have spaces '
'in them, enclose the arguments in quotation marks. For '
'example: "{}"\n\n').format("C:\\some path with spaces"
if constants_old.iswindows
else '/some path/with spaces')
'example: "{}"\n\n').format('/some path/with spaces')
if version is None:
version = '%%prog (%s %s)' % (constants_old.__appname__,
constants.VERSION)

View File

@@ -14,7 +14,6 @@ import base64
from ebook_converter.constants_old import CONFIG_DIR_MODE
from ebook_converter.constants_old import config_dir
from ebook_converter.constants_old import filesystem_encoding
from ebook_converter.constants_old import iswindows
from ebook_converter.constants_old import preferred_encoding
from ebook_converter.utils.date import isoformat
from ebook_converter.utils import iso8601
@@ -79,7 +78,7 @@ def from_json(obj):
def force_unicode(x):
try:
return x.decode('mbcs' if iswindows else preferred_encoding)
return x.decode(preferred_encoding)
except UnicodeDecodeError:
try:
return x.decode(filesystem_encoding)

View File

@@ -3,7 +3,7 @@ import datetime
import time
import functools
from ebook_converter.constants_old import iswindows, isosx, plugins, preferred_encoding
from ebook_converter.constants_old import isosx, plugins, preferred_encoding
from ebook_converter.utils.iso8601 import utc_tz, local_tz, UNDEFINED_DATE
from ebook_converter.utils.localization import lcdata
@@ -13,38 +13,21 @@ _local_tz = local_tz
# When parsing ambiguous dates that could be either dd-MM Or MM-dd use the
# user's locale preferences
if iswindows:
import ctypes
LOCALE_SSHORTDATE, LOCALE_USER_DEFAULT = 0x1f, 0
buf = ctypes.create_string_buffer(b'\0', 255)
try:
ctypes.windll.kernel32.GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SSHORTDATE, buf, 255)
parse_date_day_first = buf.value.index(b'd') < buf.value.index(b'M')
except:
parse_date_day_first = False
del ctypes, LOCALE_SSHORTDATE, buf, LOCALE_USER_DEFAULT
elif isosx:
try:
date_fmt = plugins['usbobserver'][0].date_format()
parse_date_day_first = date_fmt.index('d') < date_fmt.index('M')
except:
parse_date_day_first = False
else:
try:
def first_index(raw, queries):
for q in queries:
try:
return raw.index(q)
except ValueError:
pass
return -1
try:
def first_index(raw, queries):
for q in queries:
try:
return raw.index(q)
except ValueError:
pass
return -1
import locale
raw = locale.nl_langinfo(locale.D_FMT)
parse_date_day_first = first_index(raw, ('%d', '%a', '%A')) < first_index(raw, ('%m', '%b', '%B'))
del raw, first_index
except:
parse_date_day_first = False
import locale
raw = locale.nl_langinfo(locale.D_FMT)
parse_date_day_first = first_index(raw, ('%d', '%a', '%A')) < first_index(raw, ('%m', '%b', '%B'))
del raw, first_index
except:
parse_date_day_first = False
DEFAULT_DATE = datetime.datetime(2000,1,1, tzinfo=utc_tz)
EPOCH = datetime.datetime(1970, 1, 1, tzinfo=_utc_tz)
@@ -214,15 +197,10 @@ def strftime(fmt, t=None):
t[0] = replacement
t = time.struct_time(t)
ans = None
if iswindows:
if isinstance(fmt, bytes):
fmt = fmt.decode('mbcs', 'replace')
fmt = fmt.replace('%e', '%#d')
ans = plugins['winutil'][0].strftime(fmt, t)
else:
ans = time.strftime(fmt, t)
if isinstance(ans, bytes):
ans = ans.decode(preferred_encoding, 'replace')
ans = time.strftime(fmt, t)
if isinstance(ans, bytes):
ans = ans.decode(preferred_encoding, 'replace')
if early_year:
ans = ans.replace('_early year hack##', str(orig_year))
return ans

View File

@@ -10,7 +10,7 @@ from math import ceil
from ebook_converter import force_unicode, prints, sanitize_file_name
from ebook_converter.constants_old import (
filesystem_encoding, iswindows, plugins, preferred_encoding, isosx
filesystem_encoding, plugins, preferred_encoding, isosx
)
from ebook_converter.utils.localization import get_udc
@@ -47,9 +47,9 @@ def shorten_component(s, by_what):
def limit_component(x, limit=254):
# windows and macs use ytf-16 codepoints for length, linux uses arbitrary
# windows and macs use utf-16 codepoints for length, linux uses arbitrary
# binary data, but we will assume utf-8
filename_encoding_for_length = 'utf-16' if iswindows or isosx else 'utf-8'
filename_encoding_for_length = 'utf-8'
def encoded_length():
q = x if isinstance(x, bytes) else x.encode(filename_encoding_for_length)
@@ -100,7 +100,7 @@ def shorten_components_to(length, components, more_to_take=0, last_has_extension
def find_executable_in_path(name, path=None):
if path is None:
path = os.environ.get('PATH', '')
exts = '.exe .cmd .bat'.split() if iswindows and not name.endswith('.exe') else ('',)
exts = ('',)
path = path.split(os.pathsep)
for x in path:
for ext in exts:
@@ -118,15 +118,14 @@ def is_case_sensitive(path):
apply to the filesystem containing the directory in path.
'''
is_case_sensitive = False
if not iswindows:
name1, name2 = ('calibre_test_case_sensitivity.txt',
'calibre_TesT_CaSe_sensitiVitY.Txt')
f1, f2 = os.path.join(path, name1), os.path.join(path, name2)
if os.path.exists(f1):
os.remove(f1)
open(f1, 'w').close()
is_case_sensitive = not os.path.exists(f2)
name1, name2 = ('calibre_test_case_sensitivity.txt',
'calibre_TesT_CaSe_sensitiVitY.Txt')
f1, f2 = os.path.join(path, name1), os.path.join(path, name2)
if os.path.exists(f1):
os.remove(f1)
open(f1, 'w').close()
is_case_sensitive = not os.path.exists(f2)
os.remove(f1)
return is_case_sensitive
@@ -162,10 +161,6 @@ def case_preserving_open_file(path, mode='wb', mkdir_mode=0o777):
raise ValueError('Invalid path: %r'%path)
cpath = sep
if iswindows:
# Always upper case the drive letter and add a trailing slash so that
# the first os.listdir works correctly
cpath = components[0].upper() + sep
bdir = path if mode is None else os.path.dirname(path)
if not os.path.exists(bdir):
@@ -215,37 +210,6 @@ def case_preserving_open_file(path, mode='wb', mkdir_mode=0o777):
return ans, fpath
def windows_get_fileid(path):
''' The fileid uniquely identifies actual file contents (it is the same for
all hardlinks to a file). Similar to inode number on linux. '''
import win32file
from pywintypes import error
if isinstance(path, bytes):
path = path.decode(filesystem_encoding)
try:
h = win32file.CreateFileW(path, 0, 0, None, win32file.OPEN_EXISTING,
win32file.FILE_FLAG_BACKUP_SEMANTICS, 0)
try:
data = win32file.GetFileInformationByHandle(h)
finally:
win32file.CloseHandle(h)
except (error, EnvironmentError):
return None
return data[4], data[8], data[9]
def samefile_windows(src, dst):
samestring = (os.path.normcase(os.path.abspath(src)) ==
os.path.normcase(os.path.abspath(dst)))
if samestring:
return True
a, b = windows_get_fileid(src), windows_get_fileid(dst)
if a is None and b is None:
return False
return a == b
def samefile(src, dst):
'''
Check if two paths point to the same actual file on the filesystem. Handles
@@ -257,9 +221,6 @@ def samefile(src, dst):
case) even if the file does not exist. This is because I have no way of
knowing how reliable the GetFileInformationByHandle method is.
'''
if iswindows:
return samefile_windows(src, dst)
if hasattr(os.path, 'samefile'):
# Unix
try:
@@ -273,243 +234,20 @@ def samefile(src, dst):
return samestring
def windows_get_size(path):
''' On windows file sizes are only accurately stored in the actual file,
not in the directory entry (which could be out of date). So we open the
file, and get the actual size. '''
import win32file
if isinstance(path, bytes):
path = path.decode(filesystem_encoding)
h = win32file.CreateFileW(
path, 0, win32file.FILE_SHARE_READ | win32file.FILE_SHARE_WRITE | win32file.FILE_SHARE_DELETE,
None, win32file.OPEN_EXISTING, 0, None)
try:
return win32file.GetFileSize(h)
finally:
win32file.CloseHandle(h)
def windows_hardlink(src, dest):
import win32file, pywintypes
try:
win32file.CreateHardLink(dest, src)
except pywintypes.error as e:
msg = 'Creating hardlink from %s to %s failed: %%s' % (src, dest)
raise OSError(msg % e)
src_size = os.path.getsize(src)
# We open and close dest, to ensure its directory entry is updated
# see http://blogs.msdn.com/b/oldnewthing/archive/2011/12/26/10251026.aspx
for i in range(10):
# If we are on a network filesystem, we have to wait for some indeterminate time, since
# network file systems are the best thing since sliced bread
try:
if windows_get_size(dest) == src_size:
return
except EnvironmentError:
pass
time.sleep(0.3)
sz = windows_get_size(dest)
if sz != src_size:
msg = 'Creating hardlink from %s to %s failed: %%s' % (src, dest)
raise OSError(msg % ('hardlink size: %d not the same as source size' % sz))
def windows_fast_hardlink(src, dest):
import win32file, pywintypes
try:
win32file.CreateHardLink(dest, src)
except pywintypes.error as e:
msg = 'Creating hardlink from %s to %s failed: %%s' % (src, dest)
raise OSError(msg % e)
ssz, dsz = windows_get_size(src), windows_get_size(dest)
if ssz != dsz:
msg = 'Creating hardlink from %s to %s failed: %%s' % (src, dest)
raise OSError(msg % ('hardlink size: %d not the same as source size: %s' % (dsz, ssz)))
def windows_nlinks(path):
import win32file
dwFlagsAndAttributes = win32file.FILE_FLAG_BACKUP_SEMANTICS if os.path.isdir(path) else 0
if isinstance(path, bytes):
path = path.decode(filesystem_encoding)
handle = win32file.CreateFileW(path, win32file.GENERIC_READ, win32file.FILE_SHARE_READ, None, win32file.OPEN_EXISTING, dwFlagsAndAttributes, None)
try:
return win32file.GetFileInformationByHandle(handle)[7]
finally:
handle.Close()
class WindowsAtomicFolderMove(object):
'''
Move all the files inside a specified folder in an atomic fashion,
preventing any other process from locking a file while the operation is
incomplete. Raises an IOError if another process has locked a file before
the operation starts. Note that this only operates on the files in the
folder, not any sub-folders.
'''
def __init__(self, path):
self.handle_map = {}
import win32file, winerror
from pywintypes import error
from collections import defaultdict
if isinstance(path, bytes):
path = path.decode(filesystem_encoding)
if not os.path.exists(path):
return
names = os.listdir(path)
name_to_fileid = {x:windows_get_fileid(os.path.join(path, x)) for x in names}
fileid_to_names = defaultdict(set)
for name, fileid in name_to_fileid.items():
fileid_to_names[fileid].add(name)
for x in names:
f = os.path.normcase(os.path.abspath(os.path.join(path, x)))
if not os.path.isfile(f):
continue
try:
# Ensure the file is not read-only
win32file.SetFileAttributes(f, win32file.FILE_ATTRIBUTE_NORMAL)
except:
pass
try:
h = win32file.CreateFileW(f, win32file.GENERIC_READ,
win32file.FILE_SHARE_DELETE, None,
win32file.OPEN_EXISTING, win32file.FILE_FLAG_SEQUENTIAL_SCAN, 0)
except error as e:
if getattr(e, 'winerror', 0) == winerror.ERROR_SHARING_VIOLATION:
# The file could be a hardlink to an already opened file,
# in which case we use the same handle for both files
fileid = name_to_fileid[x]
found = False
if fileid is not None:
for other in fileid_to_names[fileid]:
other = os.path.normcase(os.path.abspath(os.path.join(path, other)))
if other in self.handle_map:
self.handle_map[f] = self.handle_map[other]
found = True
break
if found:
continue
self.close_handles()
if getattr(e, 'winerror', 0) == winerror.ERROR_SHARING_VIOLATION:
err = IOError(errno.EACCES,
'File is open in another process')
err.filename = f
raise err
prints('CreateFile failed for: %r' % f)
raise
except:
self.close_handles()
prints('CreateFile failed for: %r' % f)
raise
self.handle_map[f] = h
def copy_path_to(self, path, dest):
import win32file
handle = None
for p, h in self.handle_map.items():
if samefile_windows(path, p):
handle = h
break
if handle is None:
if os.path.exists(path):
raise ValueError('The file %r did not exist when this move'
' operation was started'%path)
else:
raise ValueError('The file %r does not exist'%path)
try:
windows_hardlink(path, dest)
return
except:
pass
win32file.SetFilePointer(handle, 0, win32file.FILE_BEGIN)
with open(dest, 'wb') as f:
while True:
hr, raw = win32file.ReadFile(handle, 1024*1024)
if hr != 0:
raise IOError(hr, 'Error while reading from %r'%path)
if not raw:
break
f.write(raw)
def release_file(self, path):
' Release the lock on the file pointed to by path. Will also release the lock on any hardlinks to path '
key = None
for p, h in self.handle_map.items():
if samefile_windows(path, p):
key = (p, h)
break
if key is not None:
import win32file
win32file.CloseHandle(key[1])
remove = [f for f, h in self.handle_map.items() if h is key[1]]
for x in remove:
self.handle_map.pop(x)
def close_handles(self):
import win32file
for h in self.handle_map.values():
win32file.CloseHandle(h)
self.handle_map = {}
def delete_originals(self):
import win32file
for path in self.handle_map:
win32file.DeleteFile(path)
self.close_handles()
def hardlink_file(src, dest):
if iswindows:
windows_hardlink(src, dest)
return
os.link(src, dest)
def nlinks_file(path):
' Return number of hardlinks to the file '
if iswindows:
return windows_nlinks(path)
return os.stat(path).st_nlink
if iswindows:
def rename_file(a, b):
move_file = plugins['winutil'][0].move_file
if isinstance(a, bytes):
a = a.decode('mbcs')
if isinstance(b, bytes):
b = b.decode('mbcs')
move_file(a, b)
def atomic_rename(oldpath, newpath):
'''Replace the file newpath with the file oldpath. Can fail if the files
are on different volumes. If succeeds, guaranteed to be atomic. newpath may
or may not exist. If it exists, it is replaced. '''
if iswindows:
for i in range(10):
try:
rename_file(oldpath, newpath)
break
except Exception:
if i > 8:
raise
# Try the rename repeatedly in case something like a virus
# scanner has opened one of the files (I love windows)
time.sleep(1)
else:
os.rename(oldpath, newpath)
os.rename(oldpath, newpath)
def remove_dir_if_empty(path, ignore_metadata_caches=False):
@@ -572,20 +310,7 @@ def copyfile(src, dest):
def get_hardlink_function(src, dest):
if iswindows:
import win32file, win32api
colon = b':' if isinstance(dest, bytes) else ':'
root = dest[0] + colon
try:
is_suitable = win32file.GetDriveType(root) not in (win32file.DRIVE_REMOTE, win32file.DRIVE_CDROM)
# See https://msdn.microsoft.com/en-us/library/windows/desktop/aa364993(v=vs.85).aspx
supports_hard_links = win32api.GetVolumeInformation(root + os.sep)[3] & 0x00400000
except Exception:
supports_hard_links = is_suitable = False
hardlink = windows_fast_hardlink if is_suitable and supports_hard_links and src[0].lower() == dest[0].lower() else None
else:
hardlink = os.link
return hardlink
return os.link
def copyfile_using_links(path, dest, dest_is_dir=True, filecopyfunc=copyfile):

View File

@@ -3,7 +3,7 @@ from collections import defaultdict
from threading import Thread
from ebook_converter import walk, prints
from ebook_converter.constants_old import iswindows, isosx
from ebook_converter.constants_old import isosx
from ebook_converter.constants_old import plugins, DEBUG
from ebook_converter.constants_old import filesystem_encoding
from ebook_converter.utils.fonts.metadata import FontMetadata, UnsupportedFont
@@ -90,14 +90,6 @@ def fc_list():
def font_dirs():
if iswindows:
winutil, err = plugins['winutil']
if err:
raise RuntimeError('Failed to load winutil: %s' % err)
try:
return [winutil.special_folder_path(winutil.CSIDL_FONTS)]
except ValueError:
return [r'C:\Windows\Fonts']
if isosx:
return [
'/Library/Fonts',

View File

@@ -6,10 +6,6 @@ from ebook_converter.utils.fonts.sfnt import UnknownTable, max_power_of_two
from ebook_converter.utils.fonts.sfnt.errors import UnsupportedFont
__license__ = 'GPL v3'
__copyright__ = '2012, Kovid Goyal <kovid at kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
# Note that the code for creating a BMP table (cmap format 4) is taken with
# thanks from the fonttools project (BSD licensed).

View File

@@ -12,7 +12,7 @@ from threading import Thread
#from PyQt5.QtGui import QColor, QImage, QImageReader, QImageWriter, QPixmap, QTransform
from ebook_converter import fit_image, force_unicode
from ebook_converter.constants_old import iswindows, plugins
from ebook_converter.constants_old import plugins
from ebook_converter.ptempfile import TemporaryDirectory
from ebook_converter.utils.config_base import tweaks
from ebook_converter.utils.filenames import atomic_rename
@@ -38,8 +38,6 @@ def normalize_format_name(fmt):
def get_exe_path(name):
from ebook_converter.ebooks.pdf.pdftohtml import PDFTOHTML
base = os.path.dirname(PDFTOHTML)
if iswindows:
name += '-calibre.exe'
if not base:
return name
return os.path.join(base, name)
@@ -47,12 +45,10 @@ def get_exe_path(name):
def load_jxr_data(data):
with TemporaryDirectory() as tdir:
if iswindows and isinstance(tdir, str):
tdir = tdir.encode('mbcs')
with open(os.path.join(tdir, 'input.jxr'), 'wb') as f:
f.write(data)
cmd = [get_exe_path('JxrDecApp'), '-i', 'input.jxr', '-o', 'output.tif']
creationflags = 0x08 if iswindows else 0
creationflags = 0
subprocess.Popen(cmd, cwd=tdir, stdout=open(os.devnull, 'wb'), stderr=subprocess.STDOUT, creationflags=creationflags).wait()
i = QImage()
if not i.load(os.path.join(tdir, 'output.tif')):
@@ -548,7 +544,7 @@ def run_optimizer(file_path, cmd, as_filter=False, input_data=None):
stdin = subprocess.PIPE if as_filter else None
stderr = subprocess.PIPE if as_filter else subprocess.STDOUT
creationflags = 0x08 if iswindows else 0
creationflags = 0
p = subprocess.Popen(cmd, cwd=cwd, stdout=subprocess.PIPE, stderr=stderr, stdin=stdin, creationflags=creationflags)
stderr = p.stderr if as_filter else p.stdout
if as_filter:
@@ -652,7 +648,7 @@ def test(): # {{{
despeckle_image(img)
remove_borders_from_image(img)
image_to_data(img, fmt='GIF')
raw = subprocess.Popen([get_exe_path('JxrDecApp'), '-h'], creationflags=0x08 if iswindows else 0, stdout=subprocess.PIPE).stdout.read()
raw = subprocess.Popen([get_exe_path('JxrDecApp'), '-h'], creationflags=0, stdout=subprocess.PIPE).stdout.read()
if b'JPEG XR Decoder Utility' not in raw:
raise SystemExit('Failed to run JxrDecApp')
# }}}

View File

@@ -6,16 +6,10 @@ import threading
from ebook_converter import force_unicode
from ebook_converter.constants_old import filesystem_encoding
from ebook_converter.constants_old import get_windows_username
from ebook_converter.constants_old import islinux
from ebook_converter.constants_old import iswindows
from ebook_converter.utils.filenames import ascii_filename
__license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
VADDRESS = None
@@ -31,34 +25,24 @@ def eintr_retry_call(func, *args, **kwargs):
@functools.lru_cache()
def socket_address(which):
if iswindows:
ans = r'\\.\pipe\Calibre' + which
try:
user = get_windows_username()
except Exception:
user = None
if user:
user = ascii_filename(user).replace(' ', '_')
if user:
ans += '-' + user[:100] + 'x'
user = force_unicode(os.environ.get('USER') or os.path.basename(os.path.expanduser('~')), filesystem_encoding)
sock_name = '{}-calibre-{}.socket'.format(ascii_filename(user).replace(' ', '_'), which)
if islinux:
ans = '\0' + sock_name
else:
user = force_unicode(os.environ.get('USER') or os.path.basename(os.path.expanduser('~')), filesystem_encoding)
sock_name = '{}-calibre-{}.socket'.format(ascii_filename(user).replace(' ', '_'), which)
if islinux:
ans = '\0' + sock_name
else:
from tempfile import gettempdir
tmp = force_unicode(gettempdir(), filesystem_encoding)
ans = os.path.join(tmp, sock_name)
from tempfile import gettempdir
tmp = force_unicode(gettempdir(), filesystem_encoding)
ans = os.path.join(tmp, sock_name)
return ans
def gui_socket_address():
return socket_address('GUI' if iswindows else 'gui')
return socket_address('gui')
def viewer_socket_address():
return socket_address('Viewer' if iswindows else 'viewer')
return socket_address('viewer')
class RC(threading.Thread):

View File

@@ -10,10 +10,6 @@ from collections import namedtuple, OrderedDict
from tempfile import SpooledTemporaryFile
__license__ = 'GPL v3'
__copyright__ = '2012, Kovid Goyal <kovid at kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
HEADER_SIG = 0x04034b50
HEADER_BYTE_SIG = pack(b'<L', HEADER_SIG)
local_header_fmt = b'<L5HL2L2H'
@@ -27,18 +23,8 @@ LocalHeader = namedtuple('LocalHeader',
'filename extra')
if hasattr(sys, 'getwindowsversion'):
windows_reserved_filenames = (
'CON', 'PRN', 'AUX', 'CLOCK$', 'NUL' 'COM0', 'COM1', 'COM2', 'COM3',
'COM4', 'COM5', 'COM6', 'COM7', 'COM8', 'COM9' 'LPT0', 'LPT1', 'LPT2',
'LPT3', 'LPT4', 'LPT5', 'LPT6', 'LPT7', 'LPT8', 'LPT9')
def is_reserved_filename(x):
base = x.partition('.')[0].upper()
return base in windows_reserved_filenames
else:
def is_reserved_filename(x):
return False
def is_reserved_filename(x):
return False
def decode_arcname(name):

View File

@@ -36,11 +36,7 @@ def find_tests():
eq(fname, f.name)
f = share_open(fname, 'rb')
eq(f.read(1), b'a')
if iswindows:
os.rename(fname, fname+'.moved')
os.remove(fname+'.moved')
else:
os.remove(fname)
os.remove(fname)
eq(f.read(1), b'a')
f2 = share_open(fname, 'w+b')
f2.write(b'b' * 10 * 1024)

View File

@@ -1,27 +1,11 @@
import os, sys, re
try:
import ctypes.wintypes
iswindows = True
except ValueError:
iswindows = False
import fcntl, termios, struct
def fmt(code):
return '\033[%dm' % code
if iswindows:
class CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure):
_fields_ = [
('dwSize', ctypes.wintypes._COORD),
('dwCursorPosition', ctypes.wintypes._COORD),
('wAttributes', ctypes.wintypes.WORD),
('srWindow', ctypes.wintypes._SMALL_RECT),
('dwMaximumWindowSize', ctypes.wintypes._COORD)
]
RATTRIBUTES = dict(
zip(range(1, 9), (
'bold',
@@ -65,21 +49,6 @@ COLORS = {v:fmt(k) for k, v in RCOLORS.items()}
RESET = fmt(0)
if iswindows:
# From wincon.h
WCOLORS = {c:i for i, c in enumerate((
'black', 'blue', 'green', 'cyan', 'red', 'magenta', 'yellow', 'white'))}
def to_flag(fg, bg, bold):
val = 0
if bold:
val |= 0x08
if fg in WCOLORS:
val |= WCOLORS[fg]
if bg in WCOLORS:
val |= (WCOLORS[bg] << 4)
return val
def colored(text, fg=None, bg=None, bold=False):
prefix = []
@@ -100,76 +69,14 @@ def colored(text, fg=None, bg=None, bold=False):
class Detect(object):
def __init__(self, stream):
__import__('pdb').set_trace()
self.stream = stream or sys.stdout
self.isatty = getattr(self.stream, 'isatty', lambda : False)()
force_ansi = False
if not self.isatty and force_ansi:
self.isatty = True
self.isansi = force_ansi or not iswindows
self.isansi = force_ansi or not False
self.set_console = self.write_console = None
self.is_console = False
if not self.isansi:
try:
import msvcrt
self.msvcrt = msvcrt
self.file_handle = msvcrt.get_osfhandle(self.stream.fileno())
from ctypes import windll, wintypes, byref, POINTER, WinDLL
mode = wintypes.DWORD(0)
f = windll.kernel32.GetConsoleMode
f.argtypes, f.restype = [wintypes.HANDLE, POINTER(wintypes.DWORD)], wintypes.BOOL
if f(self.file_handle, byref(mode)):
# Stream is a console
self.set_console = windll.kernel32.SetConsoleTextAttribute
self.default_console_text_attributes = WCOLORS['white']
kernel32 = WinDLL('kernel32', use_last_error=True)
self.write_console = kernel32.WriteConsoleW
self.write_console.argtypes = [wintypes.HANDLE, wintypes.c_wchar_p, wintypes.DWORD, POINTER(wintypes.DWORD), wintypes.LPVOID]
self.write_console.restype = wintypes.BOOL
kernel32.GetConsoleScreenBufferInfo.argtypes = [wintypes.HANDLE, ctypes.POINTER(CONSOLE_SCREEN_BUFFER_INFO)]
kernel32.GetConsoleScreenBufferInfo.restype = wintypes.BOOL
csbi = CONSOLE_SCREEN_BUFFER_INFO()
if kernel32.GetConsoleScreenBufferInfo(self.file_handle, byref(csbi)):
self.default_console_text_attributes = csbi.wAttributes
self.is_console = True
except:
pass
def write_unicode_text(self, text, ignore_errors=False):
' Windows only method that writes unicode strings correctly to the windows console using the Win32 API '
if self.is_console:
from ctypes import wintypes, byref, c_wchar_p
written = wintypes.DWORD(0)
text = text.replace('\0', '')
chunk = len(text)
while text:
t, text = text[:chunk], text[chunk:]
wt = c_wchar_p(t)
text_len = len(t.encode('utf-16'))
if not self.write_console(self.file_handle, wt, text_len, byref(written), None):
# Older versions of windows can fail to write large strings
# to console with WriteConsoleW (seen it happen on Win XP)
import winerror
err = ctypes.get_last_error()
if err == winerror.ERROR_NOT_ENOUGH_MEMORY and chunk >= 128:
# Retry with a smaller chunk size (give up if chunk < 128)
chunk = chunk // 2
text = t + text
continue
if err == winerror.ERROR_GEN_FAILURE:
# On newer windows, this happens when trying to write
# non-ascii chars to the console and the console is set
# to use raster fonts (the default). In this case
# rather than failing, write an informative error
# message and the asciized version of the text.
print('Non-ASCII text detected. You must set your Console\'s font to'
' Lucida Console or Consolas or some other TrueType font to see this text', file=self.stream, end=' -- ')
from ebook_converter.utils.filenames import ascii_text
print(ascii_text(t + text), file=self.stream, end='')
continue
if not ignore_errors:
raise ctypes.WinError(err)
class ColoredStream(Detect):
@@ -178,10 +85,6 @@ class ColoredStream(Detect):
stream = getattr(stream, 'buffer', stream)
Detect.__init__(self, stream)
self.fg, self.bg, self.bold = fg, bg, bold
if self.set_console is not None:
self.wval = to_flag(self.fg, self.bg, bold)
if not self.bg:
self.wval |= self.default_console_text_attributes & 0xF0
def cwrite(self, what):
if not isinstance(what, bytes):
@@ -286,13 +189,6 @@ class ANSIStream(Detect):
def write_plain_text(self, text, start, end):
if start < end:
text = text[start:end]
if self.is_console and isinstance(text, bytes):
try:
utext = text.decode(self.encoding)
except ValueError:
pass
else:
return self.write_unicode_text(utext)
self.polyglot_write(text)
def convert_ansi(self, paramstring, command):
@@ -326,60 +222,11 @@ class ANSIStream(Detect):
fg, bg, bold = None, None, False
self.last_state = (fg, bg, bold)
if fg or bg or bold:
val = to_flag(fg, bg, bold)
if not bg:
val |= self.default_console_text_attributes & 0xF0
self.set_console(self.file_handle, val)
else:
self.set_console(self.file_handle, self.default_console_text_attributes)
def windows_terminfo():
from ctypes import Structure, byref
from ctypes.wintypes import SHORT, WORD
class COORD(Structure):
"""struct in wincon.h"""
_fields_ = [
('X', SHORT),
('Y', SHORT),
]
class SMALL_RECT(Structure):
"""struct in wincon.h."""
_fields_ = [
("Left", SHORT),
("Top", SHORT),
("Right", SHORT),
("Bottom", SHORT),
]
class CONSOLE_SCREEN_BUFFER_INFO(Structure):
"""struct in wincon.h."""
_fields_ = [
("dwSize", COORD),
("dwCursorPosition", COORD),
("wAttributes", WORD),
("srWindow", SMALL_RECT),
("dwMaximumWindowSize", COORD),
]
csbi = CONSOLE_SCREEN_BUFFER_INFO()
import msvcrt
file_handle = msvcrt.get_osfhandle(sys.stdout.fileno())
from ctypes import windll
success = windll.kernel32.GetConsoleScreenBufferInfo(file_handle,
byref(csbi))
if not success:
raise Exception('stdout is not a console?')
return csbi
self.set_console(self.file_handle, self.default_console_text_attributes)
def get_term_geometry():
import fcntl, termios, struct
def ioctl_GWINSZ(fd):
try:
@@ -405,30 +252,10 @@ def get_term_geometry():
def geometry():
if iswindows:
try:
ti = windows_terminfo()
return (ti.dwSize.X or 80, ti.dwSize.Y or 25)
except:
return 80, 25
else:
try:
lines, cols = get_term_geometry()
if lines is not None:
return cols, lines
except Exception:
pass
return 80, 25
def test():
s = ANSIStream()
text = [colored(t, fg=t)+'. '+colored(t, fg=t, bold=True)+'.' for t in
('red', 'yellow', 'green', 'white', 'cyan', 'magenta', 'blue',)]
s.write('\n'.join(text))
u = u'\u041c\u0438\u0445\u0430\u0438\u043b fällen'
print()
s.write_unicode_text(u)
print()
try:
lines, cols = get_term_geometry()
if lines is not None:
return cols, lines
except Exception:
pass
return 80, 25

View File

@@ -340,11 +340,7 @@ class ZipInfo (object):
self.compress_type = ZIP_STORED # Type of compression for the file
self.comment = b"" # Comment for each file
self.extra = b"" # ZIP extra data
if sys.platform == 'win32':
self.create_system = 0 # System which created ZIP archive
else:
# Assume everything else is unix-y
self.create_system = 3 # System which created ZIP archive
self.create_system = 3 # System which created ZIP archive
self.create_version = 20 # Version which created ZIP archive
self.extract_version = 20 # Version needed to extract archive
self.reserved = 0 # Must be zero