Get rid of @dynamic_property

This commit is contained in:
Kovid Goyal 2019-05-15 20:39:48 +05:30
parent 846a1a5e9f
commit f51e63718c
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
43 changed files with 1269 additions and 1487 deletions

View File

@ -1,6 +1,6 @@
[flake8]
max-line-length = 160
builtins = _,dynamic_property,__,P,I,lopen,icu_lower,icu_upper,icu_title,ngettext,connect_lambda
builtins = _,__,P,I,lopen,icu_lower,icu_upper,icu_title,ngettext,connect_lambda
ignore = E12,E203,E22,E231,E241,E401,E402,E731,W391,E722,E741,W504
[yapf]

View File

@ -4,9 +4,8 @@ __copyright__ = '2008, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
import sys, os, re, time, random, warnings
from polyglot.builtins import (builtins, codepoint_to_chr, iteritems,
from polyglot.builtins import (codepoint_to_chr, iteritems,
itervalues, unicode_type, range, filter, hasenv)
builtins.__dict__['dynamic_property'] = lambda func: func(None)
from math import floor
from functools import partial

View File

@ -1145,18 +1145,15 @@ class DB(object):
def vacuum(self):
self.execute('VACUUM')
@dynamic_property
@property
def user_version(self):
doc = 'The user version of this database'
def fget(self):
'''The user version of this database'''
return self.conn.get('pragma user_version;', all=False)
def fset(self, val):
@user_version.setter
def user_version(self, val):
self.execute('pragma user_version=%d'%int(val))
return property(doc=doc, fget=fget, fset=fset)
def initialize_database(self):
metadata_sqlite = P('metadata_sqlite.sql', data=True,
allow_user_override=False).decode('utf-8')
@ -1252,12 +1249,10 @@ class DB(object):
def exists_at(cls, path):
return path and os.path.exists(os.path.join(path, 'metadata.db'))
@dynamic_property
@property
def library_id(self):
doc = ('The UUID for this library. As long as the user only operates'
' on libraries with calibre, it will be unique')
'''The UUID for this library. As long as the user only operates on libraries with calibre, it will be unique'''
def fget(self):
if getattr(self, '_library_id_', None) is None:
ans = self.conn.get('SELECT uuid FROM library_id', all=False)
if ans is None:
@ -1267,15 +1262,14 @@ class DB(object):
self._library_id_ = ans
return self._library_id_
def fset(self, val):
@library_id.setter
def library_id(self, val):
self._library_id_ = unicode_type(val)
self.execute('''
DELETE FROM library_id;
INSERT INTO library_id (uuid) VALUES (?);
''', (self._library_id_,))
return property(doc=doc, fget=fget, fset=fset)
def last_modified(self):
''' Return last modified time as a UTC datetime object '''
return utcfromtimestamp(os.stat(self.dbpath).st_mtime)

View File

@ -31,11 +31,9 @@ class FileFormatter(object):
self.name = file.name
self.path = file.path
@dynamic_property
@property
def mode_string(self):
doc=""" The mode string for this file. There are only two modes read-only and read-write """
def fget(self):
""" The mode string for this file. There are only two modes read-only and read-write """
mode, x = "-", "-"
if self.is_dir:
mode, x = "d", "x"
@ -44,24 +42,18 @@ class FileFormatter(object):
else:
mode += "rw"+x+"rw"+x+"rw"+x
return mode
return property(doc=doc, fget=fget)
@dynamic_property
@property
def isdir_name(self):
doc='''Return self.name + '/' if self is a directory'''
def fget(self):
'''Return self.name + '/' if self is a directory'''
name = self.name
if self.is_dir:
name += '/'
return name
return property(doc=doc, fget=fget)
@dynamic_property
@property
def name_in_color(self):
doc=""" The name in ANSI text. Directories are blue, ebooks are green """
def fget(self):
""" The name in ANSI text. Directories are blue, ebooks are green """
cname = self.name
blue, green, normal = "", "", ""
if self.term:
@ -73,31 +65,21 @@ class FileFormatter(object):
if ext in (".pdf", ".rtf", ".lrf", ".lrx", ".txt"):
cname = green + self.name + normal
return cname
return property(doc=doc, fget=fget)
@dynamic_property
@property
def human_readable_size(self):
doc=""" File size in human readable form """
def fget(self):
""" File size in human readable form """
return human_readable(self.size)
return property(doc=doc, fget=fget)
@dynamic_property
@property
def modification_time(self):
doc=""" Last modified time in the Linux ls -l format """
def fget(self):
""" Last modified time in the Linux ls -l format """
return time.strftime("%Y-%m-%d %H:%M", time.localtime(self.wtime))
return property(doc=doc, fget=fget)
@dynamic_property
@property
def creation_time(self):
doc=""" Last modified time in the Linux ls -l format """
def fget(self):
""" Last modified time in the Linux ls -l format """
return time.strftime("%Y-%m-%d %H:%M", time.localtime(self.ctime))
return property(doc=doc, fget=fget)
def info(dev):

View File

@ -46,26 +46,21 @@ class Book(Metadata):
# use lpath because the prefix can change, changing path
return self.lpath == getattr(other, 'lpath', None)
@dynamic_property
@property
def db_id(self):
doc = '''The database id in the application database that this file corresponds to'''
'''The database id in the application database that this file corresponds to'''
def fget(self):
match = re.search(r'_(\d+)$', self.lpath.rpartition('.')[0])
if match:
return int(match.group(1))
return None
return property(fget=fget, doc=doc)
@dynamic_property
@property
def title_sorter(self):
doc = '''String to sort the title. If absent, title is returned'''
def fget(self):
'''String to sort the title. If absent, title is returned'''
return title_sort(self.title)
return property(doc=doc, fget=fget)
@dynamic_property
@property
def thumbnail(self):
return None

View File

@ -169,12 +169,12 @@ class Block(object):
def height(self):
return int(ceil(sum(l if isinstance(l, numbers.Number) else l.boundingRect().height() for l in self.layouts)))
@dynamic_property
@property
def position(self):
def fget(self):
return self._position
def fset(self, new_pos):
@position.setter
def position(self, new_pos):
(x, y) = new_pos
self._position = Point(x, y)
if self.layouts:
@ -186,7 +186,6 @@ class Block(object):
else:
l.setPosition(QPointF(x, y))
y += l.boundingRect().height()
return property(fget=fget, fset=fset)
def draw(self, painter):
for l in self.layouts:

View File

@ -209,37 +209,29 @@ class Tag(object):
s += " at %08X, contents: %s" % (self.offset, repr(self.contents))
return s
@dynamic_property
@property
def byte(self):
def fget(self):
if len(self.contents) != 1:
raise LRFParseError("Bad parameter for tag ID: %04X" % self.id)
return struct.unpack("<B", self.contents)[0]
return property(fget=fget)
@dynamic_property
@property
def word(self):
def fget(self):
if len(self.contents) != 2:
raise LRFParseError("Bad parameter for tag ID: %04X" % self.id)
return struct.unpack("<H", self.contents)[0]
return property(fget=fget)
@dynamic_property
@property
def sword(self):
def fget(self):
if len(self.contents) != 2:
raise LRFParseError("Bad parameter for tag ID: %04X" % self.id)
return struct.unpack("<h", self.contents)[0]
return property(fget=fget)
@dynamic_property
@property
def dword(self):
def fget(self):
if len(self.contents) != 4:
raise LRFParseError("Bad parameter for tag ID: %04X" % self.id)
return struct.unpack("<I", self.contents)[0]
return property(fget=fget)
def dummy_parser(self, stream):
raise LRFParseError("Unknown tag at %08X" % stream.tell())

View File

@ -193,14 +193,13 @@ class ManifestItem(Resource): # {{{
res.mime_type = mt
return res
@dynamic_property
@property
def media_type(self):
def fget(self):
return self.mime_type
def fset(self, val):
@media_type.setter
def media_type(self, val):
self.mime_type = val
return property(fget=fget, fset=fset)
def __unicode__representation__(self):
return u'<item id="%s" href="%s" media-type="%s" />'%(self.id, self.href(), self.media_type)
@ -804,17 +803,17 @@ class OPF(object): # {{{
for item in self.iterguide():
item.set('href', get_href(item))
@dynamic_property
@property
def title(self):
# TODO: Add support for EPUB 3 refinements
def fget(self):
for elem in self.title_path(self.metadata):
title = self.get_text(elem)
if title and title.strip():
return re.sub(r'\s+', ' ', title.strip())
def fset(self, val):
@title.setter
def title(self, val):
val = (val or '').strip()
titles = self.title_path(self.metadata)
if self.package_version < 3:
@ -827,18 +826,15 @@ class OPF(object): # {{{
title = titles[0] if titles else self.create_metadata_element('title')
title.text = re.sub(r'\s+', ' ', unicode_type(val))
return property(fget=fget, fset=fset)
@dynamic_property
@property
def authors(self):
def fget(self):
ans = []
for elem in self.authors_path(self.metadata):
ans.extend(string_to_authors(self.get_text(elem)))
return ans
def fset(self, val):
@authors.setter
def authors(self, val):
remove = list(self.authors_path(self.metadata))
for elem in remove:
elem.getparent().remove(elem)
@ -853,12 +849,8 @@ class OPF(object): # {{{
elem.set('{%s}role'%self.NAMESPACES['opf'], 'aut')
self.set_text(elem, author.strip())
return property(fget=fget, fset=fset)
@dynamic_property
@property
def author_sort(self):
def fget(self):
matches = self.authors_path(self.metadata)
if matches:
for match in matches:
@ -868,7 +860,8 @@ class OPF(object): # {{{
if ans:
return ans
def fset(self, val):
@author_sort.setter
def author_sort(self, val):
matches = self.authors_path(self.metadata)
if matches:
for key in matches[0].attrib:
@ -876,12 +869,8 @@ class OPF(object): # {{{
matches[0].attrib.pop(key)
matches[0].set('{%s}file-as'%self.NAMESPACES['opf'], unicode_type(val))
return property(fget=fget, fset=fset)
@dynamic_property
@property
def tags(self):
def fget(self):
ans = []
for tag in self.tags_path(self.metadata):
text = self.get_text(tag)
@ -889,19 +878,16 @@ class OPF(object): # {{{
ans.extend([x.strip() for x in text.split(',')])
return ans
def fset(self, val):
@tags.setter
def tags(self, val):
for tag in list(self.tags_path(self.metadata)):
tag.getparent().remove(tag)
for tag in val:
elem = self.create_metadata_element('subject')
self.set_text(elem, unicode_type(tag))
return property(fget=fget, fset=fset)
@dynamic_property
@property
def pubdate(self):
def fget(self):
ans = None
for match in self.pubdate_path(self.metadata):
try:
@ -913,7 +899,8 @@ class OPF(object): # {{{
ans = val
return ans
def fset(self, val):
@pubdate.setter
def pubdate(self, val):
least_val = least_elem = None
for match in self.pubdate_path(self.metadata):
try:
@ -934,16 +921,13 @@ class OPF(object): # {{{
least_elem.attrib.clear()
least_elem.text = isoformat(val)
return property(fget=fget, fset=fset)
@dynamic_property
@property
def isbn(self):
def fget(self):
for match in self.isbn_path(self.metadata):
return self.get_text(match) or None
def fset(self, val):
@isbn.setter
def isbn(self, val):
uuid_id = None
for attr in self.root.attrib:
if attr.endswith('unique-identifier'):
@ -969,8 +953,6 @@ class OPF(object): # {{{
attrib=attrib)]
self.set_text(matches[0], unicode_type(val))
return property(fget=fget, fset=fset)
def get_identifiers(self):
identifiers = {}
for x in self.XPath(
@ -1024,14 +1006,13 @@ class OPF(object): # {{{
self.set_text(self.create_metadata_element(
'identifier', attrib=attrib), unicode_type(val))
@dynamic_property
@property
def application_id(self):
def fget(self):
for match in self.application_id_path(self.metadata):
return self.get_text(match) or None
def fset(self, val):
@application_id.setter
def application_id(self, val):
removed_ids = set()
for x in tuple(self.application_id_path(self.metadata)):
removed_ids.add(x.get('id', None))
@ -1048,16 +1029,13 @@ class OPF(object): # {{{
self.set_text(self.create_metadata_element(
'identifier', attrib=attrib), unicode_type(val))
return property(fget=fget, fset=fset)
@dynamic_property
@property
def uuid(self):
def fget(self):
for match in self.uuid_id_path(self.metadata):
return self.get_text(match) or None
def fset(self, val):
@uuid.setter
def uuid(self, val):
matches = self.uuid_id_path(self.metadata)
if not matches:
attrib = {'{%s}scheme'%self.NAMESPACES['opf']: 'uuid'}
@ -1065,25 +1043,18 @@ class OPF(object): # {{{
attrib=attrib)]
self.set_text(matches[0], unicode_type(val))
return property(fget=fget, fset=fset)
@dynamic_property
@property
def language(self):
def fget(self):
ans = self.languages
if ans:
return ans[0]
def fset(self, val):
@language.setter
def language(self, val):
self.languages = [val]
return property(fget=fget, fset=fset)
@dynamic_property
@property
def languages(self):
def fget(self):
ans = []
for match in self.languages_path(self.metadata):
t = self.get_text(match)
@ -1093,7 +1064,8 @@ class OPF(object): # {{{
ans.append(l)
return ans
def fset(self, val):
@languages.setter
def languages(self, val):
matches = self.languages_path(self.metadata)
for x in matches:
x.getparent().remove(x)
@ -1102,8 +1074,6 @@ class OPF(object): # {{{
l = self.create_metadata_element('language')
self.set_text(l, unicode_type(lang))
return property(fget=fget, fset=fset)
@property
def raw_languages(self):
for match in self.languages_path(self.metadata):
@ -1111,20 +1081,18 @@ class OPF(object): # {{{
if t and t.strip():
yield t.strip()
@dynamic_property
@property
def book_producer(self):
def fget(self):
for match in self.bkp_path(self.metadata):
return self.get_text(match) or None
def fset(self, val):
@book_producer.setter
def book_producer(self, val):
matches = self.bkp_path(self.metadata)
if not matches:
matches = [self.create_metadata_element('contributor')]
matches[0].set('{%s}role'%self.NAMESPACES['opf'], 'bkp')
self.set_text(matches[0], unicode_type(val))
return property(fget=fget, fset=fset)
def identifier_iter(self):
for item in self.identifier_path(self.metadata):
@ -1238,10 +1206,8 @@ class OPF(object): # {{{
if path and os.path.exists(path):
return path
@dynamic_property
@property
def cover(self):
def fget(self):
if self.guide is not None:
for t in ('cover', 'other.ms-coverimage-standard', 'other.ms-coverimage'):
for item in self.guide:
@ -1253,7 +1219,8 @@ class OPF(object): # {{{
except:
pass
def fset(self, path):
@cover.setter
def cover(self, path):
if self.guide is not None:
self.guide.set_cover(path)
for item in list(self.iterguide()):
@ -1273,8 +1240,6 @@ class OPF(object): # {{{
if item.type.lower() == t:
self.create_manifest_item(item.href(), guess_type(path)[0])
return property(fget=fget, fset=fset)
def get_metadata_element(self, name):
matches = self.metadata_elem_path(self.metadata, name=name)
if matches:

