diff --git a/sabnzbd/api.py b/sabnzbd/api.py index 5800fa9..815426c 100644 --- a/sabnzbd/api.py +++ b/sabnzbd/api.py @@ -793,7 +793,7 @@ def _api_undefined(name, output, kwargs): def _api_browse(name, output, kwargs): """ Return tree of local path """ compact = kwargs.get('compact') - + if compact and compact == '1': paths = [] name = platform_encode(kwargs.get('term', '')) @@ -1253,14 +1253,14 @@ def build_status(web_dir=None, root=None, prim=True, skip_dashboard=False, outpu # For the templates or for JSON if output: - server_info = { 'servername': server.displayname, - 'serveractiveconn': connected, - 'servertotalconn': server.threads, - 'serverconnections': serverconnections, + server_info = { 'servername': server.displayname, + 'serveractiveconn': connected, + 'servertotalconn': server.threads, + 'serverconnections': serverconnections, 'serverssl': server.ssl, - 'serveractive': server.active, - 'servererror': server.errormsg, - 'serverpriority': server.priority, + 'serveractive': server.active, + 'servererror': server.errormsg, + 'serverpriority': server.priority, 'serveroptional': server.optional } info['servers'].append(server_info) else: @@ -1302,8 +1302,8 @@ def build_queue(web_dir=None, root=None, prim=True, webdir='', start=0, limit=0, if info['finish'] > info['noofslots']: info['finish'] = info['noofslots'] info['queue_details'] = '0' - if 'queue_details' in cherrypy.request.cookie: - info['queue_details'] = str(int_conv(cherrypy.request.cookie['queue_details'].value)) + if 'queue_details' in cherrypy.request.cookie: + info['queue_details'] = str(int_conv(cherrypy.request.cookie['queue_details'].value)) n = 0 running_bytes = 0 diff --git a/sabnzbd/encoding.py b/sabnzbd/encoding.py index d033f5e..fbd1395 100644 --- a/sabnzbd/encoding.py +++ b/sabnzbd/encoding.py @@ -91,7 +91,7 @@ def yenc_name_fixer(p): return p.decode('utf-8') except: return p.decode('cp1252') - + def is_utf8(p): """ Return True when p is UTF-8 or plain ASCII """ diff --git a/sabnzbd/interface.py b/sabnzbd/interface.py index ea389db..f446bf1 100644 --- a/sabnzbd/interface.py +++ b/sabnzbd/interface.py @@ -96,7 +96,7 @@ def check_access(access_type=4): `access_type`: 1=nzb, 2=api, 3=full_api, 4=webui, 5=webui with login for external """ referrer = cherrypy.request.remote.ip - + # CherryPy will report ::ffff:192.168.0.10 on dual-stack situation # It will always contain that ::ffff: prefix range_ok = (not cfg.local_ranges()) or bool([1 for r in cfg.local_ranges() if (referrer.startswith(r) or referrer.replace('::ffff:', '').startswith(r))]) @@ -169,9 +169,9 @@ COOKIE_SECRET = str(randint(1000,100000)*os.getpid()) def set_login_cookie(remove=False, remember_me=False): """ We try to set a cookie as unique as possible - to the current user. Based on it's IP and the + to the current user. Based on it's IP and the current process ID of the SAB instance and a random - number, so cookies cannot be re-used + number, so cookies cannot be re-used """ salt = randint(1,1000) cherrypy.response.cookie['login_cookie'] = hashlib.sha1(str(salt) + cherrypy.request.remote.ip + COOKIE_SECRET).hexdigest() @@ -190,7 +190,7 @@ def set_login_cookie(remove=False, remember_me=False): cherrypy.response.cookie['login_salt']['expires'] = 0 else: # Notify about new login - notifier.send_notification(T('User logged in'), T('User logged in to the web interface'), 'new_login') + notifier.send_notification(T('User logged in'), T('User logged in to the web interface'), 'new_login') def check_login_cookie(): # Do we have everything? @@ -319,7 +319,7 @@ class MainPage(object): if first == 2: # Setup addresses with /sabnzbd prefix for primary and secondary skin self.sabnzbd = MainPage(web_dir, '/sabnzbd/', web_dir2, '/sabnzbd/m/', web_dirc=web_dirc, prim=True, first=1) - + self.login = LoginPage(web_dirc, root + 'login/', prim) self.queue = QueuePage(web_dir, root + 'queue/', prim) self.history = HistoryPage(web_dir, root + 'history/', prim) @@ -357,7 +357,7 @@ class MainPage(object): info['cat_list'] = list_cats(True) info['have_rss_defined'] = bool(config.get_rss()) info['have_watched_dir'] = bool(cfg.dirscan_dir()) - + # Have logout only with HTML and if inet=5, only when we are external info['have_logout'] = cfg.username() and cfg.password() and (cfg.html_login() and (cfg.inet_exposure() < 5 or (cfg.inet_exposure() == 5 and not check_access(access_type=6)))) @@ -602,7 +602,7 @@ class LoginPage(object): raise dcRaiser('../', kwargs) elif kwargs.get('username') or kwargs.get('password'): info['error'] = T('Authentication failed, check username/password.') - + # Show login template = Template(file=os.path.join(self.__web_dir, 'login', 'main.tmpl'), filter=FILTER, searchList=[info], compilerSettings=DIRECTIVES) @@ -1488,16 +1488,16 @@ class ConfigSwitches(object): SPECIAL_BOOL_LIST = \ ('start_paused', 'no_penalties', 'ignore_wrong_unrar', 'create_group_folders', 'queue_complete_pers', 'api_warnings', 'allow_64bit_tools', - 'prospective_par_download', 'never_repair', 'allow_streaming', 'ignore_unrar_dates', + 'prospective_par_download', 'never_repair', 'allow_streaming', 'ignore_unrar_dates', 'osx_menu', 'osx_speed', 'win_menu', 'use_pickle', 'allow_incomplete_nzb', 'rss_filenames', 'no_ipv6', 'keep_awake', 'empty_postproc', 'html_login', 'web_watchdog', 'wait_for_dfolder', 'warn_empty_nzb', 'enable_bonjour', - 'allow_duplicate_files', 'warn_dupl_jobs', 'backup_for_duplicates', 'enable_par_cleanup', + 'allow_duplicate_files', 'warn_dupl_jobs', 'backup_for_duplicates', 'enable_par_cleanup', 'enable_https_verification', 'api_logging', 'fixed_ports' ) SPECIAL_VALUE_LIST = \ ('size_limit', 'folder_max_length', 'fsys_type', 'movie_rename_limit', 'nomedia_marker', - 'req_completion_rate', 'wait_ext_drive', 'history_limit', 'show_sysload', + 'req_completion_rate', 'wait_ext_drive', 'history_limit', 'show_sysload', 'ipv6_servers', 'rating_host', 'selftest_host' ) SPECIAL_LIST_LIST = \ @@ -2329,7 +2329,7 @@ class ConfigScheduling(object): actions_lng = {} for action in actions: actions_lng[action] = Ttemplate("sch-" + action) - + actions_servers = {} servers = config.get_servers() for srv in servers: @@ -2640,7 +2640,7 @@ class Status(object): return msg orphan_delete(kwargs) raise dcRaiser(self.__root, kwargs) - + @cherrypy.expose def delete_all(self, **kwargs): msg = check_session(kwargs) diff --git a/sabnzbd/nzbqueue.py b/sabnzbd/nzbqueue.py index 3397f34..a20c382 100644 --- a/sabnzbd/nzbqueue.py +++ b/sabnzbd/nzbqueue.py @@ -891,7 +891,7 @@ class NzbQueue(TryList): if (not limit) or (start <= n < start+limit): pnfo_list.append(nzo.gather_info()) n += 1 - + if not search: n = len(self.__nzo_list) return QNFO(bytes_total, bytes_left, pnfo_list, q_size, n) diff --git a/sabnzbd/skintext.py b/sabnzbd/skintext.py index 28318fd..0262b7a 100644 --- a/sabnzbd/skintext.py +++ b/sabnzbd/skintext.py @@ -564,7 +564,7 @@ SKIN_TEXT = { 'srv-send_group' : TT('Send Group'), 'srv-explain-send_group' : TT('Send group command before requesting articles.'), 'srv-categories' : TT('Categories'), - 'srv-explain-categories' : TT('Only use this server for these categories.'), + 'srv-explain-categories' : TT('Only use this server for these categories.'), 'srv-explain-no-categories' : TT('None of the enabled servers have the \'Default\' category selected. Jobs in the queue that are not assigned to one of the server\'s categories will not be downloaded.'), 'srv-notes' : TT('Personal notes'), @@ -846,7 +846,7 @@ SKIN_TEXT = { 'Glitter-notification-removing1' : TT('Removing job'), # Notification window 'Glitter-notification-removing' : TT('Removing jobs'), # Notification window 'Glitter-notification-shutdown' : TT('Shutting down'), # Notification window - + #Plush skin 'Plush-confirmWithoutSavingPrompt' : TT('Changes have not been saved, and will be lost.'), 'Plush-confirm' : TT('Are you sure?'), diff --git a/sabnzbd/utils/configobj.py b/sabnzbd/utils/configobj.py index c1f6e6d..eae556a 100644 --- a/sabnzbd/utils/configobj.py +++ b/sabnzbd/utils/configobj.py @@ -153,29 +153,29 @@ class UnknownType(Exception): class Builder(object): - + def build(self, o): m = getattr(self, 'build_' + o.__class__.__name__, None) if m is None: raise UnknownType(o.__class__.__name__) return m(o) - + def build_List(self, o): return map(self.build, o.getChildren()) - + def build_Const(self, o): return o.value - + def build_Dict(self, o): d = {} i = iter(map(self.build, o.getChildren())) for el in i: d[el] = i.next() return d - + def build_Tuple(self, o): return tuple(self.build_List(o)) - + def build_Name(self, o): if o.name == 'None': return None @@ -183,10 +183,10 @@ class Builder(object): return True if o.name == 'False': return False - + # An undefined Name raise UnknownType('Undefined Name') - + def build_Add(self, o): real, imag = map(self.build_Const, o.getChildren()) try: @@ -196,14 +196,14 @@ class Builder(object): if not isinstance(imag, complex) or imag.real != 0.0: raise UnknownType('Add') return real+imag - + def build_Getattr(self, o): parent = self.build(o.expr) return getattr(parent, o.attrname) - + def build_UnarySub(self, o): return -self.build_Const(o.getChildren()[0]) - + def build_UnaryAdd(self, o): return self.build_Const(o.getChildren()[0]) @@ -317,7 +317,7 @@ class InterpolationEngine(object): # short-cut if not self._cookie in value: return value - + def recursive_interpolate(key, value, section, backtrail): """The function that does the actual work. @@ -417,7 +417,7 @@ class InterpolationEngine(object): (e.g., if we interpolated "$$" and returned "$"). """ raise NotImplementedError() - + class ConfigParserInterpolation(InterpolationEngine): @@ -466,27 +466,27 @@ interpolation_engines = { def __newobj__(cls, *args): # Hack for pickle - return cls.__new__(cls, *args) + return cls.__new__(cls, *args) class Section(dict): """ A dictionary-like object that represents a section in a config file. - + It does string interpolation if the 'interpolation' attribute of the 'main' object is set to True. - + Interpolation is tried first from this object, then from the 'DEFAULT' section of this object, next from the parent and its 'DEFAULT' section, and so on until the main object is reached. - + A Section will behave like an ordered dictionary - following the order of the ``scalars`` and ``sections`` attributes. You can use this to change the order of members. - + Iteration follows the order: scalars, then sections. """ - + def __setstate__(self, state): dict.update(self, state[0]) self.__dict__.update(state[1]) @@ -494,8 +494,8 @@ class Section(dict): def __reduce__(self): state = (dict(self), self.__dict__) return (__newobj__, (self.__class__,), state) - - + + def __init__(self, parent, depth, main, indict=None, name=None): """ * parent is the section above @@ -520,8 +520,8 @@ class Section(dict): # (rather than just passing to ``dict.__init__``) for entry, value in indict.iteritems(): self[entry] = value - - + + def _initialise(self): # the sequence of scalar values in this Section self.scalars = [] @@ -565,7 +565,7 @@ class Section(dict): def __getitem__(self, key): """Fetch the item and do string interpolation.""" val = dict.__getitem__(self, key) - if self.main.interpolation: + if self.main.interpolation: if isinstance(val, basestring): return self._interpolate(key, val) if isinstance(val, list): @@ -582,20 +582,20 @@ class Section(dict): def __setitem__(self, key, value, unrepr=False): """ Correctly set a value. - + Making dictionary values Section instances. (We have to special case 'Section' instances - which are also dicts) - + Keys must be strings. Values need only be strings (or lists of strings) if ``main.stringify`` is set. - + ``unrepr`` must be set when setting a value to a dictionary, without creating a new sub-section. """ if not isinstance(key, basestring): raise ValueError('The key "%s" is not a string.' % key) - + # add the comment if key not in self.comments: self.comments[key] = [] @@ -696,7 +696,7 @@ class Section(dict): """ A version of clear that also affects scalars/sections Also clears comments and configspec. - + Leaves other attributes alone : depth/main/parent are not affected """ @@ -770,10 +770,10 @@ class Section(dict): def dict(self): """ Return a deepcopy of self as a dictionary. - + All members that are ``Section`` instances are recursively turned to ordinary dictionaries - by calling their ``dict`` method. - + >>> n = a.dict() >>> n == a 1 @@ -798,7 +798,7 @@ class Section(dict): def merge(self, indict): """ A recursive update - useful for merging config files. - + >>> a = '''[section1] ... option1 = True ... [[subsection]] @@ -818,17 +818,17 @@ class Section(dict): if (key in self and isinstance(self[key], dict) and isinstance(val, dict)): self[key].merge(val) - else: + else: self[key] = val def rename(self, oldkey, newkey): """ Change a keyname to another, without changing position in sequence. - + Implemented so that transformations can be made on keys, as well as on values. (used by encode and decode) - + Also renames comments. """ if oldkey in self.scalars: @@ -856,30 +856,30 @@ class Section(dict): call_on_sections=False, **keywargs): """ Walk every member and call a function on the keyword and value. - + Return a dictionary of the return values - + If the function raises an exception, raise the errror unless ``raise_errors=False``, in which case set the return value to ``False``. - + Any unrecognised keyword arguments you pass to walk, will be pased on to the function you pass in. - + Note: if ``call_on_sections`` is ``True`` then - on encountering a subsection, *first* the function is called for the *whole* subsection, and then recurses into it's members. This means your function must be able to handle strings, dictionaries and lists. This allows you to change the key of subsections as well as for ordinary members. The return value when called on the whole subsection has to be discarded. - + See the encode and decode methods for examples, including functions. - + .. admonition:: caution - + You can use ``walk`` to transform the names of members of a section but you mustn't add or delete members. - + >>> config = '''[XXXXsection] ... XXXXkey = XXXXvalue'''.splitlines() >>> cfg = ConfigObj(config) @@ -942,17 +942,17 @@ class Section(dict): Accepts a key as input. The corresponding value must be a string or the objects (``True`` or 1) or (``False`` or 0). We allow 0 and 1 to retain compatibility with Python 2.2. - - If the string is one of ``True``, ``On``, ``Yes``, or ``1`` it returns + + If the string is one of ``True``, ``On``, ``Yes``, or ``1`` it returns ``True``. - - If the string is one of ``False``, ``Off``, ``No``, or ``0`` it returns + + If the string is one of ``False``, ``Off``, ``No``, or ``0`` it returns ``False``. - + ``as_bool`` is not case sensitive. - + Any other input will raise a ``ValueError``. - + >>> a = ConfigObj() >>> a['a'] = 'fish' >>> a.as_bool('a') @@ -984,10 +984,10 @@ class Section(dict): def as_int(self, key): """ A convenience method which coerces the specified value to an integer. - + If the value is an invalid literal for ``int``, a ``ValueError`` will be raised. - + >>> a = ConfigObj() >>> a['a'] = 'fish' >>> a.as_int('a') @@ -1007,10 +1007,10 @@ class Section(dict): def as_float(self, key): """ A convenience method which coerces the specified value to a float. - + If the value is an invalid literal for ``float``, a ``ValueError`` will be raised. - + >>> a = ConfigObj() >>> a['a'] = 'fish' >>> a.as_float('a') @@ -1024,13 +1024,13 @@ class Section(dict): 3.2000000000000002 """ return float(self[key]) - - + + def as_list(self, key): """ A convenience method which fetches the specified value, guaranteeing that it is a list. - + >>> a = ConfigObj() >>> a['a'] = 1 >>> a.as_list('a') @@ -1046,15 +1046,15 @@ class Section(dict): if isinstance(result, (tuple, list)): return list(result) return [result] - + def restore_default(self, key): """ Restore (and return) default value for the specified key. - + This method will only work for a ConfigObj that was created with a configspec and has been validated. - + If there is no default value for this key, ``KeyError`` is raised. """ default = self.default_values[key] @@ -1063,20 +1063,20 @@ class Section(dict): self.defaults.append(key) return default - + def restore_defaults(self): """ Recursively restore default values to all members that have them. - + This method will only work for a ConfigObj that was created with a configspec and has been validated. - + It doesn't delete or modify entries without default values. """ for key in self.default_values: self.restore_default(key) - + for section in self.sections: self[section].restore_defaults() @@ -1191,7 +1191,7 @@ class ConfigObj(Section): write_empty_values=False, _inspec=False): """ Parse a config file or create a config file object. - + ``ConfigObj(infile=None, configspec=None, encoding=None, interpolation=True, raise_errors=False, list_values=True, create_empty=False, file_error=False, stringify=True, @@ -1201,9 +1201,9 @@ class ConfigObj(Section): self._inspec = _inspec # init the superclass Section.__init__(self, self, 0, self) - + infile = infile or [] - + _options = {'configspec': configspec, 'encoding': encoding, 'interpolation': interpolation, 'raise_errors': raise_errors, 'list_values': list_values, @@ -1219,7 +1219,7 @@ class ConfigObj(Section): warnings.warn('Passing in an options dictionary to ConfigObj() is ' 'deprecated. Use **options instead.', DeprecationWarning, stacklevel=2) - + # TODO: check the values too. for entry in options: if entry not in OPTION_DEFAULTS: @@ -1230,18 +1230,18 @@ class ConfigObj(Section): keyword_value = _options[entry] if value != keyword_value: options[entry] = keyword_value - + # XXXX this ignores an explicit list_values = True in combination # with _inspec. The user should *never* do that anyway, but still... if _inspec: options['list_values'] = False - + self._initialise(options) configspec = options['configspec'] self._original_configspec = configspec self._load(infile, configspec) - - + + def _load(self, infile, configspec): if isinstance(infile, basestring): self.filename = infile @@ -1261,10 +1261,10 @@ class ConfigObj(Section): h.write('') h.close() infile = [] - + elif isinstance(infile, (list, tuple)): infile = list(infile) - + elif isinstance(infile, dict): # initialise self # the Section class handles creating subsections @@ -1277,18 +1277,18 @@ class ConfigObj(Section): this_section[section] = {} set_section(in_section[section], this_section[section]) set_section(infile, self) - + else: for entry in infile: self[entry] = infile[entry] del self._errors - + if configspec is not None: self._handle_configspec(configspec) else: self.configspec = None return - + elif getattr(infile, 'read', MISSING) is not MISSING: # This supports file like objects infile = infile.read() or [] @@ -1296,7 +1296,7 @@ class ConfigObj(Section): # in case it's not an 8 bit encoding else: raise TypeError('infile must be a filename, file like object, or list of lines.') - + if infile: # don't do it for the empty ConfigObj infile = self._handle_bom(infile) @@ -1314,7 +1314,7 @@ class ConfigObj(Section): break infile = [line.rstrip('\r\n') for line in infile] - + self._parse(infile) # if we had any errors, now is the time to raise them if self._errors: @@ -1332,17 +1332,17 @@ class ConfigObj(Section): raise error # delete private attributes del self._errors - + if configspec is None: self.configspec = None else: self._handle_configspec(configspec) - - + + def _initialise(self, options=None): if options is None: options = OPTION_DEFAULTS - + # initialise a few variables self.filename = None self._errors = [] @@ -1359,48 +1359,48 @@ class ConfigObj(Section): self.newlines = None self.write_empty_values = options['write_empty_values'] self.unrepr = options['unrepr'] - + self.initial_comment = [] self.final_comment = [] self.configspec = None - + if self._inspec: self.list_values = False - + # Clear section attributes as well Section._initialise(self) - - + + def __repr__(self): def _getval(key): try: return self[key] except MissingInterpolationOption: return dict.__getitem__(self, key) - return ('ConfigObj({%s})' % - ', '.join([('%s: %s' % (repr(key), repr(_getval(key)))) + return ('ConfigObj({%s})' % + ', '.join([('%s: %s' % (repr(key), repr(_getval(key)))) for key in (self.scalars + self.sections)])) - - + + def _handle_bom(self, infile): """ Handle any BOM, and decode if necessary. - + If an encoding is specified, that *must* be used - but the BOM should still be removed (and the BOM attribute set). - + (If the encoding is wrongly specified, then a BOM for an alternative encoding won't be discovered or removed.) - + If an encoding is not specified, UTF8 or UTF16 BOM will be detected and removed. The BOM attribute will be set. UTF16 will be decoded to unicode. - + NOTE: This method must not be called with an empty ``infile``. - + Specifying the *wrong* encoding is likely to cause a ``UnicodeDecodeError``. - + ``infile`` must always be returned as a list of lines, but may be passed in as a single string. """ @@ -1410,7 +1410,7 @@ class ConfigObj(Section): # the encoding specified doesn't have one # just decode return self._decode(infile, self.encoding) - + if isinstance(infile, (list, tuple)): line = infile[0] else: @@ -1432,18 +1432,18 @@ class ConfigObj(Section): ##self.BOM = True # Don't need to remove BOM return self._decode(infile, encoding) - + # If we get this far, will *probably* raise a DecodeError # As it doesn't appear to start with a BOM return self._decode(infile, self.encoding) - + # Must be UTF8 BOM = BOM_SET[enc] if not line.startswith(BOM): return self._decode(infile, self.encoding) - + newline = line[len(BOM):] - + # BOM removed if isinstance(infile, (list, tuple)): infile[0] = newline @@ -1451,7 +1451,7 @@ class ConfigObj(Section): infile = newline self.BOM = True return self._decode(infile, self.encoding) - + # No encoding specified - so we need to check for UTF8/UTF16 for BOM, (encoding, final_encoding) in BOMS.items(): if not line.startswith(BOM): @@ -1475,7 +1475,7 @@ class ConfigObj(Section): return infile # UTF16 - have to decode return self._decode(infile, encoding) - + # No BOM discovered and no encoding specified, just return if isinstance(infile, basestring): # infile read from a file will be a single string @@ -1494,7 +1494,7 @@ class ConfigObj(Section): def _decode(self, infile, encoding): """ Decode infile to unicode. Using the specified encoding. - + if is a string, it also needs converting to a list. """ if isinstance(infile, basestring): @@ -1535,14 +1535,14 @@ class ConfigObj(Section): temp_list_values = self.list_values if self.unrepr: self.list_values = False - + comment_list = [] done_start = False this_section = self maxline = len(infile) - 1 cur_index = -1 reset_comment = False - + while cur_index < maxline: if reset_comment: comment_list = [] @@ -1554,13 +1554,13 @@ class ConfigObj(Section): reset_comment = False comment_list.append(line) continue - + if not done_start: # preserve initial comment self.initial_comment = comment_list comment_list = [] done_start = True - + reset_comment = True # first we check if it's a section marker mat = self._sectionmarker.match(line) @@ -1574,7 +1574,7 @@ class ConfigObj(Section): self._handle_error("Cannot compute the section depth at line %s.", NestingError, infile, cur_index) continue - + if cur_depth < this_section.depth: # the new section is dropping back to a previous level try: @@ -1593,13 +1593,13 @@ class ConfigObj(Section): else: self._handle_error("Section too nested at line %s.", NestingError, infile, cur_index) - + sect_name = self._unquote(sect_name) if sect_name in parent: self._handle_error('Duplicate section name at line %s.', DuplicateError, infile, cur_index) continue - + # create the new section this_section = Section( parent, @@ -1702,7 +1702,7 @@ class ConfigObj(Section): """ Given a section and a depth level, walk back through the sections parents to see if the depth level matches a previous section. - + Return a reference to the right section, or raise a SyntaxError. """ @@ -1720,7 +1720,7 @@ class ConfigObj(Section): def _handle_error(self, text, ErrorClass, infile, cur_index): """ Handle an error according to the error settings. - + Either raise the error or store it. The error will have occured at ``cur_index`` """ @@ -1749,19 +1749,19 @@ class ConfigObj(Section): def _quote(self, value, multiline=True): """ Return a safely quoted version of a value. - + Raise a ConfigObjError if the value cannot be safely quoted. If multiline is ``True`` (default) then use triple quotes if necessary. - + * Don't quote values that don't need it. * Recursively quote members of a list and return a comma joined list. * Multiline is ``False`` for lists. * Obey list syntax for empty and single member lists. - + If ``list_values=False`` then the value is only quoted if it contains a ``\\n`` (is multiline) or '#'. - + If ``write_empty_values`` is set, and the value is an empty string, it won't be quoted. """ @@ -1769,7 +1769,7 @@ class ConfigObj(Section): # Only if multiline is set, so that it is used for values not # keys, and not values that are part of a list return '' - + if multiline and isinstance(value, (list, tuple)): if not value: return ',' @@ -1785,12 +1785,12 @@ class ConfigObj(Section): if not value: return '""' - + no_lists_no_quotes = not self.list_values and '\n' not in value and '#' not in value need_triple = multiline and ((("'" in value) and ('"' in value)) or ('\n' in value )) hash_triple_quote = multiline and not need_triple and ("'" in value) and ('"' in value) and ('#' in value) check_for_single = (no_lists_no_quotes or not need_triple) and not hash_triple_quote - + if check_for_single: if not self.list_values: # we don't quote if ``list_values=False`` @@ -1808,13 +1808,13 @@ class ConfigObj(Section): else: # if value has '\n' or "'" *and* '"', it will need triple quotes quot = self._get_triple_quote(value) - + if quot == noquot and '#' in value and self.list_values: quot = self._get_single_quote(value) - + return quot % value - - + + def _get_single_quote(self, value): if ("'" in value) and ('"' in value): raise ConfigObjError('Value "%s" cannot be safely quoted.' % value) @@ -1823,15 +1823,15 @@ class ConfigObj(Section): else: quot = dquot return quot - - + + def _get_triple_quote(self, value): if (value.find('"""') != -1) and (value.find("'''") != -1): raise ConfigObjError('Value "%s" cannot be safely quoted.' % value) if value.find('"""') == -1: quot = tdquot else: - quot = tsquot + quot = tsquot return quot @@ -1921,7 +1921,7 @@ class ConfigObj(Section): def _handle_configspec(self, configspec): """Parse the configspec.""" - # FIXME: Should we check that the configspec was created with the + # FIXME: Should we check that the configspec was created with the # correct settings ? (i.e. ``list_values=False``) if not isinstance(configspec, ConfigObj): try: @@ -1935,11 +1935,11 @@ class ConfigObj(Section): raise ConfigspecError('Parsing configspec failed: %s' % e) except IOError, e: raise IOError('Reading configspec failed: %s' % e) - + self.configspec = configspec - - + + def _set_configspec(self, section, copy): """ Called by validate. Handles setting the configspec on subsections @@ -1951,7 +1951,7 @@ class ConfigObj(Section): for entry in section.sections: if entry not in configspec: section[entry].configspec = many - + for entry in configspec.sections: if entry == '__many__': continue @@ -1962,11 +1962,11 @@ class ConfigObj(Section): # copy comments section.comments[entry] = configspec.comments.get(entry, []) section.inline_comments[entry] = configspec.inline_comments.get(entry, '') - + # Could be a scalar when we expect a section if isinstance(section[entry], Section): section[entry].configspec = configspec[entry] - + def _write_line(self, indent_string, entry, this_entry, comment): """Write an individual line, for the write method""" @@ -2006,9 +2006,9 @@ class ConfigObj(Section): def write(self, outfile=None, section=None): """ Write the current ConfigObj as a file - + tekNico: FIXME: use StringIO instead of real files - + >>> filename = a.filename >>> a.filename = 'test.ini' >>> a.write() @@ -2021,7 +2021,7 @@ class ConfigObj(Section): if self.indent_type is None: # this can be true if initialised from a dictionary self.indent_type = DEFAULT_INDENT_TYPE - + out = [] cs = self._a_to_u('#') csp = self._a_to_u('# ') @@ -2035,7 +2035,7 @@ class ConfigObj(Section): if stripped_line and not stripped_line.startswith(cs): line = csp + line out.append(line) - + indent_string = self.indent_type * section.depth for entry in (section.scalars + section.sections): if entry in section.defaults: @@ -2048,7 +2048,7 @@ class ConfigObj(Section): out.append(indent_string + comment_line) this_entry = section[entry] comment = self._handle_comment(section.inline_comments[entry]) - + if isinstance(this_entry, dict): # a section out.append(self._write_marker( @@ -2063,7 +2063,7 @@ class ConfigObj(Section): entry, this_entry, comment)) - + if section is self: for line in self.final_comment: line = self._decode_element(line) @@ -2072,10 +2072,10 @@ class ConfigObj(Section): line = csp + line out.append(line) self.interpolation = int_val - + if section is not self: return out - + if (self.filename is None) and (outfile is None): # output a list of lines # might need to encode @@ -2089,7 +2089,7 @@ class ConfigObj(Section): out.append('') out[0] = BOM_UTF8 + out[0] return out - + # Turn the list to a string, joined with correct newlines newline = self.newlines or os.linesep if (getattr(outfile, 'mode', None) is not None and outfile.mode == 'w' @@ -2102,7 +2102,7 @@ class ConfigObj(Section): if self.BOM and ((self.encoding is None) or match_utf8(self.encoding)): # Add the UTF8 BOM output = BOM_UTF8 + output - + if not output.endswith(newline): output += newline if outfile is not None: @@ -2117,34 +2117,34 @@ class ConfigObj(Section): section=None): """ Test the ConfigObj against a configspec. - + It uses the ``validator`` object from *validate.py*. - + To run ``validate`` on the current ConfigObj, call: :: - + test = config.validate(validator) - + (Normally having previously passed in the configspec when the ConfigObj was created - you can dynamically assign a dictionary of checks to the ``configspec`` attribute of a section though). - + It returns ``True`` if everything passes, or a dictionary of pass/fails (True/False). If every member of a subsection passes, it will just have the value ``True``. (It also returns ``False`` if all members fail). - + In addition, it converts the values from strings to their native types if their checks pass (and ``stringify`` is set). - + If ``preserve_errors`` is ``True`` (``False`` is default) then instead of a marking a fail with a ``False``, it will preserve the actual exception object. This can contain info about the reason for failure. For example the ``VdtValueTooSmallError`` indicates that the value supplied was too small. If a value (or section) is missing it will still be marked as ``False``. - + You must have the validate module to use ``preserve_errors=True``. - + You can then use the ``flatten_errors`` function to turn your nested results dictionary into a flattened list of failures - useful for displaying meaningful error messages. @@ -2157,7 +2157,7 @@ class ConfigObj(Section): # Which makes importing configobj faster from validate import VdtMissingValue self._vdtMissingValue = VdtMissingValue - + section = self if copy: @@ -2167,23 +2167,23 @@ class ConfigObj(Section): section.BOM = section.configspec.BOM section.newlines = section.configspec.newlines section.indent_type = section.configspec.indent_type - + # # section.default_values.clear() #?? configspec = section.configspec self._set_configspec(section, copy) - + def validate_entry(entry, spec, val, missing, ret_true, ret_false): section.default_values.pop(entry, None) - + try: section.default_values[entry] = validator.get_default_value(configspec[entry]) except (KeyError, AttributeError, validator.baseErrorClass): # No default, bad default or validator has no 'get_default_value' # (e.g. SimpleVal) pass - + try: check = validator.check(spec, val, @@ -2217,16 +2217,16 @@ class ConfigObj(Section): if not copy and missing and entry not in section.defaults: section.defaults.append(entry) return ret_true, ret_false - + # out = {} ret_true = True ret_false = True - + unvalidated = [k for k in section.scalars if k not in configspec] - incorrect_sections = [k for k in configspec.sections if k in section.scalars] + incorrect_sections = [k for k in configspec.sections if k in section.scalars] incorrect_scalars = [k for k in configspec.scalars if k in section.sections] - + for entry in configspec.scalars: if entry in ('__many__', '___many___'): # reserved names @@ -2246,16 +2246,16 @@ class ConfigObj(Section): else: missing = False val = section[entry] - - ret_true, ret_false = validate_entry(entry, configspec[entry], val, + + ret_true, ret_false = validate_entry(entry, configspec[entry], val, missing, ret_true, ret_false) - + many = None if '__many__' in configspec.scalars: many = configspec['__many__'] elif '___many___' in configspec.scalars: many = configspec['___many___'] - + if many is not None: for entry in unvalidated: val = section[entry] @@ -2279,7 +2279,7 @@ class ConfigObj(Section): ret_false = False msg = 'Section %r was provided as a single value' % entry out[entry] = validator.baseErrorClass(msg) - + # Missing sections will have been created as empty ones when the # configspec was read. for entry in section.sections: @@ -2300,7 +2300,7 @@ class ConfigObj(Section): ret_false = False else: ret_true = False - + section.extra_values = unvalidated if preserve_errors and not section._created: # If the section wasn't created (i.e. it wasn't missing) @@ -2329,12 +2329,12 @@ class ConfigObj(Section): self.configspec = None # Just to be sure ;-) self._original_configspec = None - - + + def reload(self): """ Reload a ConfigObj from file. - + This method raises a ``ReloadError`` if the ConfigObj doesn't have a filename attribute pointing to a file. """ @@ -2347,31 +2347,31 @@ class ConfigObj(Section): if entry == 'configspec': continue current_options[entry] = getattr(self, entry) - + configspec = self._original_configspec current_options['configspec'] = configspec - + self.clear() self._initialise(current_options) self._load(filename, configspec) - + class SimpleVal(object): """ A simple validator. Can be used to check that all members expected are present. - + To use it, provide a configspec with all your members in (the value given will be ignored). Pass an instance of ``SimpleVal`` to the ``validate`` method of your ``ConfigObj``. ``validate`` will return ``True`` if all members are present, or a dictionary with True/False meaning present/missing. (Whole missing sections will be replaced with ``False``) """ - + def __init__(self): self.baseErrorClass = ConfigObjError - + def check(self, check, member, missing=False): """A dummy check method, always returns the value unchanged.""" if missing: @@ -2383,32 +2383,32 @@ def flatten_errors(cfg, res, levels=None, results=None): """ An example function that will turn a nested dictionary of results (as returned by ``ConfigObj.validate``) into a flat list. - + ``cfg`` is the ConfigObj instance being checked, ``res`` is the results dictionary returned by ``validate``. - + (This is a recursive function, so you shouldn't use the ``levels`` or ``results`` arguments - they are used by the function.) - + Returns a list of keys that failed. Each member of the list is a tuple:: - + ([list of sections...], key, result) - + If ``validate`` was called with ``preserve_errors=False`` (the default) then ``result`` will always be ``False``. *list of sections* is a flattened list of sections that the key was found in. - + If the section was missing (or a section was expected and a scalar provided - or vice-versa) then key will be ``None``. - + If the value (or section) was missing then ``result`` will be ``False``. - + If ``validate`` was called with ``preserve_errors=True`` and a value was present, but failed the check, then ``result`` will be the exception object returned. You can use this as a string that describes the failure. - + For example *The value "3" is of the wrong type*. """ if levels is None: @@ -2443,21 +2443,21 @@ def get_extra_values(conf, _prepend=()): """ Find all the values and sections not in the configspec from a validated ConfigObj. - + ``get_extra_values`` returns a list of tuples where each tuple represents either an extra section, or an extra value. - - The tuples contain two values, a tuple representing the section the value + + The tuples contain two values, a tuple representing the section the value is in and the name of the extra values. For extra values in the top level section the first member will be an empty tuple. For values in the 'foo' section the first member will be ``('foo',)``. For members in the 'bar' subsection of the 'foo' section the first member will be ``('foo', 'bar')``. - + NOTE: If you call ``get_extra_values`` on a ConfigObj instance that hasn't been validated it will return an empty list. """ out = [] - + out.extend([(_prepend, name) for name in conf.extra_values]) for name in conf.sections: if name not in conf.extra_values: diff --git a/sabnzbd/utils/feedparser.py b/sabnzbd/utils/feedparser.py index c78e6a3..1341509 100644 --- a/sabnzbd/utils/feedparser.py +++ b/sabnzbd/utils/feedparser.py @@ -3485,7 +3485,7 @@ def _parse_date_group_rfc822(m): # If the year is 2 digits, assume everything in the 90's is the 1990's if m['year'] < 100: m['year'] += (1900, 2000)[m['year'] < 90] - stamp = datetime.datetime(*[m[i] for i in + stamp = datetime.datetime(*[m[i] for i in ('year', 'month', 'day', 'hour', 'minute', 'second')]) # Use the timezone information to calculate the difference between @@ -3524,7 +3524,7 @@ def _parse_date_rfc822(dt): registerDateHandler(_parse_date_rfc822) def _parse_date_rfc822_grubby(dt): - """Parse date format similar to RFC 822, but + """Parse date format similar to RFC 822, but the comma after the dayname is optional and month/day are inverted""" _rfc822_date_grubby = "%s %s %s" % (_rfc822_month, _rfc822_day, _rfc822_year) @@ -3725,7 +3725,7 @@ def convert_to_utf8(http_headers, data): u'application/xml-external-parsed-entity') text_content_types = (u'text/xml', u'text/xml-external-parsed-entity') if (http_content_type in application_content_types) or \ - (http_content_type.startswith(u'application/') and + (http_content_type.startswith(u'application/') and http_content_type.endswith(u'+xml')): acceptable_content_type = 1 rfc3023_encoding = http_encoding or xml_encoding or u'utf-8' diff --git a/sabnzbd/utils/pybonjour.py b/sabnzbd/utils/pybonjour.py index 32d7aa1..a17287c 100644 --- a/sabnzbd/utils/pybonjour.py +++ b/sabnzbd/utils/pybonjour.py @@ -1813,7 +1813,7 @@ def DNSServiceReconfirmRecord( flags: Currently unused, reserved for future use. - interfaceIndex: + interfaceIndex: If non-zero, specifies the interface of the record in question. Passing kDNSServiceInterfaceIndexAny (0) causes all instances of this record to be reconfirmed. @@ -1855,7 +1855,7 @@ def DNSServiceReconfirmRecord( def DNSServiceConstructFullName( service = None, - regtype = _NO_DEFAULT, + regtype = _NO_DEFAULT, domain = _NO_DEFAULT, ): diff --git a/sabnzbd/utils/rsslib.py b/sabnzbd/utils/rsslib.py index 19e5629..8b07de8 100644 --- a/sabnzbd/utils/rsslib.py +++ b/sabnzbd/utils/rsslib.py @@ -37,15 +37,15 @@ def _xmlcharref_encode(unicode_data, encoding): class RSS: -# """ +# """ # RSS -# +# # This class encapsulates the creation of an RSS 2.0 feed -# -# The RSS2.0 spec can be found here: +# +# The RSS2.0 spec can be found here: # http://blogs.law.harvard.edu/tech/rss -# -# +# +# # RSS validator : http://rss.scripting.com # # @@ -56,26 +56,26 @@ class RSS: # rss.channel.link = "http://channel.com" # rss.channel.title = "my channel title" # rss.channel.description = "my channel description" -# +# # ns = Namespace( "foobar", "http://foobar.baz" ) # rss.channel.namespaces.append( ns ) -# +# # item = Item() # item.link = "http://link.com" # item.description = "my link description" # item.title ="my item title" # item.nsItems[ns.name + ":foo"] = "bar" # rss.channel.items.append( item ) -# +# # item = Item() # item.link = "http://link2.com" # item.description = "my link2 description" # item.title ="my item2 title" # item.nsItems[ns.name +":foo"] = "foo bar baz" # rss.channel.items.append( item ) -# +# # print rss.write() -# +# # output: # # @@ -83,76 +83,76 @@ class RSS: # my channel title # http://channel.com # my channel description -# +# # my item title # http://link.com # my link description # bar # -# +# # my item2 title # http://link2.com # my link2 description # foo bar baz # -# +# # # -# +# # author: cmallory /a t/ berserk /dot/ o r g -# """ +# """ def __init__(self): self.channel = Channel() self.version = "2.0" self.contents = None - + # if __name__ == "__main__" : # from rsslib import RSS, Item, Namespace # rss = RSS() # rss.channel.link = "http://channel.com" # rss.channel.title = "my channel title" # rss.channel.description = "my channel description" -# +# # ns = Namespace( "foobar", "http://foobar.baz" ) # rss.addNamespace( ns ) -# +# # item = Item() # item.link = "http://link.com" # item.description = "my link description" # item.title ="my item title" -# +# # item.enclosure.url = "http://enclosure.url.com" # item.enclosure.length = 12345 # item.enclosure.type = "audio/mpeg" -# +# # item.nsItems[ns.name + ":foo"] = "bar" # rss.addItem( item ) -# +# # item = Item() # item.link = "http://link2.com" # item.description = "my link2 description" # item.title ="my item2 title" # item.nsItems[ns.name +":foo"] = "foo bar baz" # rss.addItem( item ) -# +# # print rss.write() - + #Write out the rss document def write( self ): - + self.contents = "\n" #contents += "\n" - + self.contents += " element def generateChannel( self ): contents = "" @@ -161,7 +161,7 @@ class RSS: contents += self.optionalWrite("title", self.channel.title ); contents += self.optionalWrite("link", self.channel.link ); contents += self.optionalWrite("description", self.channel.description ); - + contents += self.optionalWrite("language", self.channel.language ); contents += self.optionalWrite("copyright", self.channel.copyright ); contents += self.optionalWrite("category", self.channel.category ); @@ -172,18 +172,18 @@ class RSS: contents += self.optionalWrite("docs", self.channel.docs ); contents += self.optionalWrite("cloud", self.channel.cloud ); contents += self.optionalWrite("ttl", self.channel.ttl ); - contents += self.optionalWrite("generator", self.channel.generator ); + contents += self.optionalWrite("generator", self.channel.generator ); contents += self.optionalWrite("image", self.channel.image ); contents += self.optionalWrite("rating", self.channel.rating ); contents += self.optionalWrite("textInput", self.channel.textInput ); contents += self.optionalWrite("skipHours", self.channel.skipHours ); contents += self.optionalWrite("skipDays", self.channel.skipDays ); - + contents += "\n" + self.generateItems() + "\n" else : contents = "[Channel not properly initialized. " contents +="A required field is not set.(title/link/description]" - + return contents #Generates all items within a channel @@ -202,17 +202,17 @@ class RSS: c += self.optionalWrite("comments", i.comments ) c += self.optionalWrite("guid", i.guid ) c += self.optionalWrite("source", i.source ) - + if ( i.enclosure.url != "" ): c+= "\n" - + for k in i.nsItems.keys(): c += self.optionalWrite( k , i.nsItems[ k ] ) - + c += "\n\n" - + return c @@ -223,8 +223,8 @@ class RSS: def addItem( self, item ): if ( self.channel is not None): self.channel.items.append( item ) - - + + def optionalWrite( self, key, val ): if ( val is not None and val != "" ): return "<" + key + ">" + encode_for_xml(xml.sax.saxutils.escape(val)) + "\n" @@ -238,13 +238,13 @@ class Namespace: self.url = url self.name = name - + class Channel: # """ # Channel -# +# # (http://blogs.law.harvard.edu/tech/rss) -# +# # This object represents an RSS channel (as of ver2.0) # """ @@ -274,26 +274,26 @@ class Channel: self.textInput = "" self.skipHours = "" self.skipDays = "" - + self.items = [] self.namespaces = [] def initialized( self ): return self.title is not None and self.link is not None and self.description is not None - + class Item: # """ # Item -# +# # http://blogs.law.harvard.edu/tech/rss#hrelementsOfLtitemgt -# -# A channel may contain any number of <item>s. An item may -# represent a "story" -- much like a story in a newspaper or magazine; -# if so its description is a synopsis of the story, and the link -# points to the full story. An item may also be complete in itself, -# if so, the description contains the text (entity-encoded HTML is -# allowed; see examples), and the link and title may be omitted. -# All elements of an item are optional, however at least one of +# +# A channel may contain any number of <item>s. An item may +# represent a "story" -- much like a story in a newspaper or magazine; +# if so its description is a synopsis of the story, and the link +# points to the full story. An item may also be complete in itself, +# if so, the description contains the text (entity-encoded HTML is +# allowed; see examples), and the link and title may be omitted. +# All elements of an item are optional, however at least one of # title or description must be present. # """ def __init__( self ): @@ -309,32 +309,32 @@ class Item: self.pubDate = "" self.source = "" self.enclosure = Enclosure() - + self.nsItems = {} - - + + class Enclosure: # """ # Enclosure -# -# sub-element of +# +# sub-element of # # is an optional sub-element of . # # It has three required attributes: -# -# url: says where the enclosure is located, -# length: says how big it is in bytes, and +# +# url: says where the enclosure is located, +# length: says how big it is in bytes, and # type: says what its type is, a standard MIME type. # # The url must be an http url. # # Example: -# +# # """ def __init__(self): self.url = "" self.length = 0 self.type = "" - + diff --git a/sabnzbd/utils/ssmtplib.py b/sabnzbd/utils/ssmtplib.py index fc17bba..f59c6dd 100644 --- a/sabnzbd/utils/ssmtplib.py +++ b/sabnzbd/utils/ssmtplib.py @@ -12,22 +12,22 @@ Public errors: SMTPSSLException # # Copyright (c) 2007 M Butcher # -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # -# The above copyright notice and this permission notice shall be included in +# The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. ## ##End License @@ -43,7 +43,7 @@ SSMTP_PORT = 465 class SMTPSSLException(smtplib.SMTPException): """Base class for exceptions resulting from SSL negotiation.""" - + class SMTP_SSL (smtplib.SMTP): """This class provides SSL access to an SMTP server. SMTP over SSL typical listens on port 465. Unlike StartTLS, SMTP over SSL @@ -52,7 +52,7 @@ class SMTP_SSL (smtplib.SMTP): This class is a simple subclass of the smtplib.SMTP class that comes with Python. It overrides the connect() method to use an SSL socket, and it - overrides the starttles() function to throw an error (you can't do + overrides the starttles() function to throw an error (you can't do starttls within an SSL session). """ certfile = None @@ -66,7 +66,7 @@ class SMTP_SSL (smtplib.SMTP): which this object will connect. `local_hostname' is the name of the localhost. By default, the value of socket.getfqdn() is used. - An SMTPConnectError is raised if the SMTP host does not respond + An SMTPConnectError is raised if the SMTP host does not respond correctly. An SMTPSSLError is raised if SSL negotiation fails. @@ -84,16 +84,16 @@ class SMTP_SSL (smtplib.SMTP): `host' is localhost by default. Port will be set to 465 (the default SSL SMTP port) if no port is specified. - If the host name ends with a colon (`:') followed by a number, + If the host name ends with a colon (`:') followed by a number, that suffix will be stripped off and the - number interpreted as the port number to use. This will override the + number interpreted as the port number to use. This will override the `port' parameter. Note: This method is automatically invoked by __init__, if a host is specified during instantiation. """ - # MB: Most of this (Except for the socket connection code) is from - # the SMTP.connect() method. I changed only the bare minimum for the + # MB: Most of this (Except for the socket connection code) is from + # the SMTP.connect() method. I changed only the bare minimum for the # sake of compatibility. if not port and (host.find(':') == host.rfind(':')): i = host.rfind(':') @@ -115,7 +115,7 @@ class SMTP_SSL (smtplib.SMTP): # MB: Make the SSL connection. sslobj = socket.ssl(self.sock, self.keyfile, self.certfile) except socket.error, msg: - if self.debuglevel > 0: + if self.debuglevel > 0: print>>stderr, 'connect fail:', (host, port) if self.sock: self.sock.close() @@ -152,7 +152,7 @@ class SMTP_SSL (smtplib.SMTP): self.certfile = certfile def starttls(self, keyfile = None, certfile = None): - """Raises an exception. + """Raises an exception. You cannot do StartTLS inside of an ssl session. Calling starttls() will return an SMTPSSLException""" raise SMTPSSLException, "Cannot perform StartTLS within SSL session." diff --git a/sabnzbd/utils/systrayiconthread.py b/sabnzbd/utils/systrayiconthread.py index e248dd2..a16fe25 100644 --- a/sabnzbd/utils/systrayiconthread.py +++ b/sabnzbd/utils/systrayiconthread.py @@ -94,19 +94,19 @@ class SysTrayIconThread(Thread): # override this def doUpdates(self): pass - + # Notification def sendnotification(self, title, msg): hicon = self.get_icon(self.icon) win32gui.Shell_NotifyIcon(win32gui.NIM_MODIFY, - (self.hwnd, - 0, + (self.hwnd, + 0, win32gui.NIF_INFO, - win32con.WM_USER+20, + win32con.WM_USER+20, hicon, - "Balloon tooltip", - msg, - 200, + "Balloon tooltip", + msg, + 200, title)) def _add_ids_to_menu_options(self, menu_options):