View File

@ -122,11 +122,10 @@ class TOC(list):
for i in obj.flat():
yield i
@dynamic_property
@property
def abspath(self):
doc='Return the file this toc entry points to as a absolute path to a file on the system.'
'Return the file this toc entry points to as a absolute path to a file on the system.'
def fget(self):
if self.href is None:
return None
path = self.href.replace('/', os.sep)
@ -134,8 +133,6 @@ class TOC(list):
path = os.path.join(self.base_path, path)
return path
return property(fget=fget, doc=doc)
def read_from_opf(self, opfreader):
toc = opfreader.soup.find('spine', toc=True)
if toc is not None:

View File

@ -131,14 +131,13 @@ class IndexEntry(object):
' parent_index=%r)')%(self.offset, self.depth, self.length,
self.index, self.parent_index)
@dynamic_property
@property
def size(self):
def fget(self):
return self.length
def fset(self, val):
@size.setter
def size(self, val):
self.length = val
return property(fget=fget, fset=fset, doc='Alias for length')
@property
def next_offset(self):

View File

@ -704,20 +704,17 @@ class Metadata(object):
if attr != nsattr:
attrib[nsattr] = attrib.pop(attr)
@dynamic_property
@property
def name(self):
def fget(self):
return self.term
return property(fget=fget)
@dynamic_property
@property
def content(self):
def fget(self):
return self.value
def fset(self, value):
@content.setter
def content(self, value):
self.value = value
return property(fget=fget, fset=fset)
scheme = Attribute(lambda term: 'scheme' if
term == OPF('meta') else OPF('scheme'),
@ -830,33 +827,27 @@ class Metadata(object):
def __getattr__(self, term):
return self.items[term]
@dynamic_property
@property
def _nsmap(self):
def fget(self):
nsmap = {}
for term in self.items:
for item in self.items[term]:
nsmap.update(item.nsmap)
return nsmap
return property(fget=fget)
@dynamic_property
@property
def _opf1_nsmap(self):
def fget(self):
nsmap = self._nsmap
for key, value in nsmap.items():
if value in OPF_NSES or value in DC_NSES:
del nsmap[key]
return nsmap
return property(fget=fget)
@dynamic_property
@property
def _opf2_nsmap(self):
def fget(self):
nsmap = self._nsmap
nsmap.update(OPF2_NSMAP)
return nsmap
return property(fget=fget)
def to_opf1(self, parent=None):
nsmap = self._opf1_nsmap
@ -1011,9 +1002,9 @@ class Manifest(object):
# }}}
@dynamic_property
@property
def data(self):
doc = """Provides MIME type sensitive access to the manifest
"""Provides MIME type sensitive access to the manifest
entry's associated content.
- XHTML, HTML, and variant content is parsed as necessary to
@ -1025,8 +1016,6 @@ class Manifest(object):
- All other content is returned as a :class:`str` object with no
special parsing.
"""
def fget(self):
data = self._data
if data is None:
if self._loader is None:
@ -1053,12 +1042,13 @@ class Manifest(object):
self._data = data
return data
def fset(self, value):
@data.setter
def data(self, value):
self._data = value
def fdel(self):
@data.deleter
def data(self):
self._data = None
return property(fget, fset, fdel, doc=doc)
def unload_data_from_memory(self, memory=None):
if isinstance(self._data, bytes):
@ -1266,9 +1256,8 @@ class Manifest(object):
element(elem, OPF('item'), attrib=attrib)
return elem
@dynamic_property
@property
def main_stylesheet(self):
def fget(self):
ans = getattr(self, '_main_stylesheet', None)
if ans is None:
for item in self:
@ -1277,9 +1266,9 @@ class Manifest(object):
break
return ans
def fset(self, item):
@main_stylesheet.setter
def main_stylesheet(self, item):
self._main_stylesheet = item
return property(fget=fget, fset=fset)
class Spine(object):
@ -1422,15 +1411,12 @@ class Guide(object):
return 'Reference(type=%r, title=%r, href=%r)' \
% (self.type, self.title, self.href)
@dynamic_property
@property
def item(self):
doc = """The manifest item associated with this reference."""
def fget(self):
"""The manifest item associated with this reference."""
path = urldefrag(self.href)[0]
hrefs = self.oeb.manifest.hrefs
return hrefs.get(path, None)
return property(fget=fget, doc=doc)
def __init__(self, oeb):
self.oeb = oeb

View File

@ -1369,14 +1369,13 @@ class EpubContainer(Container):
with self.open(name, 'wb') as f:
f.write(data)
@dynamic_property
@property
def path_to_ebook(self):
def fget(self):
return self.pathtoepub
def fset(self, val):
@path_to_ebook.setter
def path_to_ebook(self, val):
self.pathtoepub = val
return property(fget=fget, fset=fset)
# }}}
@ -1496,14 +1495,13 @@ class AZW3Container(Container):
outpath = self.pathtoazw3
opf_to_azw3(self.name_path_map[self.opf_name], outpath, self)
@dynamic_property
@property
def path_to_ebook(self):
def fget(self):
return self.pathtoazw3
def fset(self, val):
@path_to_ebook.setter
def path_to_ebook(self, val):
self.pathtoazw3 = val
return property(fget=fget, fset=fset)
@property
def names_that_must_not_be_changed(self):

View File

@ -1022,19 +1022,19 @@ class Application(QApplication):
else:
return QApplication.event(self, e)
@dynamic_property
@property
def current_custom_colors(self):
from PyQt5.Qt import QColorDialog, QColor
from PyQt5.Qt import QColorDialog
def fget(self):
return [col.getRgb() for col in
(QColorDialog.customColor(i) for i in range(QColorDialog.customCount()))]
def fset(self, colors):
@current_custom_colors.setter
def current_custom_colors(self, colors):
from PyQt5.Qt import QColorDialog, QColor
num = min(len(colors), QColorDialog.customCount())
for i in range(num):
QColorDialog.setCustomColor(i, QColor(*colors[i]))
return property(fget=fget, fset=fset)
def read_custom_colors(self):
colors = self.color_prefs.get('custom_colors_for_color_dialog', None)

View File

@ -51,18 +51,17 @@ class ChooseFormat(QDialog): # {{{
b.setChecked(True)
self.accept()
@dynamic_property
@property
def formats(self):
def fget(self):
for b in self.buttons:
if b.isChecked():
yield unicode_type(b.text())[1:]
def fset(self, formats):
@formats.setter
def formats(self, formats):
formats = {x.upper() for x in formats}
for b in self.buttons:
b.setChecked(b.text()[1:] in formats)
return property(fget=fget, fset=fset)
# }}}

View File

@ -336,10 +336,8 @@ class EditorWidget(QWebView, LineEditECM): # {{{
def remove_format_cleanup(self):
self.html = self.html
@dynamic_property
@property
def html(self):
def fget(self):
ans = u''
try:
if not self.page().mainFrame().documentElement().findFirst('meta[name="calibre-dont-sanitize"]').isNull():
@ -378,13 +376,13 @@ class EditorWidget(QWebView, LineEditECM): # {{{
return ans
def fset(self, val):
@html.setter
def html(self, val):
if self.base_url is None:
self.setHtml(val)
else:
self.setHtml(val, self.base_url)
self.set_font_style()
return property(fget=fget, fset=fset)
def set_base_url(self, qurl):
self.base_url = qurl
@ -763,15 +761,14 @@ class Editor(QWidget): # {{{
def set_minimum_height_for_editor(self, val):
self.editor.setMinimumHeight(val)
@dynamic_property
@property
def html(self):
def fset(self, v):
self.editor.html = v
def fget(self):
self.tabs.setCurrentIndex(0)
return self.editor.html
return property(fget=fget, fset=fset)
@html.setter
def html(self, v):
self.editor.html = v
def change_tab(self, index):
# print 'reloading:', (index and self.wyswyg_dirty) or (not index and
@ -785,14 +782,13 @@ class Editor(QWidget): # {{{
self.editor.html = unicode_type(self.code_edit.toPlainText())
self.source_dirty = False
@dynamic_property
@property
def tab(self):
def fget(self):
return 'code' if self.tabs.currentWidget() is self.code_edit else 'wyswyg'
def fset(self, val):
@tab.setter
def tab(self, val):
self.tabs.setCurrentWidget(self.code_edit if val == 'code' else self.wyswyg)
return property(fget=fget, fset=fset)
def wyswyg_dirtied(self, *args):
self.wyswyg_dirty = True
@ -816,14 +812,13 @@ class Editor(QWidget): # {{{
if self.toolbar_prefs_name is not None:
gprefs.set(self.toolbar_prefs_name, visible)
@dynamic_property
@property
def toolbars_visible(self):
def fget(self):
return self.toolbar1.isVisible() or self.toolbar2.isVisible() or self.toolbar3.isVisible()
def fset(self, val):
@toolbars_visible.setter
def toolbars_visible(self, val):
getattr(self, ('show' if val else 'hide') + '_toolbars')()
return property(fget=fget, fset=fset)
def set_readonly(self, what):
self.editor.set_readonly(what)

View File

@ -333,23 +333,21 @@ class LineEdit(QLineEdit, LineEditECM):
def set_add_separator(self, what):
self.add_separator = bool(what)
@dynamic_property
@property
def all_items(self):
def fget(self):
return self.mcompleter.model().all_items
def fset(self, items):
@all_items.setter
def all_items(self, items):
self.mcompleter.model().set_items(items)
return property(fget=fget, fset=fset)
@dynamic_property
@property
def disable_popup(self):
def fget(self):
return self.mcompleter.disable_popup
def fset(self, val):
@disable_popup.setter
def disable_popup(self, val):
self.mcompleter.disable_popup = bool(val)
return property(fget=fget, fset=fset)
# }}}
def event(self, ev):
@ -471,23 +469,21 @@ class EditWithComplete(EnComboBox):
self.setText(what)
self.lineEdit().selectAll()
@dynamic_property
@property
def all_items(self):
def fget(self):
return self.lineEdit().all_items
def fset(self, val):
@all_items.setter
def all_items(self, val):
self.lineEdit().all_items = val
return property(fget=fget, fset=fset)
@dynamic_property
@property
def disable_popup(self):
def fget(self):
return self.lineEdit().disable_popup
def fset(self, val):
@disable_popup.setter
def disable_popup(self, val):
self.lineEdit().disable_popup = bool(val)
return property(fget=fget, fset=fset)
# }}}
def text(self):

View File

@ -43,14 +43,13 @@ class ColorButton(QToolButton):
self.setIcon(QIcon(self.pix))
self.clicked.connect(self.choose_color)
@dynamic_property
@property
def color(self):
def fget(self):
return self._color.name(QColor.HexRgb)[1:]
def fset(self, val):
@color.setter
def color(self, val):
self._color = QColor('#' + val)
return property(fget=fget, fset=fset)
def update_display(self):
self.pix.fill(self._color)

View File

@ -377,14 +377,13 @@ class Comments(Base):
val = None
return val
@dynamic_property
@property
def tab(self):
def fget(self):
return self._tb.tab
def fset(self, val):
@tab.setter
def tab(self, val):
self._tb.tab = val
return property(fget=fget, fset=fset)
def connect_data_changed(self, slot):
self._tb.data_changed.connect(slot)

View File

@ -1367,11 +1367,9 @@ class DeviceMixin(object): # {{{
memory=[files, remove])
self.status_bar.show_message(_('Sending catalogs to device.'), 5000)
@dynamic_property
@property
def news_to_be_synced(self):
doc = 'Set of ids to be sent to device'
def fget(self):
'Set of ids to be sent to device'
ans = []
try:
ans = self.library_view.model().db.prefs.get('news_to_be_synced',
@ -1381,7 +1379,8 @@ class DeviceMixin(object): # {{{
traceback.print_exc()
return set(ans)
def fset(self, ids):
@news_to_be_synced.setter
def news_to_be_synced(self, ids):
try:
self.library_view.model().db.new_api.set_pref('news_to_be_synced',
list(ids))
@ -1389,8 +1388,6 @@ class DeviceMixin(object): # {{{
import traceback
traceback.print_exc()
return property(fget=fget, fset=fset, doc=doc)
def sync_news(self, send_ids=None, do_auto_convert=True):
if self.device_connected:
del_on_upload = config['delete_news_from_library_on_upload']

View File

@ -378,15 +378,15 @@ class BasicRecipe(QWidget): # {{{
return False
return True
@dynamic_property
@property
def recipe_source(self):
def fget(self):
title = self.title.text().strip()
feeds = [self.feeds.item(i).data(Qt.UserRole) for i in range(self.feeds.count())]
return options_to_recipe_source(title, self.oldest_article.value(), self.max_articles.value(), feeds)
def fset(self, src):
@recipe_source.setter
def recipe_source(self, src):
self.feeds.clear()
self.feed_title.clear()
self.feed_url.clear()
@ -403,7 +403,6 @@ class BasicRecipe(QWidget): # {{{
title, url = ('', x) if len(x) == 1 else x
QListWidgetItem('%s - %s' % (title, url), self.feeds).setData(Qt.UserRole, (title, url))
return property(fget=fget, fset=fset)
# }}}
@ -431,17 +430,14 @@ class AdvancedRecipe(QWidget): # {{{
return False
return True
@dynamic_property
@property
def recipe_source(self):
def fget(self):
return self.editor.toPlainText()
def fset(self, src):
@recipe_source.setter
def recipe_source(self, src):
self.editor.load_text(src, syntax='python', doc_name='<recipe>')
return property(fget=fget, fset=fset)
def sizeHint(self):
return QSize(800, 500)
# }}}

View File

@ -64,14 +64,13 @@ class ProgressDialog(QDialog):
def set_value(self, val):
self.value = val
@dynamic_property
@property
def value(self):
def fset(self, val):
return self.bar.setValue(val)
def fget(self):
return self.bar.value()
return property(fget=fget, fset=fset)
@value.setter
def value(self, val):
self.bar.setValue(val)
def set_min(self, min):
self.min = min
@ -79,42 +78,38 @@ class ProgressDialog(QDialog):
def set_max(self, max):
self.max = max
@dynamic_property
@property
def max(self):
def fget(self):
return self.bar.maximum()
def fset(self, val):
@max.setter
def max(self, val):
self.bar.setMaximum(val)
return property(fget=fget, fset=fset)
@dynamic_property
@property
def min(self):
def fget(self):
return self.bar.minimum()
def fset(self, val):
@min.setter
def min(self, val):
self.bar.setMinimum(val)
return property(fget=fget, fset=fset)
@dynamic_property
@property
def title(self):
def fget(self):
return self.title_label.text()
def fset(self, val):
@title.setter
def title(self, val):
self.title_label.setText(unicode_type(val or ''))
return property(fget=fget, fset=fset)
@dynamic_property
@property
def msg(self):
def fget(self):
return self.message.text()
def fset(self, val):
@msg.setter
def msg(self, val):
val = unicode_type(val or '')
self.message.setText(elided_text(val, self.font(), self.message.minimumWidth()-10))
return property(fget=fget, fset=fset)
def _canceled(self, *args):
self.canceled = True

View File

@ -353,18 +353,17 @@ class FontFamilyChooser(QWidget):
def clear_family(self):
self.font_family = None
@dynamic_property
@property
def font_family(self):
def fget(self):
return self._current_family
def fset(self, val):
@font_family.setter
def font_family(self, val):
if not val:
val = None
self._current_family = val
self.button.setText(val or self.default_text)
self.family_changed.emit(val)
return property(fget=fget, fset=fset)
def show_chooser(self):
d = FontFamilyDialog(self.font_family, self)

View File

@ -60,10 +60,8 @@ class LanguagesEdit(EditWithComplete):
parts = [x.strip() for x in raw.split(',')]
return [self.comma_rmap.get(x, x) for x in parts]
@dynamic_property
@property
def lang_codes(self):
def fget(self):
vals = self.vals
ans = []
for name in vals:
@ -73,11 +71,10 @@ class LanguagesEdit(EditWithComplete):
ans.append(code)
return ans
def fset(self, lang_codes):
@lang_codes.setter
def lang_codes(self, lang_codes):
self.set_lang_codes(lang_codes, allow_undo=False)
return property(fget=fget, fset=fset)
def set_lang_codes(self, lang_codes, allow_undo=True):
ans = []
for lc in lang_codes:

View File

@ -186,18 +186,17 @@ class PreserveViewState(object): # {{{
view.horizontalScrollBar().setValue(self.hscroll)
self.init_vals()
@dynamic_property
@property
def state(self):
def fget(self):
self.__enter__()
return {x:getattr(self, x) for x in ('selected_ids', 'current_id',
'vscroll', 'hscroll')}
def fset(self, state):
@state.setter
def state(self, state):
for k, v in iteritems(state):
setattr(self, k, v)
self.__exit__()
return property(fget=fget, fset=fset)
# }}}
@ -1161,16 +1160,16 @@ class BooksView(QTableView): # {{{
ans.append(i)
return ans
@dynamic_property
@property
def current_id(self):
def fget(self):
try:
return self.model().id(self.currentIndex())
except:
pass
return None
def fset(self, val):
@current_id.setter
def current_id(self, val):
if val is None:
return
m = self.model()
@ -1178,7 +1177,6 @@ class BooksView(QTableView): # {{{
if m.id(row) == val:
self.set_current_row(row, select=False)
break
return property(fget=fget, fset=fset)
@property
def next_id(self):

View File

@ -72,14 +72,13 @@ class BasicMetadataWidget(object):
def commit(self, db, id_):
return True
@dynamic_property
@property
def current_val(self):
# Present in most but not all basic metadata widgets
def fget(self):
return None
def fset(self, val):
@current_val.setter
def current_val(self, val):
pass
return property(fget=fget, fset=fset)
'''
@ -225,16 +224,16 @@ class TitleEdit(EnLineEdit, ToMetadataMixin):
# to work even if some of the book files are opened in windows.
getattr(db, 'set_'+ self.TITLE_ATTR)(id_, title, notify=False)
@dynamic_property
@property
def current_val(self):
def fget(self):
title = clean_text(unicode_type(self.text()))
if not title:
title = self.get_default()
return title.strip()
def fset(self, val):
@current_val.setter
def current_val(self, val):
if hasattr(val, 'strip'):
val = val.strip()
if not val:
@ -242,8 +241,6 @@ class TitleEdit(EnLineEdit, ToMetadataMixin):
self.set_text(val)
self.setCursorPosition(0)
return property(fget=fget, fset=fset)
def break_cycles(self):
self.dialog = None
@ -416,23 +413,21 @@ class AuthorsEdit(EditWithComplete, ToMetadataMixin):
self.books_to_refresh |= db.set_authors(id_, authors, notify=False,
allow_case_change=True)
@dynamic_property
@property
def current_val(self):
def fget(self):
au = clean_text(unicode_type(self.text()))
if not au:
au = self.get_default()
return string_to_authors(au)
def fset(self, val):
@current_val.setter
def current_val(self, val):
if not val:
val = [self.get_default()]
self.set_edit_text(' & '.join([x.strip() for x in val]))
self.lineEdit().setCursorPosition(0)
return property(fget=fget, fset=fset)
def break_cycles(self):
self.db = self.dialog = None
try:
@ -485,20 +480,18 @@ class AuthorSortEdit(EnLineEdit, ToMetadataMixin):
self.first_time = True
self.update_state()
@dynamic_property
@property
def current_val(self):
def fget(self):
return clean_text(unicode_type(self.text()))
def fset(self, val):
@current_val.setter
def current_val(self, val):
if not val:
val = ''
self.set_text(val.strip())
self.setCursorPosition(0)
return property(fget=fget, fset=fset)
def update_state_and_val(self):
# Handle case change if the authors box changed
aus = authors_to_sort_string(self.authors_edit.current_val)
@ -613,20 +606,18 @@ class SeriesEdit(EditWithComplete, ToMetadataMixin):
self.books_to_refresh = set([])
self.lineEdit().textChanged.connect(self.data_changed)
@dynamic_property
@property
def current_val(self):
def fget(self):
return clean_text(unicode_type(self.currentText()))
def fset(self, val):
@current_val.setter
def current_val(self, val):
if not val:
val = ''
self.set_edit_text(val.strip())
self.lineEdit().setCursorPosition(0)
return property(fget=fget, fset=fset)
def initialize(self, db, id_):
self.books_to_refresh = set([])
all_series = db.all_series()
@ -672,20 +663,18 @@ class SeriesIndexEdit(make_undoable(QDoubleSpinBox), ToMetadataMixin):
def enable(self, *args):
self.setEnabled(bool(self.series_edit.current_val))
@dynamic_property
@property
def current_val(self):
def fget(self):
return self.value()
def fset(self, val):
@current_val.setter
def current_val(self, val):
if val is None:
val = 1.0
val = float(val)
self.set_spinbox_value(val)
return property(fget=fget, fset=fset)
def initialize(self, db, id_):
self.db = db
if self.series_edit.current_val:
@ -1255,12 +1244,12 @@ class Cover(ImageView): # {{{
def changed(self):
return self.current_val != self.original_val
@dynamic_property
@property
def current_val(self):
def fget(self):
return self._cdata
def fset(self, cdata):
@current_val.setter
def current_val(self, cdata):
self._cdata = None
self.cdata_before_trim = None
pm = QPixmap()
@ -1279,8 +1268,6 @@ class Cover(ImageView): # {{{
self.setToolTip(tt)
self.data_changed.emit()
return property(fget=fget, fset=fset)
def commit(self, db, id_):
if self.changed:
if self.current_val:
@ -1309,12 +1296,12 @@ class CommentsEdit(Editor, ToMetadataMixin): # {{{
FIELD_NAME = 'comments'
toolbar_prefs_name = 'metadata-comments-editor-widget-hidden-toolbars'
@dynamic_property
@property
def current_val(self):
def fget(self):
return self.html
def fset(self, val):
@current_val.setter
def current_val(self, val):
if not val or not val.strip():
val = ''
else:
@ -1322,7 +1309,6 @@ class CommentsEdit(Editor, ToMetadataMixin): # {{{
self.set_html(val, self.allow_undo)
self.wyswyg_dirtied()
self.data_changed.emit()
return property(fget=fget, fset=fset)
def initialize(self, db, id_):
path = db.abspath(id_, index_is_id=True)
@ -1350,14 +1336,13 @@ class RatingEdit(RatingEditor, ToMetadataMixin): # {{{
self.setWhatsThis(self.TOOLTIP)
self.currentTextChanged.connect(self.data_changed)
@dynamic_property
@property
def current_val(self):
def fget(self):
return self.rating_value
def fset(self, val):
@current_val.setter
def current_val(self, val):
self.rating_value = val
return property(fget=fget, fset=fset)
def initialize(self, db, id_):
val = db.rating(id_, index_is_id=True)
@ -1390,17 +1375,16 @@ class TagsEdit(EditWithComplete, ToMetadataMixin): # {{{
self.setToolTip(self.TOOLTIP)
self.setWhatsThis(self.TOOLTIP)
@dynamic_property
@property
def current_val(self):
def fget(self):
return [clean_text(x) for x in unicode_type(self.text()).split(',')]
def fset(self, val):
@current_val.setter
def current_val(self, val):
if not val:
val = []
self.set_edit_text(', '.join([x.strip() for x in val]))
self.setCursorPosition(0)
return property(fget=fget, fset=fset)
def initialize(self, db, id_):
self.books_to_refresh = set([])
@ -1454,14 +1438,13 @@ class LanguagesEdit(LE, ToMetadataMixin): # {{{
self.textChanged.connect(self.data_changed)
self.setToolTip(self.TOOLTIP)
@dynamic_property
@property
def current_val(self):
def fget(self):
return self.lang_codes
def fset(self, val):
@current_val.setter
def current_val(self, val):
self.set_lang_codes(val, self.allow_undo)
return property(fget=fget, fset=fset)
def initialize(self, db, id_):
self.init_langs(db)
@ -1562,9 +1545,8 @@ class IdentifiersEdit(QLineEdit, ToMetadataMixin):
if d.exec_() == d.Accepted:
self.current_val = d.get_identifiers()
@dynamic_property
@property
def current_val(self):
def fget(self):
raw = unicode_type(self.text()).strip()
parts = [clean_text(x) for x in raw.split(',')]
ans = {}
@ -1580,7 +1562,8 @@ class IdentifiersEdit(QLineEdit, ToMetadataMixin):
ans[itype] = c
return ans
def fset(self, val):
@current_val.setter
def current_val(self, val):
if not val:
val = {}
@ -1599,7 +1582,6 @@ class IdentifiersEdit(QLineEdit, ToMetadataMixin):
# Use selectAll + insert instead of setText so that undo works
self.selectAll(), self.insert(txt.strip())
self.setCursorPosition(0)
return property(fget=fget, fset=fset)
def initialize(self, db, id_):
self.original_val = db.get_identifiers(id_, index_is_id=True)
@ -1778,20 +1760,18 @@ class PublisherEdit(EditWithComplete, ToMetadataMixin): # {{{
self.clear_button.setToolTip(_('Clear publisher'))
self.clear_button.clicked.connect(self.clearEditText)
@dynamic_property
@property
def current_val(self):
def fget(self):
return clean_text(unicode_type(self.currentText()))
def fset(self, val):
@current_val.setter
def current_val(self, val):
if not val:
val = ''
self.set_edit_text(val.strip())
self.lineEdit().setCursorPosition(0)
return property(fget=fget, fset=fset)
def initialize(self, db, id_):
self.books_to_refresh = set([])
all_publishers = db.all_publishers()
@ -1857,18 +1837,17 @@ class DateEdit(make_undoable(QDateTimeEdit), ToMetadataMixin):
def reset_date(self, *args):
self.current_val = None
@dynamic_property
@property
def current_val(self):
def fget(self):
return qt_to_dt(self.dateTime(), as_utc=False)
def fset(self, val):
@current_val.setter
def current_val(self, val):
if val is None or is_date_undefined(val):
val = UNDEFINED_DATE
else:
val = as_local_time(val)
self.set_spinbox_value(val)
return property(fget=fget, fset=fset)
def initialize(self, db, id_):
self.current_val = getattr(db, self.ATTR)(id_, index_is_id=True)

View File

@ -49,9 +49,8 @@ class LineEdit(EditWithComplete):
self.set_separator(sep)
self.textChanged.connect(self.changed)
@dynamic_property
@property
def value(self):
def fget(self):
val = unicode_type(self.text()).strip()
ism = self.metadata['is_multiple']
if ism:
@ -62,7 +61,8 @@ class LineEdit(EditWithComplete):
val = [x.strip() for x in val.split(ism['list_to_ui']) if x.strip()]
return val
def fset(self, val):
@value.setter
def value(self, val):
ism = self.metadata['is_multiple']
if ism:
if not val:
@ -71,7 +71,6 @@ class LineEdit(EditWithComplete):
val = ism['list_to_ui'].join(val)
self.setText(val)
self.setCursorPosition(0)
return property(fget=fget, fset=fset)
def from_mi(self, mi):
val = mi.get(self.field, default='') or ''
@ -85,15 +84,14 @@ class LineEdit(EditWithComplete):
elif self.field == 'authors':
mi.set('author_sort', authors_to_sort_string(val))
@dynamic_property
@property
def current_val(self):
def fget(self):
return unicode_type(self.text())
def fset(self, val):
@current_val.setter
def current_val(self, val):
self.setText(val)
self.setCursorPosition(0)
return property(fget=fget, fset=fset)
@property
def is_blank(self):
@ -119,14 +117,13 @@ class LanguagesEdit(LE):
if not is_new:
self.lineEdit().setReadOnly(True)
@dynamic_property
@property
def current_val(self):
def fget(self):
return self.lang_codes
def fset(self, val):
@current_val.setter
def current_val(self, val):
self.lang_codes = val
return property(fget=fget, fset=fset)
def from_mi(self, mi):
self.lang_codes = mi.languages
@ -241,17 +238,16 @@ class IdentifiersEdit(LineEdit):
def to_mi(self, mi):
mi.set_identifiers(self.as_dict)
@dynamic_property
@property
def as_dict(self):
def fget(self):
parts = (x.strip() for x in self.current_val.split(',') if x.strip())
return {k:v for k, v in iteritems({x.partition(':')[0].strip():x.partition(':')[-1].strip() for x in parts}) if k and v}
def fset(self, val):
@as_dict.setter
def as_dict(self, val):
val = ('%s:%s' % (k, v) for k, v in iteritems(val))
self.setText(', '.join(val))
self.setCursorPosition(0)
return property(fget=fget, fset=fset)
class CommentsEdit(Editor):
@ -269,15 +265,14 @@ class CommentsEdit(Editor):
self.hide_toolbars()
self.set_readonly(True)
@dynamic_property
@property
def current_val(self):
def fget(self):
return self.html
def fset(self, val):
@current_val.setter
def current_val(self, val):
self.html = val or ''
self.changed.emit()
return property(fget=fget, fset=fset)
def from_mi(self, mi):
val = mi.get(self.field, default='')
@ -315,16 +310,15 @@ class CoverView(QWidget):
def is_blank(self):
return self.pixmap is None
@dynamic_property
@property
def current_val(self):
def fget(self):
return self.pixmap
def fset(self, val):
@current_val.setter
def current_val(self, val):
self.pixmap = val
self.changed.emit()
self.update()
return property(fget=fget, fset=fset)
def from_mi(self, mi):
p = getattr(mi, 'cover', None)

View File

@ -138,35 +138,33 @@ class ConditionEditor(QWidget): # {{{
b.setSizeAdjustPolicy(b.AdjustToMinimumContentsLengthWithIcon)
b.setMinimumContentsLength(20)
@dynamic_property
@property
def current_col(self):
def fget(self):
idx = self.column_box.currentIndex()
return unicode_type(self.column_box.itemData(idx) or '')
def fset(self, val):
@current_col.setter
def current_col(self, val):
for idx in range(self.column_box.count()):
c = unicode_type(self.column_box.itemData(idx) or '')
if c == val:
self.column_box.setCurrentIndex(idx)
return
raise ValueError('Column %r not found'%val)
return property(fget=fget, fset=fset)
@dynamic_property
@property
def current_action(self):
def fget(self):
idx = self.action_box.currentIndex()
return unicode_type(self.action_box.itemData(idx) or '')
def fset(self, val):
@current_action.setter
def current_action(self, val):
for idx in range(self.action_box.count()):
c = unicode_type(self.action_box.itemData(idx) or '')
if c == val:
self.action_box.setCurrentIndex(idx)
return
raise ValueError('Action %r not valid for current column'%val)
return property(fget=fget, fset=fset)
@property
def current_val(self):
@ -176,17 +174,17 @@ class ConditionEditor(QWidget): # {{{
ans = rmap.get(lower(ans), ans)
return ans
@dynamic_property
@property
def condition(self):
def fget(self):
c, a, v = (self.current_col, self.current_action,
self.current_val)
if not c or not a:
return None
return (c, a, v)
def fset(self, condition):
@condition.setter
def condition(self, condition):
c, a, v = condition
if not v:
v = ''
@ -195,8 +193,6 @@ class ConditionEditor(QWidget): # {{{
self.current_action = a
self.value_box.setText(v)
return property(fget=fget, fset=fset)
def init_action_box(self):
self.action_box.blockSignals(True)
self.action_box.clear()

View File

@ -62,23 +62,21 @@ class ResizeDialog(QDialog): # {{{
other.setValue(oval)
other.blockSignals(False)
@dynamic_property
@property
def width(self):
def fget(self):
return self._width.value()
def fset(self, val):
@width.setter
def width(self, val):
self._width.setValue(val)
return property(fget=fget, fset=fset)
@dynamic_property
@property
def height(self):
def fget(self):
return self._height.value()
def fset(self, val):
@height.setter
def height(self, val):
self._height.setValue(val)
return property(fget=fget, fset=fset)
# }}}
@ -111,24 +109,22 @@ class Editor(QMainWindow):
self.canvas.undo_redo_state_changed.connect(self.undo_redo_state_changed)
self.canvas.selection_state_changed.connect(self.update_clipboard_actions)
@dynamic_property
@property
def is_modified(self):
def fget(self):
return self._is_modified
def fset(self, val):
@is_modified.setter
def is_modified(self, val):
self._is_modified = val
self.modification_state_changed.emit(val)
return property(fget=fget, fset=fset)
@dynamic_property
@property
def current_editing_state(self):
def fget(self):
return {}
def fset(self, val):
@current_editing_state.setter
def current_editing_state(self, val):
pass
return property(fget=fget, fset=fset)
@property
def undo_available(self):
@ -138,14 +134,13 @@ class Editor(QMainWindow):
def redo_available(self):
return self.canvas.redo_action.isEnabled()
@dynamic_property
@property
def current_line(self):
def fget(self):
return 0
def fset(self, val):
@current_line.setter
def current_line(self, val):
pass
return property(fget=fget, fset=fset)
@property
def number_of_lines(self):
@ -160,15 +155,14 @@ class Editor(QMainWindow):
def get_raw_data(self):
return self.canvas.get_image_data(quality=self.quality)
@dynamic_property
@property
def data(self):
def fget(self):
return self.get_raw_data()
def fset(self, val):
@data.setter
def data(self, val):
self.canvas.load_image(val)
self._is_modified = False # The image_changed signal will have been triggered causing this editor to be incorrectly marked as modified
return property(fget=fget, fset=fset)
def replace_data(self, raw, only_if_different=True):
# We ignore only_if_different as it is useless in our case, and

View File

@ -221,9 +221,8 @@ class EditorTabStop(object):
with m:
m.text = text
@dynamic_property
@property
def text(self):
def fget(self):
editor = self.editor()
if editor is None or self.is_deleted:
return ''
@ -231,7 +230,8 @@ class EditorTabStop(object):
c.setPosition(self.left), c.setPosition(self.right, c.KeepAnchor)
return editor.selected_text_from_cursor(c)
def fset(self, text):
@text.setter
def text(self, text):
editor = self.editor()
if editor is None or self.is_deleted:
return
@ -240,7 +240,6 @@ class EditorTabStop(object):
c.setPosition(self.left), c.setPosition(self.right, c.KeepAnchor)
c.insertText(text)
c.endEditBlock()
return property(fget=fget, fset=fset)
def set_editor_cursor(self, editor):
if not self.is_deleted:
@ -537,12 +536,8 @@ class EditSnippet(QWidget):
self.types.item(0).setCheckState(Qt.Checked)
(self.name if self.creating_snippet else self.template).setFocus(Qt.OtherFocusReason)
@dynamic_property
@property
def snip(self):
def fset(self, snip):
self.apply_snip(snip)
def fget(self):
ftypes = []
for i in range(self.types.count()):
i = self.types.item(i)
@ -550,7 +545,9 @@ class EditSnippet(QWidget):
ftypes.append(i.data(Qt.UserRole))
return {'description':self.name.text().strip(), 'trigger':self.trig.text(), 'template':self.template.toPlainText(), 'syntaxes':ftypes}
return property(fget=fget, fset=fset)
@snip.setter
def snip(self, snip):
self.apply_snip(snip)
def validate(self):
snip = self.snip

View File

@ -206,17 +206,15 @@ class TextEdit(PlainTextEdit):
insert_text(md.html())
return
@dynamic_property
@property
def is_modified(self):
''' True if the document has been modified since it was loaded or since
the last time is_modified was set to False. '''
def fget(self):
return self.document().isModified()
def fset(self, val):
@is_modified.setter
def is_modified(self, val):
self.document().setModified(bool(val))
return property(fget=fget, fset=fset)
def sizeHint(self):
return self.size_hint

View File

@ -159,28 +159,26 @@ class Editor(QMainWindow):
self.editor.link_clicked.connect(self.link_clicked)
self.editor.smart_highlighting_updated.connect(self.smart_highlighting_updated)
@dynamic_property
@property
def current_line(self):
def fget(self):
return self.editor.textCursor().blockNumber()
def fset(self, val):
@current_line.setter
def current_line(self, val):
self.editor.go_to_line(val)
return property(fget=fget, fset=fset)
@dynamic_property
@property
def current_editing_state(self):
def fget(self):
c = self.editor.textCursor()
return {'cursor':(c.anchor(), c.position())}
def fset(self, val):
@current_editing_state.setter
def current_editing_state(self, val):
anchor, position = val.get('cursor', (None, None))
if anchor is not None and position is not None:
c = self.editor.textCursor()
c.setPosition(anchor), c.setPosition(position, c.KeepAnchor)
self.editor.setTextCursor(c)
return property(fget=fget, fset=fset)
def current_tag(self, for_position_sync=True):
return self.editor.current_tag(for_position_sync=for_position_sync)
@ -189,18 +187,17 @@ class Editor(QMainWindow):
def number_of_lines(self):
return self.editor.blockCount()
@dynamic_property
@property
def data(self):
def fget(self):
ans = self.get_raw_data()
ans, changed = replace_encoding_declarations(ans, enc='utf-8', limit=4*1024)
if changed:
self.data = ans
return ans.encode('utf-8')
def fset(self, val):
@data.setter
def data(self, val):
self.editor.load_text(val, syntax=self.syntax, doc_name=editor_name(self))
return property(fget=fget, fset=fset)
def init_from_template(self, template):
self.editor.load_text(template, syntax=self.syntax, process_template=True, doc_name=editor_name(self))
@ -317,14 +314,13 @@ class Editor(QMainWindow):
def has_marked_text(self):
return self.editor.current_search_mark is not None
@dynamic_property
@property
def is_modified(self):
def fget(self):
return self.editor.is_modified
def fset(self, val):
@is_modified.setter
def is_modified(self, val):
self.editor.is_modified = val
return property(fget=fget, fset=fset)
def create_toolbars(self):
self.action_bar = b = self.addToolBar(_('Edit actions tool bar'))

View File

@ -370,17 +370,16 @@ class WebView(QWebView):
def refresh(self):
self.pageAction(self.page().Reload).trigger()
@dynamic_property
@property
def scroll_pos(self):
def fget(self):
mf = self.page().mainFrame()
return (mf.scrollBarValue(Qt.Horizontal), mf.scrollBarValue(Qt.Vertical))
def fset(self, val):
@scroll_pos.setter
def scroll_pos(self, val):
mf = self.page().mainFrame()
mf.setScrollBarValue(Qt.Horizontal, val[0])
mf.setScrollBarValue(Qt.Vertical, val[1])
return property(fget=fget, fset=fset)
def clear(self):
self.setHtml(_(

View File

@ -1061,14 +1061,13 @@ class CSSWidget(QWidget):
self.summary = la = QLabel('\xa0')
h.addWidget(la)
@dynamic_property
@property
def sort_order(self):
def fget(self):
return [Qt.AscendingOrder, Qt.DescendingOrder][self._sort_order.currentIndex()]
def fset(self, val):
@sort_order.setter
def sort_order(self, val):
self._sort_order.setCurrentIndex({Qt.AscendingOrder:0}.get(val, 1))
return property(fget=fget, fset=fset)
def update_summary(self):
self.summary.setText(_('{0} rules, {1} unused').format(self.model.rowCount(), self.model.num_unused))

View File

@ -152,16 +152,15 @@ class WhereBox(QComboBox):
f.setBold(True), f.setItalic(True)
self.setFont(f)
@dynamic_property
@property
def where(self):
wm = {0:'current', 1:'text', 2:'styles', 3:'selected', 4:'open', 5:'selected-text'}
def fget(self):
return wm[self.currentIndex()]
def fset(self, val):
@where.setter
def where(self, val):
wm = {0:'current', 1:'text', 2:'styles', 3:'selected', 4:'open', 5:'selected-text'}
self.setCurrentIndex({v:k for k, v in iteritems(wm)}[val])
return property(fget=fget, fset=fset)
def showPopup(self):
# We do it like this so that the popup uses a normal font
@ -190,14 +189,13 @@ class DirectionBox(QComboBox):
<dd>Search for the previous match from your current position</dd>
</dl>'''))
@dynamic_property
@property
def direction(self):
def fget(self):
return 'down' if self.currentIndex() == 0 else 'up'
def fset(self, val):
@direction.setter
def direction(self, val):
self.setCurrentIndex(1 if val == 'up' else 0)
return property(fget=fget, fset=fset)
class ModeBox(QComboBox):
@ -216,14 +214,13 @@ class ModeBox(QComboBox):
<dd>The search expression is interpreted as a regular expression. The replace expression is an arbitrarily powerful Python function.</dd>
</dl>'''))
@dynamic_property
@property
def mode(self):
def fget(self):
return ('normal', 'regex', 'function')[self.currentIndex()]
def fset(self, val):
@mode.setter
def mode(self, val):
self.setCurrentIndex({'regex':1, 'function':2}.get(val, 0))
return property(fget=fget, fset=fset)
class SearchWidget(QWidget):
@ -353,91 +350,82 @@ class SearchWidget(QWidget):
self.replace_text.setVisible(not function_mode)
self.functions_container.setVisible(function_mode)
@dynamic_property
@property
def mode(self):
def fget(self):
return self.mode_box.mode
def fset(self, val):
@mode.setter
def mode(self, val):
self.mode_box.mode = val
self.da.setVisible(self.mode in ('regex', 'function'))
return property(fget=fget, fset=fset)
@dynamic_property
@property
def find(self):
def fget(self):
return unicode_type(self.find_text.text())
def fset(self, val):
@find.setter
def find(self, val):
self.find_text.setText(val)
return property(fget=fget, fset=fset)
@dynamic_property
@property
def replace(self):
def fget(self):
if self.mode == 'function':
return self.functions.text()
return unicode_type(self.replace_text.text())
def fset(self, val):
@replace.setter
def replace(self, val):
self.replace_text.setText(val)
return property(fget=fget, fset=fset)
@dynamic_property
@property
def where(self):
def fget(self):
return self.where_box.where
def fset(self, val):
@where.setter
def where(self, val):
self.where_box.where = val
return property(fget=fget, fset=fset)
@dynamic_property
@property
def case_sensitive(self):
def fget(self):
return self.cs.isChecked()
def fset(self, val):
@case_sensitive.setter
def case_sensitive(self, val):
self.cs.setChecked(bool(val))
return property(fget=fget, fset=fset)
@dynamic_property
@property
def direction(self):
def fget(self):
return self.direction_box.direction
def fset(self, val):
@direction.setter
def direction(self, val):
self.direction_box.direction = val
return property(fget=fget, fset=fset)
@dynamic_property
@property
def wrap(self):
def fget(self):
return self.wr.isChecked()
def fset(self, val):
@wrap.setter
def wrap(self, val):
self.wr.setChecked(bool(val))
return property(fget=fget, fset=fset)
@dynamic_property
@property
def dot_all(self):
def fget(self):
return self.da.isChecked()
def fset(self, val):
@dot_all.setter
def dot_all(self, val):
self.da.setChecked(bool(val))
return property(fget=fget, fset=fset)
@dynamic_property
@property
def state(self):
def fget(self):
return {x:getattr(self, x) for x in self.DEFAULT_STATE}
def fset(self, val):
@state.setter
def state(self, val):
for x in self.DEFAULT_STATE:
if x in val:
setattr(self, x, val[x])
return property(fget=fget, fset=fset)
def restore_state(self):
self.state = tprefs.get('find-widget-state', self.DEFAULT_STATE)
@ -1008,14 +996,13 @@ class SavedSearches(QWidget):
self.searches.setFocus(Qt.OtherFocusReason)
@dynamic_property
@property
def state(self):
def fget(self):
return {'wrap':self.wrap, 'direction':self.direction, 'where':self.where}
def fset(self, val):
@state.setter
def state(self, val):
self.wrap, self.where, self.direction = val['wrap'], val['where'], val['direction']
return property(fget=fget, fset=fset)
def save_state(self):
tprefs['saved_seaches_state'] = self.state
@ -1042,32 +1029,29 @@ class SavedSearches(QWidget):
for x in ('eb', 'ab', 'rb', 'upb', 'dnb', 'd2', 'filter_text', 'cft', 'd3', 'ib', 'eb2'):
getattr(self, x).setVisible(visible)
@dynamic_property
@property
def where(self):
def fget(self):
return self.where_box.where
def fset(self, val):
@where.setter
def where(self, val):
self.where_box.where = val
return property(fget=fget, fset=fset)
@dynamic_property
@property
def direction(self):
def fget(self):
return self.direction_box.direction
def fset(self, val):
@direction.setter
def direction(self, val):
self.direction_box.direction = val
return property(fget=fget, fset=fset)
@dynamic_property
@property
def wrap(self):
def fget(self):
return self.wr.isChecked()
def fset(self, val):
@wrap.setter
def wrap(self, val):
self.wr.setChecked(bool(val))
return property(fget=fget, fset=fset)
def do_filter(self, text):
self.model.do_filter(text)

View File

@ -36,14 +36,13 @@ class ModeBox(QComboBox):
<dd>The search expression is interpreted as a regular expression. See the User Manual for more help on using regular expressions.</dd>
</dl>'''))
@dynamic_property
@property
def mode(self):
def fget(self):
return ('normal', 'regex')[self.currentIndex()]
def fset(self, val):
@mode.setter
def mode(self, val):
self.setCurrentIndex({'regex':1}.get(val, 0))
return property(fget=fget, fset=fset)
class WhereBox(QComboBox):
@ -71,16 +70,15 @@ class WhereBox(QComboBox):
f.setBold(True), f.setItalic(True)
self.setFont(f)
@dynamic_property
@property
def where(self):
wm = {0:'current', 1:'text', 2:'selected', 3:'open'}
def fget(self):
return wm[self.currentIndex()]
def fset(self, val):
@where.setter
def where(self, val):
wm = {0:'current', 1:'text', 2:'selected', 3:'open'}
self.setCurrentIndex({v:k for k, v in iteritems(wm)}[val])
return property(fget=fget, fset=fset)
def showPopup(self):
# We do it like this so that the popup uses a normal font
@ -137,17 +135,16 @@ class TextSearch(QWidget):
state = tprefs.get('text_search_widget_state')
self.state = state or {}
@dynamic_property
@property
def state(self):
def fget(self):
return {'mode': self.mode.mode, 'where':self.where_box.where, 'case_sensitive':self.cs.isChecked(), 'dot_all':self.da.isChecked()}
def fset(self, val):
@state.setter
def state(self, val):
self.mode.mode = val.get('mode', 'normal')
self.where_box.where = val.get('where', 'current')
self.cs.setChecked(bool(val.get('case_sensitive')))
self.da.setChecked(bool(val.get('dot_all', True)))
return property(fget=fget, fset=fset)
def save_state(self):
tprefs['text_search_widget_state'] = self.state

View File

@ -236,17 +236,16 @@ class ConfigDialog(QDialog, Ui_Dialog):
from calibre.gui2.viewer.main import dprefs
self.word_lookups = dprefs['word_lookups']
@dynamic_property
@property
def word_lookups(self):
def fget(self):
return dict(self.dictionary_list.item(i).data(Qt.UserRole) for i in range(self.dictionary_list.count()))
def fset(self, wl):
@word_lookups.setter
def word_lookups(self, wl):
self.dictionary_list.clear()
for langcode, url in sorted(iteritems(wl), key=lambda lc_url:sort_key(calibre_langcode_to_name(lc_url[0]))):
i = QListWidgetItem('%s: %s' % (calibre_langcode_to_name(langcode), url), self.dictionary_list)
i.setData(Qt.UserRole, (langcode, url))
return property(fget=fget, fset=fset)
def add_dictionary_website(self):
class AD(QDialog):

View File

@ -430,9 +430,8 @@ class Document(QWebPage): # {{{
def xpos(self):
return self.mainFrame().scrollPosition().x()
@dynamic_property
@property
def scroll_fraction(self):
def fget(self):
if self.in_paged_mode:
return self.javascript('''
ans = 0.0;
@ -446,7 +445,8 @@ class Document(QWebPage): # {{{
except ZeroDivisionError:
return 0.
def fset(self, val):
@scroll_fraction.setter
def scroll_fraction(self, val):
if self.in_paged_mode and self.loaded_javascript:
self.javascript('paged_display.scroll_to_pos(%f)'%val)
else:
@ -454,22 +454,19 @@ class Document(QWebPage): # {{{
if npos < 0:
npos = 0
self.scroll_to(x=self.xpos, y=npos)
return property(fget=fget, fset=fset)
@dynamic_property
@property
def page_number(self):
' The page number is the number of the page at the left most edge of the screen (starting from 0) '
def fget(self):
if self.in_paged_mode:
return self.javascript(
'ans = 0; if (window.paged_display) ans = window.paged_display.column_boundaries()[0]; ans;', typ='int')
def fset(self, val):
@page_number.setter
def page_number(self, val):
if self.in_paged_mode and self.loaded_javascript:
self.javascript('if (window.paged_display) window.paged_display.scroll_to_column(%d)' % int(val))
return True
return property(fget=fget, fset=fset)
@property
def page_dimensions(self):
@ -862,14 +859,13 @@ class DocumentView(QWebView): # {{{
def sizeHint(self):
return self._size_hint
@dynamic_property
@property
def scroll_fraction(self):
def fget(self):
return self.document.scroll_fraction
def fset(self, val):
@scroll_fraction.setter
def scroll_fraction(self, val):
self.document.scroll_fraction = float(val)
return property(fget=fget, fset=fset)
@property
def hscroll_fraction(self):
@ -879,14 +875,13 @@ class DocumentView(QWebView): # {{{
def content_size(self):
return self.document.width, self.document.height
@dynamic_property
@property
def current_language(self):
def fget(self):
return self.document.current_language
def fset(self, val):
@current_language.setter
def current_language(self, val):
self.document.current_language = val
return property(fget=fget, fset=fset)
def search(self, text, backwards=False):
flags = self.document.FindBackward if backwards else self.document.FindFlags(0)
@ -1189,19 +1184,18 @@ class DocumentView(QWebView): # {{{
if notify and self.manager is not None and new_pos != old_pos:
self.manager.scrolled(self.scroll_fraction)
@dynamic_property
@property
def multiplier(self):
def fget(self):
return self.zoomFactor()
def fset(self, val):
@multiplier.setter
def multiplier(self, val):
oval = self.zoomFactor()
self.setZoomFactor(val)
if val != oval:
if self.document.in_paged_mode:
self.document.update_contents_size_for_paged_mode()
self.magnification_changed.emit(val)
return property(fget=fget, fset=fset)
def magnify_fonts(self, amount=None):
if amount is None:

View File

@ -1131,14 +1131,14 @@ class Splitter(QSplitter):
print(self.save_name, 'side:', self.side_index_size, 'other:', end=' ')
print(list(self.sizes())[self.other_index])
@dynamic_property
@property
def side_index_size(self):
def fget(self):
if self.count() < 2:
return 0
return self.sizes()[self.side_index]
def fset(self, val):
@side_index_size.setter
def side_index_size(self, val):
if self.count() < 2:
return
if val == 0 and not self.is_side_index_hidden:
@ -1154,8 +1154,6 @@ class Splitter(QSplitter):
self.setSizes(sizes)
self.initialize()
return property(fget=fget, fset=fset)
def do_resize(self, *args):
orig = self.desired_side_size
QSplitter.resizeEvent(self, self._resize_ev)

View File

@ -86,12 +86,12 @@ class ColorButton(QPushButton):
self.color = initial_color
self.clicked.connect(self.choose_color)
@dynamic_property
@property
def color(self):
def fget(self):
return self._color
def fset(self, val):
@color.setter
def color(self, val):
val = unicode_type(val or '')
col = QColor(val)
orig = self._color
@ -107,7 +107,6 @@ class ColorButton(QPushButton):
self.setIcon(QIcon())
if orig != col:
self.color_changed.emit(self._color)
return property(fget=fget, fset=fset)
def choose_color(self):
col = QColorDialog.getColor(QColor(self._color or Qt.white), self, _('Choose a color'))

View File

@ -827,13 +827,10 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE;
# _lock_file = None
self.conn.close()
@dynamic_property
@property
def user_version(self):
doc = 'The user version of this database'
def fget(self):
'The user version of this database'
return self.conn.get('pragma user_version;', all=False)
return property(doc=doc, fget=fget)
def is_empty(self):
return not self.conn.get('SELECT id FROM books LIMIT 1', all=False)

View File

@ -75,25 +75,19 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
PATH_LIMIT = 40 if 'win32' in sys.platform else 100
WINDOWS_LIBRARY_PATH_LIMIT = 75
@dynamic_property
@property
def user_version(self):
doc = 'The user version of this database'
def fget(self):
'The user version of this database'
return self.conn.get('pragma user_version;', all=False)
def fset(self, val):
@user_version.setter
def user_version(self, val):
self.conn.execute('pragma user_version=%d'%int(val))
self.conn.commit()
return property(doc=doc, fget=fget, fset=fset)
@dynamic_property
@property
def library_id(self):
doc = ('The UUID for this library. As long as the user only operates'
' on libraries with calibre, it will be unique')
def fget(self):
'''The UUID for this library. As long as the user only operates on libraries with calibre, it will be unique'''
if self._library_id_ is None:
ans = self.conn.get('SELECT uuid FROM library_id', all=False)
if ans is None:
@ -103,7 +97,8 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
self._library_id_ = ans
return self._library_id_
def fset(self, val):
@library_id.setter
def library_id(self, val):
self._library_id_ = unicode_type(val)
self.conn.executescript('''
DELETE FROM library_id;
@ -111,8 +106,6 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
'''%self._library_id_)
self.conn.commit()
return property(doc=doc, fget=fget, fset=fset)
def connect(self):
if iswindows and len(self.library_path) + 4*self.PATH_LIMIT + 10 > 259:
raise ValueError(_(

View File

@ -57,47 +57,43 @@ class Image(object):
def to_qimage(self):
return clone_image(self.img)
@dynamic_property
@property
def type(self):
def fget(self):
if len(self.img.colorTable()) > 0:
return 'PaletteType'
return 'TrueColorType'
def fset(self, t):
@type.setter
def type(self, t):
if t == 'GrayscaleType':
self.img = grayscale_image(self.img)
elif t == 'PaletteType':
self.img = quantize_image(self.img)
return property(fget=fget, fset=fset)
@dynamic_property
@property
def format(self):
def fget(self):
return self.write_format or self.read_format
def fset(self, val):
@format.setter
def format(self, val):
self.write_format = val
return property(fget=fget, fset=fset)
@dynamic_property
@property
def colorspace(self):
def fget(self):
return 'RGBColorspace'
def fset(self, val):
@colorspace.setter
def colorspace(self, val):
raise NotImplementedError('Changing image colorspace is not supported')
return property(fget=fget, fset=fset)
@dynamic_property
@property
def size(self):
def fget(self):
return self.img.width(), self.img.height()
def fset(self, val):
@size.setter
def size(self, val):
w, h = val[:2]
self.img = resize_image(self.img, w, h)
return property(fget=fget, fset=fset)
def save(self, path, format=None):
if format is None:

View File

@ -57,32 +57,29 @@ class Article(object):
self.localtime = self.utctime.astimezone(local_tz)
self._formatted_date = None
@dynamic_property
@property
def formatted_date(self):
def fget(self):
if self._formatted_date is None:
self._formatted_date = strftime(" [%a, %d %b %H:%M]",
t=self.localtime.timetuple())
return self._formatted_date
def fset(self, val):
@formatted_date.setter
def formatted_date(self, val):
if isinstance(val, unicode_type):
self._formatted_date = val
return property(fget=fget, fset=fset)
@dynamic_property
@property
def title(self):
def fget(self):
t = self._title
if not isinstance(t, unicode_type) and hasattr(t, 'decode'):
t = t.decode('utf-8', 'replace')
return t
def fset(self, val):
@title.setter
def title(self, val):
self._title = clean_ascii_chars(val)
return property(fget=fget, fset=fset)
def __repr__(self):
return \