From b8c928c2ec66553d70ca0483732ca52dfe8790af Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 7 Feb 2017 17:59:22 +0000 Subject: [PATCH 01/16] Autogenerate a pylint configuration file. --- pylintrc | 410 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 410 insertions(+) create mode 100644 pylintrc diff --git a/pylintrc b/pylintrc new file mode 100644 index 000000000..eb29a2c3d --- /dev/null +++ b/pylintrc @@ -0,0 +1,410 @@ +[MASTER] + +# A comma-separated list of package or module names from where C extensions may +# be loaded. Extensions are loading into the active Python interpreter and may +# run arbitrary code +extension-pkg-whitelist= + +# Add files or directories to the blacklist. They should be base names, not +# paths. +ignore=CVS + +# Add files or directories matching the regex patterns to the blacklist. The +# regex matches against base names, not paths. +ignore-patterns= + +# Python code to execute, usually for sys.path manipulation such as +# pygtk.require(). +#init-hook= + +# Use multiple processes to speed up Pylint. +jobs=1 + +# List of plugins (as comma separated values of python modules names) to load, +# usually to register additional checkers. +load-plugins= + +# Pickle collected data for later comparisons. +persistent=yes + +# Specify a configuration file. +#rcfile= + +# Allow loading of arbitrary C extensions. Extensions are imported into the +# active Python interpreter and may run arbitrary code. +unsafe-load-any-extension=no + + +[MESSAGES CONTROL] + +# Only show warnings with the listed confidence levels. Leave empty to show +# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED +confidence= + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifiers separated by comma (,) or put this +# option multiple times (only on the command line, not in the configuration +# file where it should appear only once).You can also use "--disable=all" to +# disable everything first and then reenable specific checks. For example, if +# you want to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use"--disable=all --enable=classes +# --disable=W" +disable=print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time (only on the command line, not in the configuration file where +# it should appear only once). See also the "--disable" option for examples. +enable= + + +[REPORTS] + +# Python expression which should return a note less than 10 (10 is the highest +# note). You have access to the variables errors warning, statement which +# respectively contain the number of errors / warnings messages and the total +# number of statements analyzed. This is used by the global evaluation report +# (RP0004). +evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) + +# Template used to display messages. This is a python new-style format string +# used to format the message information. See doc for all details +#msg-template= + +# Set the output format. Available formats are text, parseable, colorized, json +# and msvs (visual studio).You can also give a reporter class, eg +# mypackage.mymodule.MyReporterClass. +output-format=text + +# Tells whether to display a full report or only the messages +reports=no + +# Activate the evaluation score. +score=yes + + +[REFACTORING] + +# Maximum number of nested blocks for function / method body +max-nested-blocks=5 + + +[VARIABLES] + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid to define new builtins when possible. +additional-builtins= + +# Tells whether unused global variables should be treated as a violation. +allow-global-unused-variables=yes + +# List of strings which can identify a callback function by name. A callback +# name must start or end with one of those strings. +callbacks=cb_,_cb + +# A regular expression matching the name of dummy variables (i.e. expectedly +# not used). +dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy + +# Argument names that match this expression will be ignored. Default to name +# with leading underscore +ignored-argument-names=_.* + +# Tells whether we should check for unused import in __init__ files. +init-import=no + +# List of qualified module names which can have objects that can redefine +# builtins. +redefining-builtins-modules=six.moves,future.builtins + + +[TYPECHECK] + +# List of decorators that produce context managers, such as +# contextlib.contextmanager. Add to this list to register other decorators that +# produce valid context managers. +contextmanager-decorators=contextlib.contextmanager + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E1101 when accessed. Python regular +# expressions are accepted. +generated-members= + +# Tells whether missing members accessed in mixin class should be ignored. A +# mixin class is detected if its name ends with "mixin" (case insensitive). +ignore-mixin-members=yes + +# List of class names for which member attributes should not be checked (useful +# for classes with dynamically set attributes). This supports the use of +# qualified names. +ignored-classes=optparse.Values,thread._local,_thread._local + +# List of module names for which member attributes should not be checked +# (useful for modules/projects where namespaces are manipulated during runtime +# and thus existing member attributes cannot be deduced by static analysis. It +# supports qualified module names, as well as Unix pattern matching. +ignored-modules= + +# Show a hint with possible names when a member name was not found. The aspect +# of finding the hint is based on edit distance. +missing-member-hint=yes + +# The minimum edit distance a name should have in order to be considered a +# similar match for a missing member name. +missing-member-hint-distance=1 + +# The total number of similar names that should be taken in consideration when +# showing a hint for a missing member. +missing-member-max-choices=1 + + +[SPELLING] + +# Spelling dictionary name. Available dictionaries: none. To make it working +# install python-enchant package. +spelling-dict= + +# List of comma separated words that should not be checked. +spelling-ignore-words= + +# A path to a file that contains private dictionary; one word per line. +spelling-private-dict-file= + +# Tells whether to store unknown words to indicated private dictionary in +# --spelling-private-dict-file option instead of raising a message. +spelling-store-unknown-words=no + + +[SIMILARITIES] + +# Ignore comments when computing similarities. +ignore-comments=yes + +# Ignore docstrings when computing similarities. +ignore-docstrings=yes + +# Ignore imports when computing similarities. +ignore-imports=no + +# Minimum lines number of a similarity. +min-similarity-lines=4 + + +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +notes=FIXME,XXX,TODO + + +[LOGGING] + +# Logging modules to check that the string format arguments are in logging +# function parameter format +logging-modules=logging + + +[FORMAT] + +# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. +expected-line-ending-format= + +# Regexp for a line that is allowed to be longer than the limit. +ignore-long-lines=^\s*(# )??$ + +# Number of spaces of indent required inside a hanging or continued line. +indent-after-paren=4 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 +# tab). +indent-string=' ' + +# Maximum number of characters on a single line. +max-line-length=100 + +# Maximum number of lines in a module +max-module-lines=1000 + +# List of optional constructs for which whitespace checking is disabled. `dict- +# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}. +# `trailing-comma` allows a space between comma and closing bracket: (a, ). +# `empty-line` allows space-only lines. +no-space-check=trailing-comma,dict-separator + +# Allow the body of an if to be on the same line as the test if there is no +# else. +single-line-if-stmt=no + + +[BASIC] + +# Naming hint for argument names +argument-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ + +# Regular expression matching correct argument names +argument-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ + +# Naming hint for attribute names +attr-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ + +# Regular expression matching correct attribute names +attr-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ + +# Bad variable names which should always be refused, separated by a comma +bad-names=foo,bar,baz,toto,tutu,tata + +# Naming hint for class attribute names +class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ + +# Regular expression matching correct class attribute names +class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ + +# Naming hint for class names +class-name-hint=[A-Z_][a-zA-Z0-9]+$ + +# Regular expression matching correct class names +class-rgx=[A-Z_][a-zA-Z0-9]+$ + +# Naming hint for constant names +const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$ + +# Regular expression matching correct constant names +const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ + +# Minimum line length for functions/classes that require docstrings, shorter +# ones are exempt. +docstring-min-length=-1 + +# Naming hint for function names +function-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ + +# Regular expression matching correct function names +function-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ + +# Good variable names which should always be accepted, separated by a comma +good-names=i,j,k,ex,Run,_ + +# Include a hint for the correct naming format with invalid-name +include-naming-hint=no + +# Naming hint for inline iteration names +inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$ + +# Regular expression matching correct inline iteration names +inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ + +# Naming hint for method names +method-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ + +# Regular expression matching correct method names +method-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ + +# Naming hint for module names +module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Regular expression matching correct module names +module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Colon-delimited sets of names that determine each other's naming style when +# the name regexes allow several styles. +name-group= + +# Regular expression which should only match function or class names that do +# not require a docstring. +no-docstring-rgx=^_ + +# List of decorators that produce properties, such as abc.abstractproperty. Add +# to this list to register other decorators that produce valid properties. +property-classes=abc.abstractproperty + +# Naming hint for variable names +variable-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ + +# Regular expression matching correct variable names +variable-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ + + +[IMPORTS] + +# Analyse import fallback blocks. This can be used to support both Python 2 and +# 3 compatible code, which means that the block might have code that exists +# only in one or another interpreter, leading to false positives when analysed. +analyse-fallback-blocks=no + +# Deprecated modules which should not be used, separated by a comma +deprecated-modules=optparse,tkinter.tix + +# Create a graph of external dependencies in the given file (report RP0402 must +# not be disabled) +ext-import-graph= + +# Create a graph of every (i.e. internal and external) dependencies in the +# given file (report RP0402 must not be disabled) +import-graph= + +# Create a graph of internal dependencies in the given file (report RP0402 must +# not be disabled) +int-import-graph= + +# Force import order to recognize a module as part of the standard +# compatibility libraries. +known-standard-library= + +# Force import order to recognize a module as part of a third party library. +known-third-party=enchant + + +[DESIGN] + +# Maximum number of arguments for function / method +max-args=5 + +# Maximum number of attributes for a class (see R0902). +max-attributes=7 + +# Maximum number of boolean expressions in a if statement +max-bool-expr=5 + +# Maximum number of branch for function / method body +max-branches=12 + +# Maximum number of locals for function / method body +max-locals=15 + +# Maximum number of parents for a class (see R0901). +max-parents=7 + +# Maximum number of public methods for a class (see R0904). +max-public-methods=20 + +# Maximum number of return / yield for function / method body +max-returns=6 + +# Maximum number of statements in function / method body +max-statements=50 + +# Minimum number of public methods for a class (see R0903). +min-public-methods=2 + + +[CLASSES] + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__,__new__,setUp + +# List of member names, which should be excluded from the protected access +# warning. +exclude-protected=_asdict,_fields,_replace,_source,_make + +# List of valid names for the first argument in a class method. +valid-classmethod-first-arg=cls + +# List of valid names for the first argument in a metaclass class method. +valid-metaclass-classmethod-first-arg=mcs + + +[EXCEPTIONS] + +# Exceptions that will emit a warning when being caught. Defaults to +# "Exception" +overgeneral-exceptions=Exception From e2901f09f6d74c2131e9a1852a838c15ba0d72cf Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 7 Feb 2017 20:41:08 +0000 Subject: [PATCH 02/16] pylint: Tweak the configuration file a bit. --- pylintrc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pylintrc b/pylintrc index eb29a2c3d..9d0b37e30 100644 --- a/pylintrc +++ b/pylintrc @@ -50,7 +50,7 @@ confidence= # --enable=similarities". If you want to run only the classes checker, but have # no Warning level messages displayed, use"--disable=all --enable=classes # --disable=W" -disable=print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call +disable=print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call,missing-docstring,not-callable # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option @@ -94,7 +94,7 @@ max-nested-blocks=5 # List of additional names supposed to be defined in builtins. Remember that # you should avoid to define new builtins when possible. -additional-builtins= +additional-builtins=_ # Tells whether unused global variables should be treated as a violation. allow-global-unused-variables=yes From 51eb62bb73e14c9e2a46099e63a19af566381e96 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 7 Feb 2017 19:32:28 +0000 Subject: [PATCH 03/16] Replace some wildcard imports with explicit ones. --- src/command_system/implementation/custom.py | 2 +- src/command_system/implementation/execute.py | 2 +- src/command_system/implementation/standard.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/command_system/implementation/custom.py b/src/command_system/implementation/custom.py index 3fa00d083..38cd2e2c3 100644 --- a/src/command_system/implementation/custom.py +++ b/src/command_system/implementation/custom.py @@ -35,7 +35,7 @@ detected. """ from ..framework import CommandContainer, command, doc -from .hosts import * +from .hosts import ChatCommands, PrivateChatCommands, GroupChatCommands class CustomCommonCommands(CommandContainer): """ diff --git a/src/command_system/implementation/execute.py b/src/command_system/implementation/execute.py index ab14f4ea1..767e761a5 100644 --- a/src/command_system/implementation/execute.py +++ b/src/command_system/implementation/execute.py @@ -38,7 +38,7 @@ from os.path import expanduser from gi.repository import GLib from ..framework import CommandContainer, command, doc -from .hosts import * +from .hosts import ChatCommands, PrivateChatCommands, GroupChatCommands class Execute(CommandContainer): AUTOMATIC = True diff --git a/src/command_system/implementation/standard.py b/src/command_system/implementation/standard.py index 8cdfa3516..bd263b669 100644 --- a/src/command_system/implementation/standard.py +++ b/src/command_system/implementation/standard.py @@ -30,7 +30,7 @@ from ..errors import CommandError from ..framework import CommandContainer, command, doc from ..mapping import generate_usage -from .hosts import * +from .hosts import ChatCommands, PrivateChatCommands, GroupChatCommands from . import execute # This holds constants fron the logger, which we'll be using in some of our From 07716daec2de3408a9844e0bd843179345a69eb1 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 7 Feb 2017 19:32:56 +0000 Subject: [PATCH 04/16] Use staticmethod decorator where it makes sense. --- src/advanced_configuration_window.py | 6 +- src/gui_interface.py | 82 ++++++++++++++++++---------- 2 files changed, 58 insertions(+), 30 deletions(-) diff --git a/src/advanced_configuration_window.py b/src/advanced_configuration_window.py index 1e95bb1fe..6faba9ec2 100644 --- a/src/advanced_configuration_window.py +++ b/src/advanced_configuration_window.py @@ -150,7 +150,8 @@ class AdvancedConfigurationWindow(object): else: cell.set_property('editable', True) - def get_option_path(self, model, iter_): + @staticmethod + def get_option_path(model, iter_): # It looks like path made from reversed array # path[0] is the true one optname # path[1] is the key name @@ -255,7 +256,8 @@ class AdvancedConfigurationWindow(object): modelrow[1] = text self.check_for_restart() - def on_advanced_configuration_window_destroy(self, widget): + @staticmethod + def on_advanced_configuration_window_destroy(widget): del gajim.interface.instances['advanced_config'] def on_reset_button_clicked(self, widget): diff --git a/src/gui_interface.py b/src/gui_interface.py index a50a82ba3..e2806328c 100644 --- a/src/gui_interface.py +++ b/src/gui_interface.py @@ -120,7 +120,8 @@ class Interface: self.db_error_dialog = None self.db_error_dialog.connect('destroy', destroyed) - def handle_event_information(self, obj): + @staticmethod + def handle_event_information(obj): if obj.popup: if obj.level == 'error': cls = dialogs.ErrorDialog @@ -147,7 +148,8 @@ class Interface: self.instances['change_nick_dialog'] = dialogs.ChangeNickDialog( account, room_jid, title, prompt, transient_for=parent_win) - def handle_event_http_auth(self, obj): + @staticmethod + def handle_event_http_auth(obj): #('HTTP_AUTH', account, (method, url, transaction_id, iq_obj, msg)) def response(account, answer): obj.conn.build_http_auth_answer(obj.stanza, answer) @@ -200,14 +202,16 @@ class Interface: if ctrl and ctrl.type_id == message_control.TYPE_GC: ctrl.print_conversation('Error %s: %s' % (obj.errcode, obj.errmsg)) - def handle_event_connection_lost(self, obj): + @staticmethod + def handle_event_connection_lost(obj): # ('CONNECTION_LOST', account, [title, text]) path = gtkgui_helpers.get_icon_path('gajim-connection_lost', 48) account = obj.conn.name notify.popup(_('Connection Failed'), account, account, '', path, obj.title, obj.msg) - def unblock_signed_in_notifications(self, account): + @staticmethod + def unblock_signed_in_notifications(account): gajim.block_signed_in_notifications[account] = False def handle_event_status(self, obj): # OUR status @@ -247,7 +251,8 @@ class Interface: profile_window.ProfileWindow(account, gajim.interface.roster.window) gajim.connections[account].request_vcard(jid) - def handle_gc_error(self, gc_control, pritext, sectext): + @staticmethod + def handle_gc_error(gc_control, pritext, sectext): if gc_control and gc_control.autorejoin is not None: if gc_control.error_dialog: gc_control.error_dialog.destroy() @@ -339,7 +344,8 @@ class Interface: if gc_control and gc_control.autorejoin: gc_control.autorejoin = False - def handle_event_gc_message(self, obj): + @staticmethod + def handle_event_gc_message(obj): if not obj.stanza.getTag('body'): # no # It could be a voice request. See # http://www.xmpp.org/extensions/xep-0045.html#voiceapprove @@ -443,14 +449,16 @@ class Interface: if session: session.roster_message(jid, msg, obj.time_, msg_type='error') - def handle_event_msgsent(self, obj): + @staticmethod + def handle_event_msgsent(obj): #('MSGSENT', account, (jid, msg, keyID)) # do not play sound when standalone chatstate message (eg no msg) if obj.message and gajim.config.get_per('soundevents', 'message_sent', 'enabled'): helpers.play_sound('message_sent') - def handle_event_msgnotsent(self, obj): + @staticmethod + def handle_event_msgnotsent(obj): #('MSGNOTSENT', account, (jid, ierror_msg, msg, time, session)) msg = _('error while sending %(message)s ( %(error)s )') % { 'message': obj.message, 'error': obj.error} @@ -540,7 +548,8 @@ class Interface: notify.popup(event_type, obj.jid, account, 'unsubscribed', path, event_type, obj.jid) - def handle_event_register_agent_info(self, obj): + @staticmethod + def handle_event_register_agent_info(obj): # ('REGISTER_AGENT_INFO', account, (agent, infos, is_form)) # info in a dataform if is_form is True if obj.is_form or 'instructions' in obj.config: @@ -688,7 +697,8 @@ class Interface: _('You are currently connected without your OpenPGP key.')) self.forget_gpg_passphrase(obj.keyID) - def handle_event_client_cert_passphrase(self, obj): + @staticmethod + def handle_event_client_cert_passphrase(obj): def on_ok(passphrase, checked): obj.conn.on_client_cert_passphrase(passphrase, obj.con, obj.port, obj.secure_tuple) @@ -710,7 +720,8 @@ class Interface: self.gpg_passphrase[obj.keyid] = request request.add_callback(obj.conn.name, obj.callback) - def handle_event_gpg_trust_key(self, obj): + @staticmethod + def handle_event_gpg_trust_key(obj): #('GPG_ALWAYS_TRUST', account, callback) def on_yes(checked): if checked: @@ -861,7 +872,8 @@ class Interface: notify.popup(event_type, jid, account, 'file-send-error', path, event_type, file_props.name) - def handle_event_gmail_notify(self, obj): + @staticmethod + def handle_event_gmail_notify(obj): jid = obj.jid gmail_new_messages = int(obj.newmsgs) gmail_messages_list = obj.gmail_messages_list @@ -963,7 +975,8 @@ class Interface: notify.popup(event_type, obj.jid, account, 'file-request', path_to_image=path, title=event_type, text=txt) - def handle_event_file_error(self, title, message): + @staticmethod + def handle_event_file_error(title, message): dialogs.ErrorDialog(title, message) def handle_event_file_progress(self, account, file_props): @@ -1129,7 +1142,8 @@ class Interface: notify.popup(event_type, jid, account, msg_type, path_to_image=path, title=event_type, text=txt) - def ask_offline_status(self, account): + @staticmethod + def ask_offline_status(account): for contact in gajim.contacts.iter_contacts(account): gajim.connections[account].request_last_status_time(contact.jid, contact.resource) @@ -1187,13 +1201,16 @@ class Interface: location_listener.enable() - def handle_event_metacontacts(self, obj): + @staticmethod + def handle_event_metacontacts(obj): gajim.contacts.define_metacontacts(obj.conn.name, obj.meta_list) - def handle_atom_entry(self, obj): + @staticmethod + def handle_atom_entry(obj): AtomWindow.newAtomEntry(obj.atom_entry) - def handle_event_failed_decrypt(self, obj): + @staticmethod + def handle_event_failed_decrypt(obj): details = _('Unable to decrypt message from %s\nIt may have been ' 'tampered with.') % obj.fjid dialogs.WarningDialog(_('Unable to decrypt message'), details) @@ -1328,7 +1345,8 @@ class Interface: if ctrl: ctrl.set_audio_state('error', reason=obj.reason) - def handle_event_roster_item_exchange(self, obj): + @staticmethod + def handle_event_roster_item_exchange(obj): # data = (action in [add, delete, modify], exchange_list, jid_from) dialogs.RosterItemExchangeWindow(obj.conn.name, obj.action, obj.exchange_items_list, obj.fjid) @@ -1821,7 +1839,8 @@ class Interface: ### Methods dealing with emoticons ################################################################################ - def image_is_ok(self, image): + @staticmethod + def image_is_ok(image): if not os.path.exists(image): return False img = Gtk.Image() @@ -2317,7 +2336,8 @@ class Interface: ### Other Methods ################################################################################ - def change_awn_icon_status(self, status): + @staticmethod + def change_awn_icon_status(status): if not dbus_support.supported: # do nothing if user doesn't have D-Bus bindings return @@ -2356,8 +2376,8 @@ class Interface: listener.disconnect(self.music_track_changed_signal) self.music_track_changed_signal = None - def music_track_changed(self, unused_listener, music_track_info, - account=None): + @staticmethod + def music_track_changed(unused_listener, music_track_info, account=None): if not account: accounts = gajim.connections.keys() else: @@ -2478,7 +2498,8 @@ class Interface: self.systray_enabled = False self.systray.hide_icon() - def on_launch_browser_mailer(self, widget, url, kind): + @staticmethod + def on_launch_browser_mailer(widget, url, kind): helpers.launch_browser_mailer(kind, url) def process_connections(self): @@ -2497,7 +2518,8 @@ class Interface: raise return True # renew timeout (loop for ever) - def save_config(self): + @staticmethod + def save_config(): err_str = parser.write() if err_str is not None: print(err_str, file=sys.stderr) @@ -2507,7 +2529,8 @@ class Interface: 'preferences'), err_str) sys.exit() - def save_avatar_files(self, jid, photo, puny_nick = None, local = False): + @staticmethod + def save_avatar_files(jid, photo, puny_nick = None, local = False): """ Save an avatar to a separate file, and generate files for dbus notifications. An avatar can be given as a pixmap directly or as an @@ -2567,7 +2590,8 @@ class Interface: log.error('Error writing avatar file %s: %s' % \ (path_to_original_file, str(e))) - def remove_avatar_files(self, jid, puny_nick = None, local = False): + @staticmethod + def remove_avatar_files(jid, puny_nick = None, local = False): """ Remove avatar files of a jid """ @@ -2657,7 +2681,8 @@ class Interface: return gc_ctrl and gc_ctrl.type_id == message_control.TYPE_GC - def get_pep_icon(self, pep_obj): + @staticmethod + def get_pep_icon(pep_obj): if isinstance(pep_obj, pep.UserMoodPEP): received_mood = pep_obj._pep_specific_data['mood'] mood = received_mood if received_mood in pep.MOODS else 'unknown' @@ -2688,7 +2713,8 @@ class Interface: quiet=True) return icon - def create_ipython_window(self): + @staticmethod + def create_ipython_window(): try: from ipython_view import IPythonView except ImportError: From 289d82fae7af91f459335623aede5bb57c8994cf Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 7 Feb 2017 19:56:26 +0000 Subject: [PATCH 05/16] Remove unused imports. --- src/advanced_configuration_window.py | 1 - src/atom_window.py | 1 - src/command_system/framework.py | 1 - src/command_system/implementation/standard.py | 1 - src/command_system/tools.py | 4 +--- src/common/connection_handlers.py | 14 ++++---------- src/common/connection_handlers_events.py | 2 +- src/common/gajim.py | 1 - src/common/helpers.py | 1 - src/common/jingle_content.py | 1 - src/common/jingle_ft.py | 1 - src/common/jingle_transport.py | 1 - src/common/jingle_xtls.py | 4 +--- src/common/location_listener.py | 1 - src/common/pep.py | 3 --- src/common/protocol/bytestream.py | 1 - src/common/protocol/caps.py | 1 - src/common/zeroconf/client_zeroconf.py | 1 - .../zeroconf/connection_handlers_zeroconf.py | 5 ----- src/common/zeroconf/connection_zeroconf.py | 2 -- src/common/zeroconf/zeroconf_avahi.py | 2 +- src/conversation_textview.py | 1 - src/features_window.py | 1 - src/groupchat_control.py | 1 - src/gui_interface.py | 4 +--- src/history_manager.py | 1 - src/htmltextview.py | 3 --- src/plugins/gui.py | 3 +-- src/roster_window.py | 6 +----- src/statusicon.py | 2 -- src/tooltips.py | 3 +-- src/upower_listener.py | 2 -- 32 files changed, 12 insertions(+), 64 deletions(-) diff --git a/src/advanced_configuration_window.py b/src/advanced_configuration_window.py index 6faba9ec2..2a0bb9c73 100644 --- a/src/advanced_configuration_window.py +++ b/src/advanced_configuration_window.py @@ -29,7 +29,6 @@ from gi.repository import GLib from gi.repository import Pango from common import gajim -from common import helpers ( OPT_TYPE, diff --git a/src/atom_window.py b/src/atom_window.py index fb4afed76..88a0b5030 100644 --- a/src/atom_window.py +++ b/src/atom_window.py @@ -22,7 +22,6 @@ ## -from gi.repository import Gtk from gi.repository import Gdk from gi.repository import GLib diff --git a/src/command_system/framework.py b/src/command_system/framework.py index ca2469522..c6922c953 100644 --- a/src/command_system/framework.py +++ b/src/command_system/framework.py @@ -19,7 +19,6 @@ architecture to implement commands in a streight and flexible, declarative way. """ -import re from types import FunctionType from inspect import getargspec, getdoc diff --git a/src/command_system/implementation/standard.py b/src/command_system/implementation/standard.py index bd263b669..8644242cd 100644 --- a/src/command_system/implementation/standard.py +++ b/src/command_system/implementation/standard.py @@ -31,7 +31,6 @@ from ..framework import CommandContainer, command, doc from ..mapping import generate_usage from .hosts import ChatCommands, PrivateChatCommands, GroupChatCommands -from . import execute # This holds constants fron the logger, which we'll be using in some of our # commands. diff --git a/src/command_system/tools.py b/src/command_system/tools.py index 307f3b0f2..42a295dd0 100644 --- a/src/command_system/tools.py +++ b/src/command_system/tools.py @@ -24,12 +24,10 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -from types import * - def remove(sequence, target): if isinstance(sequence, list): if target in sequence: sequence.remove(target) elif isinstance(sequence, dict): if target in sequence: - del sequence[target] \ No newline at end of file + del sequence[target] diff --git a/src/common/connection_handlers.py b/src/common/connection_handlers.py index f749db5b8..1a54b7432 100644 --- a/src/common/connection_handlers.py +++ b/src/common/connection_handlers.py @@ -30,14 +30,13 @@ import os import base64 -import sys import operator import hashlib -from gi.repository import GLib -from time import (altzone, daylight, gmtime, localtime, mktime, strftime, +from time import (altzone, daylight, gmtime, localtime, strftime, time as time_time, timezone, tzname) -from calendar import timegm + +from gi.repository import GLib import nbxmpp from common import caps_cache as capscache @@ -63,11 +62,6 @@ from common.nec import NetworkEvent from common.jingle import ConnectionJingle -from common import dbus_support -if dbus_support.supported: - import dbus - from music_track_listener import MusicTrackListener - import logging log = logging.getLogger('gajim.c.connection_handlers') @@ -603,7 +597,7 @@ class ConnectionVcard: node = conf.getAttr('node') form_tag = conf.getTag('x', namespace=nbxmpp.NS_DATA) if form_tag: - form = common.dataforms.ExtendForm(node=form_tag) + form = dataforms.ExtendForm(node=form_tag) gajim.nec.push_incoming_event(PEPConfigReceivedEvent(None, conn=self, node=node, form=form)) diff --git a/src/common/connection_handlers_events.py b/src/common/connection_handlers_events.py index a16ef0c16..d7b0d19fb 100644 --- a/src/common/connection_handlers_events.py +++ b/src/common/connection_handlers_events.py @@ -21,7 +21,7 @@ import datetime import sys import os -from time import (localtime, time as time_time) +from time import time as time_time from calendar import timegm import hmac import hashlib diff --git a/src/common/gajim.py b/src/common/gajim.py index f9ba812df..b738b018f 100644 --- a/src/common/gajim.py +++ b/src/common/gajim.py @@ -35,7 +35,6 @@ import uuid from common import config import nbxmpp -from common import defs from common import ged as ged_module interface = None # The actual interface (the gtk one for the moment) diff --git a/src/common/helpers.py b/src/common/helpers.py index 38fc4f12c..25dffea55 100644 --- a/src/common/helpers.py +++ b/src/common/helpers.py @@ -45,7 +45,6 @@ import socket import time import datetime -from gi.repository import GObject from encodings.punycode import punycode_encode from string import Template diff --git a/src/common/jingle_content.py b/src/common/jingle_content.py index 630a98b8a..3442c8ae7 100644 --- a/src/common/jingle_content.py +++ b/src/common/jingle_content.py @@ -20,7 +20,6 @@ Handles Jingle contents (XEP 0166) import os from common import gajim import nbxmpp -from common.jingle_transport import JingleTransportIBB from .jingle_xtls import SELF_SIGNED_CERTIFICATE from .jingle_xtls import load_cert_file diff --git a/src/common/jingle_ft.py b/src/common/jingle_ft.py index f12a15c4b..091025e21 100644 --- a/src/common/jingle_ft.py +++ b/src/common/jingle_ft.py @@ -28,7 +28,6 @@ from . import jingle_xtls from common.jingle_content import contents, JingleContent from common.jingle_transport import * from common import helpers -from common.socks5 import Socks5ReceiverClient, Socks5SenderClient from common.connection_handlers_events import FileRequestReceivedEvent import threading import logging diff --git a/src/common/jingle_transport.py b/src/common/jingle_transport.py index 16f85da88..ffd26bae9 100644 --- a/src/common/jingle_transport.py +++ b/src/common/jingle_transport.py @@ -20,7 +20,6 @@ Handles Jingle Transports (currently only ICE-UDP) import nbxmpp import socket from common import gajim -from common.protocol.bytestream import ConnectionSocks5Bytestream import logging log = logging.getLogger('gajim.c.jingle_transport') diff --git a/src/common/jingle_xtls.py b/src/common/jingle_xtls.py index 84fd51a26..25e182291 100644 --- a/src/common/jingle_xtls.py +++ b/src/common/jingle_xtls.py @@ -44,9 +44,7 @@ except ImportError: log.info("PyOpenSSL not available") if PYOPENSSL_PRESENT: - from OpenSSL import SSL - from OpenSSL.SSL import Context - from OpenSSL import crypto + from OpenSSL import SSL, crypto TYPE_RSA = crypto.TYPE_RSA TYPE_DSA = crypto.TYPE_DSA diff --git a/src/common/location_listener.py b/src/common/location_listener.py index 058bcadcd..88c12c8f9 100644 --- a/src/common/location_listener.py +++ b/src/common/location_listener.py @@ -21,7 +21,6 @@ from datetime import datetime from common import gajim -from common import pep from common import dbus_support if dbus_support.supported: import dbus diff --git a/src/common/pep.py b/src/common/pep.py index c0aa00e18..4a96a085a 100644 --- a/src/common/pep.py +++ b/src/common/pep.py @@ -216,13 +216,10 @@ LOCATION_DATA = { 'uri': _('uri')} from gi.repository import GLib -from gi.repository import Gtk -from gi.repository import GdkPixbuf import logging log = logging.getLogger('gajim.c.pep') -from common import helpers import nbxmpp from common import gajim diff --git a/src/common/protocol/bytestream.py b/src/common/protocol/bytestream.py index 448dcc36d..ce0f471bf 100644 --- a/src/common/protocol/bytestream.py +++ b/src/common/protocol/bytestream.py @@ -36,7 +36,6 @@ import time import nbxmpp from common import gajim from common import helpers -from common import dataforms from common import ged from common import jingle_xtls from common.file_props import FilesProp diff --git a/src/common/protocol/caps.py b/src/common/protocol/caps.py index b8792d5ab..8753449a2 100644 --- a/src/common/protocol/caps.py +++ b/src/common/protocol/caps.py @@ -27,7 +27,6 @@ log = logging.getLogger('gajim.c.p.caps') from common import gajim from common import ged -from common import helpers from common.connection_handlers_events import CapsPresenceReceivedEvent, \ CapsDiscoReceivedEvent, CapsReceivedEvent diff --git a/src/common/zeroconf/client_zeroconf.py b/src/common/zeroconf/client_zeroconf.py index 9c093441e..e61ee462b 100644 --- a/src/common/zeroconf/client_zeroconf.py +++ b/src/common/zeroconf/client_zeroconf.py @@ -22,7 +22,6 @@ import nbxmpp from nbxmpp.idlequeue import IdleObject from nbxmpp import dispatcher_nb, simplexml from nbxmpp.plugin import * -from nbxmpp.simplexml import ustr from nbxmpp.transports_nb import DATA_RECEIVED, DATA_SENT, DATA_ERROR from common.zeroconf import zeroconf diff --git a/src/common/zeroconf/connection_handlers_zeroconf.py b/src/common/zeroconf/connection_handlers_zeroconf.py index f1d113c62..ddacc0e37 100644 --- a/src/common/zeroconf/connection_handlers_zeroconf.py +++ b/src/common/zeroconf/connection_handlers_zeroconf.py @@ -23,13 +23,9 @@ ## along with Gajim. If not, see . ## -import time - import nbxmpp -from common import helpers from common import gajim -from common.zeroconf import zeroconf from common.commands import ConnectionCommands from common.protocol.bytestream import ConnectionSocks5BytestreamZeroconf from common.connection_handlers_events import ZeroconfMessageReceivedEvent @@ -51,7 +47,6 @@ except Exception: HAS_IDLE = False from common import connection_handlers -from session import ChatControlSession class ConnectionVcard(connection_handlers.ConnectionVcard): def add_sha(self, p, send_caps = True): diff --git a/src/common/zeroconf/connection_zeroconf.py b/src/common/zeroconf/connection_zeroconf.py index ea910547a..0c55146de 100644 --- a/src/common/zeroconf/connection_zeroconf.py +++ b/src/common/zeroconf/connection_zeroconf.py @@ -50,8 +50,6 @@ from common.zeroconf import zeroconf from common.zeroconf.connection_handlers_zeroconf import * from common.connection_handlers_events import * -import locale - class ConnectionZeroconf(CommonConnection, ConnectionHandlersZeroconf): def __init__(self, name): ConnectionHandlersZeroconf.__init__(self) diff --git a/src/common/zeroconf/zeroconf_avahi.py b/src/common/zeroconf/zeroconf_avahi.py index 260671e75..497a0c374 100644 --- a/src/common/zeroconf/zeroconf_avahi.py +++ b/src/common/zeroconf/zeroconf_avahi.py @@ -26,7 +26,7 @@ except ImportError: pass from common.zeroconf.zeroconf import C_BARE_NAME, C_RESOLVED_INFO, \ -C_RI_INTERFACE, C_RI_PROTOCOL, C_RI_APROTOCOL, C_DOMAIN, C_TXT +C_RI_INTERFACE, C_RI_PROTOCOL, C_DOMAIN, C_TXT class Zeroconf: def __init__(self, new_serviceCB, remove_serviceCB, name_conflictCB, diff --git a/src/conversation_textview.py b/src/conversation_textview.py index 054c92e0a..0c2b2a452 100644 --- a/src/conversation_textview.py +++ b/src/conversation_textview.py @@ -51,7 +51,6 @@ from common.fuzzyclock import FuzzyClock from htmltextview import HtmlTextView from common.exceptions import GajimGeneralException -from encodings.punycode import punycode_encode as puny_encode NOT_SHOWN = 0 ALREADY_RECEIVED = 1 diff --git a/src/features_window.py b/src/features_window.py index f28f5ab3c..35fea44c8 100644 --- a/src/features_window.py +++ b/src/features_window.py @@ -29,7 +29,6 @@ from gi.repository import Gtk import gtkgui_helpers from common import gajim -from common import helpers from common.i18n import Q_ class FeaturesWindow: diff --git a/src/groupchat_control.py b/src/groupchat_control.py index 878cd1aa8..bf4a72c6a 100644 --- a/src/groupchat_control.py +++ b/src/groupchat_control.py @@ -55,7 +55,6 @@ from common import i18n from chat_control import ChatControl from chat_control_base import ChatControlBase -from common.exceptions import GajimGeneralException from command_system.implementation.hosts import PrivateChatCommands from command_system.implementation.hosts import GroupChatCommands diff --git a/src/gui_interface.py b/src/gui_interface.py index e2806328c..712176cbc 100644 --- a/src/gui_interface.py +++ b/src/gui_interface.py @@ -80,13 +80,11 @@ from common import caps_cache from common import proxy65_manager from common import socks5 from common import helpers -from common import dataforms from common import passwords from common import logging_helpers from common.connection_handlers_events import OurShowEvent, \ - FileRequestErrorEvent, FileTransferCompletedEvent, InformationEvent + FileRequestErrorEvent, FileTransferCompletedEvent from common.connection import Connection -from common import jingle from common.file_props import FilesProp from common import pep diff --git a/src/history_manager.py b/src/history_manager.py index 97b086873..873f32cea 100644 --- a/src/history_manager.py +++ b/src/history_manager.py @@ -89,7 +89,6 @@ del parseOpts import common.configpaths common.configpaths.gajimpaths.init(config_path) del config_path -from common import exceptions from common import gajim import gtkgui_helpers from common.logger import LOG_DB_PATH, constants diff --git a/src/htmltextview.py b/src/htmltextview.py index 1b0092eea..a6f6a6270 100644 --- a/src/htmltextview.py +++ b/src/htmltextview.py @@ -51,7 +51,6 @@ if __name__ == '__main__': from common import i18n import common.configpaths common.configpaths.gajimpaths.init(None) - import gtkgui_helpers from common import gajim from gtkgui_helpers import get_icon_pixmap from common import helpers @@ -1130,8 +1129,6 @@ class HtmlTextView(Gtk.TextView): change_cursor = None if __name__ == '__main__': - import os - from conversation_textview import ConversationTextview import gajim as gaj diff --git a/src/plugins/gui.py b/src/plugins/gui.py index b9382f6f8..c2db69f59 100644 --- a/src/plugins/gui.py +++ b/src/plugins/gui.py @@ -36,7 +36,7 @@ import gtkgui_helpers from dialogs import WarningDialog, YesNoDialog, ArchiveChooserDialog from htmltextview import HtmlTextView from common import gajim -from plugins.helpers import log_calls, log +from plugins.helpers import log_calls from plugins.helpers import GajimPluginActivateException from plugins.plugins_i18n import _ from common.exceptions import PluginsystemError @@ -221,7 +221,6 @@ class PluginsWindow(object): @log_calls('PluginsWindow') def on_configure_plugin_button_clicked(self, widget): - #log.debug('widget: %s'%(widget)) selection = self.installed_plugins_treeview.get_selection() model, iter = selection.get_selected() if iter: diff --git a/src/roster_window.py b/src/roster_window.py index 79c92de1e..a967235d6 100644 --- a/src/roster_window.py +++ b/src/roster_window.py @@ -64,16 +64,12 @@ from common import gajim from common import helpers from common.exceptions import GajimGeneralException from common import i18n -from common import pep from common import location_listener from common import ged +from common import dbus_support from message_window import MessageWindowMgr -from common import dbus_support -if dbus_support.supported: - import dbus - from nbxmpp.protocol import NS_FILE, NS_ROSTERX, NS_CONFERENCE #(icon, name, type, jid, account, editable, second pixbuf) diff --git a/src/statusicon.py b/src/statusicon.py index 84795982f..4544cb2df 100644 --- a/src/statusicon.py +++ b/src/statusicon.py @@ -25,7 +25,6 @@ from gi.repository import Gtk from gi.repository import Gdk -from gi.repository import GObject import os import dialogs @@ -35,7 +34,6 @@ import gtkgui_helpers from common import gajim from common import helpers -from common import pep class StatusIcon: """ diff --git a/src/tooltips.py b/src/tooltips.py index bfdf48688..3c9d30388 100644 --- a/src/tooltips.py +++ b/src/tooltips.py @@ -40,7 +40,6 @@ import gtkgui_helpers from common import gajim from common import helpers -from common.pep import MOODS, ACTIVITIES from common.i18n import Q_ class BaseTooltip: @@ -920,4 +919,4 @@ def colorize_status(status): color = gajim.config.get('tooltip_status_offline_color') if color: status = formatted % (color, status) - return status \ No newline at end of file + return status diff --git a/src/upower_listener.py b/src/upower_listener.py index e6441e9ac..744399689 100644 --- a/src/upower_listener.py +++ b/src/upower_listener.py @@ -33,8 +33,6 @@ def on_suspend(*args, **kwargs): conn.time_to_reconnect = 5 if dbus_support.supported: - import dbus - try: from common.dbus_support import system_bus bus = system_bus.bus() From 5f91455fb931532cb8975532aa208d6e31ca768e Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 7 Feb 2017 19:56:52 +0000 Subject: [PATCH 06/16] common.dh: Reformat to follow PEP-0008. --- src/common/dh.py | 387 ++++++++++++++++++++++++----------------------- 1 file changed, 195 insertions(+), 192 deletions(-) diff --git a/src/common/dh.py b/src/common/dh.py index 3ec46e01d..aeba2d288 100644 --- a/src/common/dh.py +++ b/src/common/dh.py @@ -28,203 +28,206 @@ These constants have been obtained from RFC2409 and RFC3526. import string -generators = [None, # one to get the right offset - 2, - 2, - None, - None, - 2, - None, - None, - None, - None, - None, - None, - None, - None, - 2, # group 14 - 2, - 2, - 2, - 2] - -hex_primes = [None, - -# group 1 -'''FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 -29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD -EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 -E485B576 625E7EC6 F44C42E9 A63A3620 FFFFFFFF FFFFFFFF''', - -# group 2 -'''FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 -29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD -EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 -E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED -EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381 -FFFFFFFF FFFFFFFF''', - -# XXX how do I obtain these? -None, -None, - -# group 5 -'''FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 -29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD -EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 -E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED -EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D -C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F -83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D -670C354E 4ABC9804 F1746C08 CA237327 FFFFFFFF FFFFFFFF''', - -None, -None, -None, -None, -None, -None, -None, -None, - -# group 14 -'''FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 -29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD -EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 -E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED -EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D -C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F -83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D -670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B -E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 -DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510 -15728E5A 8AACAA68 FFFFFFFF FFFFFFFF''', - -# group 15 -'''FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 -29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD -EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 -E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED -EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D -C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F -83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D -670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B -E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 -DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510 -15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64 -ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7 -ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B -F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C -BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31 -43DB5BFC E0FD108E 4B82D120 A93AD2CA FFFFFFFF FFFFFFFF''', - -# group 16 -'''FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 -29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD -EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 -E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED -EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D -C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F -83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D -670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B -E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 -DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510 -15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64 -ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7 -ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B -F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C -BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31 -43DB5BFC E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7 -88719A10 BDBA5B26 99C32718 6AF4E23C 1A946834 B6150BDA -2583E9CA 2AD44CE8 DBBBC2DB 04DE8EF9 2E8EFC14 1FBECAA6 -287C5947 4E6BC05D 99B2964F A090C3A2 233BA186 515BE7ED -1F612970 CEE2D7AF B81BDD76 2170481C D0069127 D5B05AA9 -93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34063199 -FFFFFFFF FFFFFFFF''', - -# group 17 -'''FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 29024E08 -8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD EF9519B3 CD3A431B -302B0A6D F25F1437 4FE1356D 6D51C245 E485B576 625E7EC6 F44C42E9 -A637ED6B 0BFF5CB6 F406B7ED EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 -49286651 ECE45B3D C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 -FD24CF5F 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D -670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B E39E772C -180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 DE2BCBF6 95581718 -3995497C EA956AE5 15D22618 98FA0510 15728E5A 8AAAC42D AD33170D -04507A33 A85521AB DF1CBA64 ECFB8504 58DBEF0A 8AEA7157 5D060C7D -B3970F85 A6E1E4C7 ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 -1AD2EE6B F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C -BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31 43DB5BFC -E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7 88719A10 BDBA5B26 -99C32718 6AF4E23C 1A946834 B6150BDA 2583E9CA 2AD44CE8 DBBBC2DB -04DE8EF9 2E8EFC14 1FBECAA6 287C5947 4E6BC05D 99B2964F A090C3A2 -233BA186 515BE7ED 1F612970 CEE2D7AF B81BDD76 2170481C D0069127 -D5B05AA9 93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34028492 -36C3FAB4 D27C7026 C1D4DCB2 602646DE C9751E76 3DBA37BD F8FF9406 -AD9E530E E5DB382F 413001AE B06A53ED 9027D831 179727B0 865A8918 -DA3EDBEB CF9B14ED 44CE6CBA CED4BB1B DB7F1447 E6CC254B 33205151 -2BD7AF42 6FB8F401 378CD2BF 5983CA01 C64B92EC F032EA15 D1721D03 -F482D7CE 6E74FEF6 D55E702F 46980C82 B5A84031 900B1C9E 59E7C97F -BEC7E8F3 23A97A7E 36CC88BE 0F1D45B7 FF585AC5 4BD407B2 2B4154AA -CC8F6D7E BF48E1D8 14CC5ED2 0F8037E0 A79715EE F29BE328 06A1D58B -B7C5DA76 F550AA3D 8A1FBFF0 EB19CCB1 A313D55C DA56C9EC 2EF29632 -387FE8D7 6E3C0468 043E8F66 3F4860EE 12BF2D5B 0B7474D6 E694F91E -6DCC4024 FFFFFFFF FFFFFFFF''', - -# group 18 -'''FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 -29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD -EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 -E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED -EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D -C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F -83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D -670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B -E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 -DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510 -15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64 -ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7 -ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B -F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C -BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31 -43DB5BFC E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7 -88719A10 BDBA5B26 99C32718 6AF4E23C 1A946834 B6150BDA -2583E9CA 2AD44CE8 DBBBC2DB 04DE8EF9 2E8EFC14 1FBECAA6 -287C5947 4E6BC05D 99B2964F A090C3A2 233BA186 515BE7ED -1F612970 CEE2D7AF B81BDD76 2170481C D0069127 D5B05AA9 -93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34028492 -36C3FAB4 D27C7026 C1D4DCB2 602646DE C9751E76 3DBA37BD -F8FF9406 AD9E530E E5DB382F 413001AE B06A53ED 9027D831 -179727B0 865A8918 DA3EDBEB CF9B14ED 44CE6CBA CED4BB1B -DB7F1447 E6CC254B 33205151 2BD7AF42 6FB8F401 378CD2BF -5983CA01 C64B92EC F032EA15 D1721D03 F482D7CE 6E74FEF6 -D55E702F 46980C82 B5A84031 900B1C9E 59E7C97F BEC7E8F3 -23A97A7E 36CC88BE 0F1D45B7 FF585AC5 4BD407B2 2B4154AA -CC8F6D7E BF48E1D8 14CC5ED2 0F8037E0 A79715EE F29BE328 -06A1D58B B7C5DA76 F550AA3D 8A1FBFF0 EB19CCB1 A313D55C -DA56C9EC 2EF29632 387FE8D7 6E3C0468 043E8F66 3F4860EE -12BF2D5B 0B7474D6 E694F91E 6DBE1159 74A3926F 12FEE5E4 -38777CB6 A932DF8C D8BEC4D0 73B931BA 3BC832B6 8D9DD300 -741FA7BF 8AFC47ED 2576F693 6BA42466 3AAB639C 5AE4F568 -3423B474 2BF1C978 238F16CB E39D652D E3FDB8BE FC848AD9 -22222E04 A4037C07 13EB57A8 1A23F0C7 3473FC64 6CEA306B -4BCBC886 2F8385DD FA9D4B7F A2C087E8 79683303 ED5BDD3A -062B3CF5 B3A278A6 6D2A13F8 3F44F82D DF310EE0 74AB6A36 -4597E899 A0255DC1 64F31CC5 0846851D F9AB4819 5DED7EA1 -B1D510BD 7EE74D73 FAF36BC3 1ECFA268 359046F4 EB879F92 -4009438B 481C6CD7 889A002E D5EE382B C9190DA6 FC026E47 -9558E447 5677E9AA 9E3050E2 765694DF C81F56E8 80B96E71 -60C980DD 98EDD3DF FFFFFFFF FFFFFFFF''' +generators = [ + None, # one to get the right offset + 2, + 2, + None, + None, + 2, + None, + None, + None, + None, + None, + None, + None, + None, + 2, # group 14 + 2, + 2, + 2, + 2 ] -all_ascii = ''.join(map(chr, range(256))) +_HEX_PRIMES = [ + None, + + # group 1 + '''FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 + 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD + EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 + E485B576 625E7EC6 F44C42E9 A63A3620 FFFFFFFF FFFFFFFF''', + + # group 2 + '''FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 + 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD + EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 + E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED + EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381 + FFFFFFFF FFFFFFFF''', + + # XXX how do I obtain these? + None, + None, + + # group 5 + '''FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 + 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD + EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 + E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED + EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D + C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F + 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D + 670C354E 4ABC9804 F1746C08 CA237327 FFFFFFFF FFFFFFFF''', + + None, + None, + None, + None, + None, + None, + None, + None, + + # group 14 + '''FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 + 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD + EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 + E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED + EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D + C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F + 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D + 670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B + E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 + DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510 + 15728E5A 8AACAA68 FFFFFFFF FFFFFFFF''', + + # group 15 + '''FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 + 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD + EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 + E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED + EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D + C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F + 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D + 670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B + E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 + DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510 + 15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64 + ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7 + ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B + F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C + BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31 + 43DB5BFC E0FD108E 4B82D120 A93AD2CA FFFFFFFF FFFFFFFF''', + + # group 16 + '''FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 + 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD + EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 + E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED + EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D + C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F + 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D + 670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B + E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 + DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510 + 15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64 + ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7 + ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B + F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C + BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31 + 43DB5BFC E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7 + 88719A10 BDBA5B26 99C32718 6AF4E23C 1A946834 B6150BDA + 2583E9CA 2AD44CE8 DBBBC2DB 04DE8EF9 2E8EFC14 1FBECAA6 + 287C5947 4E6BC05D 99B2964F A090C3A2 233BA186 515BE7ED + 1F612970 CEE2D7AF B81BDD76 2170481C D0069127 D5B05AA9 + 93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34063199 + FFFFFFFF FFFFFFFF''', + + # group 17 + '''FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 29024E08 + 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD EF9519B3 CD3A431B + 302B0A6D F25F1437 4FE1356D 6D51C245 E485B576 625E7EC6 F44C42E9 + A637ED6B 0BFF5CB6 F406B7ED EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 + 49286651 ECE45B3D C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 + FD24CF5F 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D + 670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B E39E772C + 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 DE2BCBF6 95581718 + 3995497C EA956AE5 15D22618 98FA0510 15728E5A 8AAAC42D AD33170D + 04507A33 A85521AB DF1CBA64 ECFB8504 58DBEF0A 8AEA7157 5D060C7D + B3970F85 A6E1E4C7 ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 + 1AD2EE6B F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C + BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31 43DB5BFC + E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7 88719A10 BDBA5B26 + 99C32718 6AF4E23C 1A946834 B6150BDA 2583E9CA 2AD44CE8 DBBBC2DB + 04DE8EF9 2E8EFC14 1FBECAA6 287C5947 4E6BC05D 99B2964F A090C3A2 + 233BA186 515BE7ED 1F612970 CEE2D7AF B81BDD76 2170481C D0069127 + D5B05AA9 93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34028492 + 36C3FAB4 D27C7026 C1D4DCB2 602646DE C9751E76 3DBA37BD F8FF9406 + AD9E530E E5DB382F 413001AE B06A53ED 9027D831 179727B0 865A8918 + DA3EDBEB CF9B14ED 44CE6CBA CED4BB1B DB7F1447 E6CC254B 33205151 + 2BD7AF42 6FB8F401 378CD2BF 5983CA01 C64B92EC F032EA15 D1721D03 + F482D7CE 6E74FEF6 D55E702F 46980C82 B5A84031 900B1C9E 59E7C97F + BEC7E8F3 23A97A7E 36CC88BE 0F1D45B7 FF585AC5 4BD407B2 2B4154AA + CC8F6D7E BF48E1D8 14CC5ED2 0F8037E0 A79715EE F29BE328 06A1D58B + B7C5DA76 F550AA3D 8A1FBFF0 EB19CCB1 A313D55C DA56C9EC 2EF29632 + 387FE8D7 6E3C0468 043E8F66 3F4860EE 12BF2D5B 0B7474D6 E694F91E + 6DCC4024 FFFFFFFF FFFFFFFF''', + + # group 18 + '''FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 + 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD + EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245 + E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED + EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D + C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F + 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D + 670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B + E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 + DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510 + 15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64 + ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7 + ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B + F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C + BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31 + 43DB5BFC E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7 + 88719A10 BDBA5B26 99C32718 6AF4E23C 1A946834 B6150BDA + 2583E9CA 2AD44CE8 DBBBC2DB 04DE8EF9 2E8EFC14 1FBECAA6 + 287C5947 4E6BC05D 99B2964F A090C3A2 233BA186 515BE7ED + 1F612970 CEE2D7AF B81BDD76 2170481C D0069127 D5B05AA9 + 93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34028492 + 36C3FAB4 D27C7026 C1D4DCB2 602646DE C9751E76 3DBA37BD + F8FF9406 AD9E530E E5DB382F 413001AE B06A53ED 9027D831 + 179727B0 865A8918 DA3EDBEB CF9B14ED 44CE6CBA CED4BB1B + DB7F1447 E6CC254B 33205151 2BD7AF42 6FB8F401 378CD2BF + 5983CA01 C64B92EC F032EA15 D1721D03 F482D7CE 6E74FEF6 + D55E702F 46980C82 B5A84031 900B1C9E 59E7C97F BEC7E8F3 + 23A97A7E 36CC88BE 0F1D45B7 FF585AC5 4BD407B2 2B4154AA + CC8F6D7E BF48E1D8 14CC5ED2 0F8037E0 A79715EE F29BE328 + 06A1D58B B7C5DA76 F550AA3D 8A1FBFF0 EB19CCB1 A313D55C + DA56C9EC 2EF29632 387FE8D7 6E3C0468 043E8F66 3F4860EE + 12BF2D5B 0B7474D6 E694F91E 6DBE1159 74A3926F 12FEE5E4 + 38777CB6 A932DF8C D8BEC4D0 73B931BA 3BC832B6 8D9DD300 + 741FA7BF 8AFC47ED 2576F693 6BA42466 3AAB639C 5AE4F568 + 3423B474 2BF1C978 238F16CB E39D652D E3FDB8BE FC848AD9 + 22222E04 A4037C07 13EB57A8 1A23F0C7 3473FC64 6CEA306B + 4BCBC886 2F8385DD FA9D4B7F A2C087E8 79683303 ED5BDD3A + 062B3CF5 B3A278A6 6D2A13F8 3F44F82D DF310EE0 74AB6A36 + 4597E899 A0255DC1 64F31CC5 0846851D F9AB4819 5DED7EA1 + B1D510BD 7EE74D73 FAF36BC3 1ECFA268 359046F4 EB879F92 + 4009438B 481C6CD7 889A002E D5EE382B C9190DA6 FC026E47 + 9558E447 5677E9AA 9E3050E2 765694DF C81F56E8 80B96E71 + 60C980DD 98EDD3DF FFFFFFFF FFFFFFFF''' +] + +_ALL_ASCII = ''.join(map(chr, range(256))) def hex_to_decimal(stripee): if not stripee: return None - return int(stripee.translate(all_ascii).translate(str.maketrans("", "", - string.whitespace)), 16) + return int(stripee.translate(_ALL_ASCII).translate( + str.maketrans("", "", string.whitespace)), 16) -primes = list(map(hex_to_decimal, hex_primes)) +primes = list(map(hex_to_decimal, _HEX_PRIMES)) From fb221a692bd94f65e64284dad589ce25228a5e04 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 7 Feb 2017 20:05:27 +0000 Subject: [PATCH 07/16] =?UTF-8?q?Remove=20wrong=20usage=20of=20the=20list(?= =?UTF-8?q?range(=E2=80=A6))=20pattern.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/command_system/implementation/execute.py | 2 +- src/common/socks5.py | 2 +- src/dataforms_widget.py | 2 +- src/gtkgui_helpers.py | 2 +- src/message_window.py | 6 +++--- src/plugins/gui.py | 6 +++--- src/roster_window.py | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/command_system/implementation/execute.py b/src/command_system/implementation/execute.py index 767e761a5..0e8718be4 100644 --- a/src/command_system/implementation/execute.py +++ b/src/command_system/implementation/execute.py @@ -68,7 +68,7 @@ class Execute(CommandContainer): @classmethod def poller(cls, processor, popen): - for x in list(range(cls.POLL_COUNT)): + for _ in range(cls.POLL_COUNT): yield cls.brush(processor, popen) cls.overdue(processor, popen) yield False diff --git a/src/common/socks5.py b/src/common/socks5.py index 60b3584fe..a823023b2 100644 --- a/src/common/socks5.py +++ b/src/common/socks5.py @@ -825,7 +825,7 @@ class Socks5(object): auth_mechanisms = [] try: num_auth = struct.unpack('!xB', buff[:2])[0] - for i in list(range(num_auth)): + for i in range(num_auth): mechanism, = struct.unpack('!B', buff[1 + i]) auth_mechanisms.append(mechanism) except Exception: diff --git a/src/dataforms_widget.py b/src/dataforms_widget.py index 3f087381a..913200f65 100644 --- a/src/dataforms_widget.py +++ b/src/dataforms_widget.py @@ -279,7 +279,7 @@ class DataFormWidget(Gtk.Alignment, object): selection = self.records_treeview.get_selection() model, rowrefs = selection.get_selected_rows() # rowref is a list of paths - for i in list(range(len(rowrefs))): + for i in range(len(rowrefs)): rowrefs[i] = Gtk.TreeRowReference.new(model, rowrefs[i]) # rowref is a list of row references; need to convert because we will # modify the model, paths would change diff --git a/src/gtkgui_helpers.py b/src/gtkgui_helpers.py index 1f4515756..1ab87acc9 100644 --- a/src/gtkgui_helpers.py +++ b/src/gtkgui_helpers.py @@ -362,7 +362,7 @@ class HashDigest: def __str__(self): prettydigest = '' - for i in list(range(0, len(self.digest), 2)): + for i in range(0, len(self.digest), 2): prettydigest += self.digest[i:i + 2] + ':' return prettydigest[:-1] diff --git a/src/message_window.py b/src/message_window.py index fa1b0b4bd..209c9e624 100644 --- a/src/message_window.py +++ b/src/message_window.py @@ -120,7 +120,7 @@ class MessageWindow(object): 'b', 'F4', 'w', 'Page_Up', 'Page_Down', 'Right', 'Left', 'd', 'c', 'm', 't', 'Escape'] + \ - [''+str(i) for i in list(range(10))] + [''+str(i) for i in range(10)] accel_group = Gtk.AccelGroup() for key in keys: keyval, mod = Gtk.accelerator_parse(key) @@ -877,7 +877,7 @@ class MessageWindow(object): to_right = False horiz = self.notebook.get_tab_pos() == Gtk.PositionType.TOP or \ self.notebook.get_tab_pos() == Gtk.PositionType.BOTTOM - for i in list(range(self.notebook.get_n_pages())): + for i in range(self.notebook.get_n_pages()): page = self.notebook.get_nth_page(i) tab = self.notebook.get_tab_label(page) tab_alloc = tab.get_allocation() @@ -903,7 +903,7 @@ class MessageWindow(object): Find the page num of the tab label """ page_num = -1 - for i in list(range(self.notebook.get_n_pages())): + for i in range(self.notebook.get_n_pages()): page = self.notebook.get_nth_page(i) tab = self.notebook.get_tab_label(page) if tab == tab_label: diff --git a/src/plugins/gui.py b/src/plugins/gui.py index c2db69f59..f544c9242 100644 --- a/src/plugins/gui.py +++ b/src/plugins/gui.py @@ -270,9 +270,9 @@ class PluginsWindow(object): return model = self.installed_plugins_model - for row in list(range(len(model))): - if plugin == model[row][PLUGIN]: - model.remove(model.get_iter((row, PLUGIN))) + for i, row in enumerate(model): + if plugin == row[PLUGIN]: + model.remove(model.get_iter((i, PLUGIN))) break iter_ = model.append([plugin, plugin.name, False, diff --git a/src/roster_window.py b/src/roster_window.py index a967235d6..0039acfe3 100644 --- a/src/roster_window.py +++ b/src/roster_window.py @@ -3081,7 +3081,7 @@ class RosterWindow: 'attached_gpg_keys').split() keys = {} keyID = _('None') - for i in list(range(int(len(attached_keys)/2))): + for i in range(len(attached_keys) // 2): keys[attached_keys[2*i]] = attached_keys[2*i+1] if attached_keys[2*i] == contact.jid: keyID = attached_keys[2*i+1] From b6b1a7a074b579722aa6fe685772db008788d7d1 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 7 Feb 2017 20:17:48 +0000 Subject: [PATCH 08/16] ACE: Remove unused constants. --- src/advanced_configuration_window.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/advanced_configuration_window.py b/src/advanced_configuration_window.py index 2a0bb9c73..bc6bc1e4b 100644 --- a/src/advanced_configuration_window.py +++ b/src/advanced_configuration_window.py @@ -30,19 +30,12 @@ from gi.repository import Pango from common import gajim -( -OPT_TYPE, -OPT_VAL -) = range(2) - ( C_PREFNAME, C_VALUE, C_TYPE ) = range(3) -GTKGUI_GLADE = 'manage_accounts_window.ui' - def rate_limit(rate): """ Call func at most *rate* times per second From 2fbadc91e9dc5f543358e2fbdacdb554688516de Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 7 Feb 2017 20:18:41 +0000 Subject: [PATCH 09/16] Use Enum or IntEnum instead of range() constants. --- src/advanced_configuration_window.py | 31 +- src/chat_control.py | 12 +- src/common/config.py | 48 +-- src/common/configpaths.py | 44 +-- src/common/connection_handlers_events.py | 3 +- src/common/jingle_transport.py | 3 +- src/common/logger.py | 214 ++++++------- src/common/zeroconf/roster_zeroconf.py | 13 +- src/common/zeroconf/zeroconf.py | 18 +- src/common/zeroconf/zeroconf_avahi.py | 21 +- src/common/zeroconf/zeroconf_bonjour.py | 10 +- src/filetransfers_window.py | 79 ++--- src/groupchat_control.py | 76 ++--- src/history_manager.py | 46 +-- src/history_window.py | 95 +++--- src/plugins/gui.py | 53 ++-- src/roster_window.py | 384 +++++++++++------------ 17 files changed, 580 insertions(+), 570 deletions(-) diff --git a/src/advanced_configuration_window.py b/src/advanced_configuration_window.py index bc6bc1e4b..2e3946cd5 100644 --- a/src/advanced_configuration_window.py +++ b/src/advanced_configuration_window.py @@ -23,6 +23,8 @@ ## along with Gajim. If not, see . ## +from enum import IntEnum + from gi.repository import Gtk import gtkgui_helpers from gi.repository import GLib @@ -30,11 +32,10 @@ from gi.repository import Pango from common import gajim -( -C_PREFNAME, -C_VALUE, -C_TYPE -) = range(3) +class Column(IntEnum): + PREFERENCE_NAME = 0 + VALUE = 1 + TYPE = 2 def rate_limit(rate): """ @@ -135,8 +136,8 @@ class AdvancedConfigurationWindow(object): Check if it's boolen or holds password stuff and if yes make the cellrenderertext not editable, else - it's editable """ - optname = model[iter_][C_PREFNAME] - opttype = model[iter_][C_TYPE] + optname = model[iter_][Column.PREFERENCE_NAME] + opttype = model[iter_][Column.TYPE] if opttype == self.types['boolean'] or optname == 'password': cell.set_property('editable', False) else: @@ -263,8 +264,8 @@ class AdvancedConfigurationWindow(object): elif len(opt_path) == 3: default = gajim.config.get_default_per(opt_path[2], opt_path[0]) - if model[iter_][C_TYPE] == self.types['boolean']: - if self.right_true_dict[default] == model[iter_][C_VALUE]: + if model[iter_][Column.TYPE] == self.types['boolean']: + if self.right_true_dict[default] == model[iter_][Column.VALUE]: return modelpath = self.modelfilter.convert_path_to_child_path(path) modelrow = self.model[modelpath] @@ -275,15 +276,15 @@ class AdvancedConfigurationWindow(object): keyrow = self.model[modelpath[:2]] key = keyrow[0] self.remember_option(option + '\n' + key + '\n' + optname, - modelrow[C_VALUE], default) + modelrow[Column.VALUE], default) gajim.config.set_per(optname, key, option, default) else: - self.remember_option(option, modelrow[C_VALUE], default) + self.remember_option(option, modelrow[Column.VALUE], default) gajim.config.set(option, default) - modelrow[C_VALUE] = self.right_true_dict[default] + modelrow[Column.VALUE] = self.right_true_dict[default] self.check_for_restart() else: - if str(default) == model[iter_][C_VALUE]: + if str(default) == model[iter_][Column.VALUE]: return self.on_config_edited(None, path.to_string(), str(default)) @@ -317,14 +318,14 @@ class AdvancedConfigurationWindow(object): def visible_func(self, model, treeiter, data): search_string = self.entry.get_text().lower() for it in tree_model_pre_order(model, treeiter): - if model[it][C_TYPE] != '': + if model[it][Column.TYPE] != '': opt_path = self.get_option_path(model, it) if len(opt_path) == 3: desc = gajim.config.get_desc_per(opt_path[2], opt_path[1], opt_path[0]) elif len(opt_path) == 1: desc = gajim.config.get_desc(opt_path[0]) - if search_string in model[it][C_PREFNAME] or (desc and \ + if search_string in model[it][Column.PREFERENCE_NAME] or (desc and \ search_string in desc.lower()): return True return False diff --git a/src/chat_control.py b/src/chat_control.py index 669e025eb..6ecc7b8db 100644 --- a/src/chat_control.py +++ b/src/chat_control.py @@ -46,7 +46,7 @@ from common import ged from common import i18n from common.stanza_session import EncryptedStanzaSession, ArchivingStanzaSession from common.contacts import GC_Contact -from common.logger import constants +from common.logger import KindConstant from nbxmpp.protocol import NS_XHTML, NS_XHTML_IM, NS_FILE, NS_MUC from nbxmpp.protocol import NS_RECEIPTS, NS_ESESSION from nbxmpp.protocol import NS_JINGLE_RTP_AUDIO, NS_JINGLE_RTP_VIDEO @@ -1679,15 +1679,15 @@ class ChatControl(ChatControlBase): additional_data = row[4] if not msg: # message is empty, we don't print it continue - if row[1] in (constants.KIND_CHAT_MSG_SENT, - constants.KIND_SINGLE_MSG_SENT): + if row[1] in (KindConstant.CHAT_MSG_SENT, + KindConstant.SINGLE_MSG_SENT): kind = 'outgoing' name = self.get_our_nick() - elif row[1] in (constants.KIND_SINGLE_MSG_RECV, - constants.KIND_CHAT_MSG_RECV): + elif row[1] in (KindConstant.SINGLE_MSG_RECV, + KindConstant.CHAT_MSG_RECV): kind = 'incoming' name = self.contact.get_shown_name() - elif row[1] == constants.KIND_ERROR: + elif row[1] == KindConstant.ERROR: kind = 'status' name = self.contact.get_shown_name() diff --git a/src/common/config.py b/src/common/config.py index 5ce3f7981..b35c44392 100644 --- a/src/common/config.py +++ b/src/common/config.py @@ -35,15 +35,15 @@ import re from common import defs from gi.repository import GLib +from enum import IntEnum -( -OPT_TYPE, -OPT_VAL, -OPT_DESC, -# If OPT_RESTART is True - we need restart to use our changed option -# OPT_DESC also should be there -OPT_RESTART, -) = range(4) +class Option(IntEnum): + TYPE = 0 + VAL = 1 + DESC = 2 + # If Option.RESTART is True - we need restart to use our changed option + # Option.DESC also should be there + RESTART = 3 opt_int = [ 'integer', 0 ] opt_str = [ 'string', 0 ] @@ -633,7 +633,7 @@ class Config: def set(self, optname, value): if optname not in self.__options[1]: return - value = self.is_valid(self.__options[0][optname][OPT_TYPE], value) + value = self.is_valid(self.__options[0][optname][Option.TYPE], value) if value is None: return @@ -650,24 +650,24 @@ class Config: def get_default(self, optname): if optname not in self.__options[0]: return None - return self.__options[0][optname][OPT_VAL] + return self.__options[0][optname][Option.VAL] def get_type(self, optname): if optname not in self.__options[0]: return None - return self.__options[0][optname][OPT_TYPE][0] + return self.__options[0][optname][Option.TYPE][0] def get_desc(self, optname): if optname not in self.__options[0]: return None - if len(self.__options[0][optname]) > OPT_DESC: - return self.__options[0][optname][OPT_DESC] + if len(self.__options[0][optname]) > Option.DESC: + return self.__options[0][optname][Option.DESC] def get_restart(self, optname): if optname not in self.__options[0]: return None - if len(self.__options[0][optname]) > OPT_RESTART: - return self.__options[0][optname][OPT_RESTART] + if len(self.__options[0][optname]) > Option.RESTART: + return self.__options[0][optname][Option.RESTART] def add_per(self, typename, name): # per_group_of_option if typename not in self.__options_per_key: @@ -679,7 +679,7 @@ class Config: return 'you already have added %s before' % name opt[1][name] = {} for o in opt[0]: - opt[1][name][o] = opt[0][o][OPT_VAL] + opt[1][name][o] = opt[0][o][Option.VAL] self._timeout_save() def del_per(self, typename, name, subname = None): # per_group_of_option @@ -705,7 +705,7 @@ class Config: obj = dict_[key] if subname not in obj: return - typ = self.__options_per_key[optname][0][subname][OPT_TYPE] + typ = self.__options_per_key[optname][0][subname][Option.TYPE] value = self.is_valid(typ, value) if value is None: return @@ -735,7 +735,7 @@ class Config: dict_ = self.__options_per_key[optname][0] if subname not in dict_: return None - return dict_[subname][OPT_VAL] + return dict_[subname][Option.VAL] def get_type_per(self, optname, subname): if optname not in self.__options_per_key: @@ -743,7 +743,7 @@ class Config: dict_ = self.__options_per_key[optname][0] if subname not in dict_: return None - return dict_[subname][OPT_TYPE][0] + return dict_[subname][Option.TYPE][0] def get_desc_per(self, optname, key=None, subname=None): if optname not in self.__options_per_key: @@ -758,8 +758,8 @@ class Config: return None if subname not in obj: return None - if len(obj[subname]) > OPT_DESC: - return obj[subname][OPT_DESC] + if len(obj[subname]) > Option.DESC: + return obj[subname][Option.DESC] return None def get_restart_per(self, optname, key=None, subname=None): @@ -775,8 +775,8 @@ class Config: return False if subname not in obj: return False - if len(obj[subname]) > OPT_RESTART: - return obj[subname][OPT_RESTART] + if len(obj[subname]) > Option.RESTART: + return obj[subname][Option.RESTART] return False def should_log(self, account, jid): @@ -794,7 +794,7 @@ class Config: def _init_options(self): for opt in self.__options[0]: - self.__options[1][opt] = self.__options[0][opt][OPT_VAL] + self.__options[1][opt] = self.__options[0][opt][Option.VAL] def _really_save(self): from common import gajim diff --git a/src/common/configpaths.py b/src/common/configpaths.py index 717541700..74c171da3 100644 --- a/src/common/configpaths.py +++ b/src/common/configpaths.py @@ -26,12 +26,12 @@ import os import sys import tempfile from common import defs +from enum import Enum -( -TYPE_CONFIG, -TYPE_CACHE, -TYPE_DATA -) = range(3) +class Type(Enum): + CONFIG = 0 + CACHE = 1 + DATA = 2 # Note on path and filename encodings: # @@ -65,7 +65,7 @@ def get(key): class ConfigPaths: def __init__(self): - # {'name': (type, path), } type can be TYPE_CONFIG, TYPE_CACHE, TYPE_DATA + # {'name': (type, path), } type can be Type.CONFIG, Type.CACHE, Type.DATA # or None self.paths = {} @@ -109,11 +109,11 @@ class ConfigPaths: def __getitem__(self, key): type_, path = self.paths[key] - if type_ == TYPE_CONFIG: + if type_ == Type.CONFIG: return os.path.join(self.config_root, path) - elif type_ == TYPE_CACHE: + elif type_ == Type.CACHE: return os.path.join(self.cache_root, path) - elif type_ == TYPE_DATA: + elif type_ == Type.DATA: return os.path.join(self.data_root, path) return path @@ -145,26 +145,26 @@ class ConfigPaths: 'RNG_SEED': 'rng_seed'} for name in d: d[name] += profile - self.add(name, TYPE_DATA, windowsify(d[name])) + self.add(name, Type.DATA, windowsify(d[name])) if len(profile): - self.add('MY_DATA', TYPE_DATA, 'data.dir') + self.add('MY_DATA', Type.DATA, 'data.dir') else: - self.add('MY_DATA', TYPE_DATA, '') + self.add('MY_DATA', Type.DATA, '') d = {'CACHE_DB': 'cache.db', 'VCARD': 'vcards', 'AVATAR': 'avatars'} for name in d: d[name] += profile - self.add(name, TYPE_CACHE, windowsify(d[name])) + self.add(name, Type.CACHE, windowsify(d[name])) if len(profile): - self.add('MY_CACHE', TYPE_CACHE, 'cache.dir') + self.add('MY_CACHE', Type.CACHE, 'cache.dir') else: - self.add('MY_CACHE', TYPE_CACHE, '') + self.add('MY_CACHE', Type.CACHE, '') if len(profile): - self.add('MY_CONFIG', TYPE_CONFIG, 'config.dir') + self.add('MY_CONFIG', Type.CONFIG, 'config.dir') else: - self.add('MY_CONFIG', TYPE_CONFIG, '') + self.add('MY_CONFIG', Type.CONFIG, '') try: self.add('TMP', None, tempfile.gettempdir()) @@ -187,10 +187,10 @@ class ConfigPaths: certsdir += u'.' + profile localcertsdir += u'.' + profile - self.add('SECRETS_FILE', TYPE_DATA, secretsfile) - self.add('MY_PEER_CERTS', TYPE_DATA, certsdir) - self.add('CONFIG_FILE', TYPE_CONFIG, conffile) - self.add('PLUGINS_CONFIG_DIR', TYPE_CONFIG, pluginsconfdir) - self.add('MY_CERT', TYPE_CONFIG, localcertsdir) + self.add('SECRETS_FILE', Type.DATA, secretsfile) + self.add('MY_PEER_CERTS', Type.DATA, certsdir) + self.add('CONFIG_FILE', Type.CONFIG, conffile) + self.add('PLUGINS_CONFIG_DIR', Type.CONFIG, pluginsconfdir) + self.add('MY_CERT', Type.CONFIG, localcertsdir) gajimpaths = ConfigPaths() diff --git a/src/common/connection_handlers_events.py b/src/common/connection_handlers_events.py index d7b0d19fb..c8287020f 100644 --- a/src/common/connection_handlers_events.py +++ b/src/common/connection_handlers_events.py @@ -35,6 +35,7 @@ import nbxmpp from common import dataforms from common import exceptions from common.zeroconf import zeroconf +from common.zeroconf.zeroconf import Constant from common.logger import LOG_DB_PATH from common.pep import SUPPORTED_PERSONAL_USER_EVENTS from nbxmpp.protocol import NS_CHATSTATES @@ -1328,7 +1329,7 @@ class ZeroconfMessageReceivedEvent(MessageReceivedEvent): if self.fjid is None: for key in self.conn.connection.zeroconf.contacts: if self.ip == self.conn.connection.zeroconf.contacts[key][ - zeroconf.C_ADDRESS]: + Constant.ADDRESS]: self.fjid = key break diff --git a/src/common/jingle_transport.py b/src/common/jingle_transport.py index ffd26bae9..29073e766 100644 --- a/src/common/jingle_transport.py +++ b/src/common/jingle_transport.py @@ -21,6 +21,7 @@ import nbxmpp import socket from common import gajim import logging +from enum import IntEnum log = logging.getLogger('gajim.c.jingle_transport') @@ -33,7 +34,7 @@ def get_jingle_transport(node): return transports[namespace](node) -class TransportType(object): +class TransportType(IntEnum): """ Possible types of a JingleTransport """ diff --git a/src/common/logger.py b/src/common/logger.py index 204734ea3..1a8781728 100644 --- a/src/common/logger.py +++ b/src/common/logger.py @@ -36,6 +36,7 @@ import json from gzip import GzipFile from io import BytesIO from gi.repository import GLib +from enum import IntEnum from common import exceptions from common import gajim @@ -50,59 +51,50 @@ CACHE_DB_PATH = gajim.gajimpaths['CACHE_DB'] import logging log = logging.getLogger('gajim.c.logger') -class Constants: - def __init__(self): - ( - self.JID_NORMAL_TYPE, - self.JID_ROOM_TYPE - ) = range(2) +class JIDConstant(IntEnum): + NORMAL_TYPE = 0 + ROOM_TYPE = 1 - ( - self.KIND_STATUS, - self.KIND_GCSTATUS, - self.KIND_GC_MSG, - self.KIND_SINGLE_MSG_RECV, - self.KIND_CHAT_MSG_RECV, - self.KIND_SINGLE_MSG_SENT, - self.KIND_CHAT_MSG_SENT, - self.KIND_ERROR - ) = range(8) +class KindConstant(IntEnum): + STATUS = 0 + GCSTATUS = 1 + GC_MSG = 2 + SINGLE_MSG_RECV = 3 + CHAT_MSG_RECV = 4 + SINGLE_MSG_SENT = 5 + CHAT_MSG_SENT = 6 + ERROR = 7 - ( - self.SHOW_ONLINE, - self.SHOW_CHAT, - self.SHOW_AWAY, - self.SHOW_XA, - self.SHOW_DND, - self.SHOW_OFFLINE - ) = range(6) +class ShowConstant(IntEnum): + ONLINE = 0 + CHAT = 1 + AWAY = 2 + XA = 3 + DND = 4 + OFFLINE = 5 - ( - self.TYPE_AIM, - self.TYPE_GG, - self.TYPE_HTTP_WS, - self.TYPE_ICQ, - self.TYPE_MSN, - self.TYPE_QQ, - self.TYPE_SMS, - self.TYPE_SMTP, - self.TYPE_TLEN, - self.TYPE_YAHOO, - self.TYPE_NEWMAIL, - self.TYPE_RSS, - self.TYPE_WEATHER, - self.TYPE_MRIM, - self.TYPE_NO_TRANSPORT, - ) = range(15) +class TypeConstant(IntEnum): + AIM = 0 + GG = 1 + HTTP_WS = 2 + ICQ = 3 + MSN = 4 + QQ = 5 + SMS = 6 + SMTP = 7 + TLEN = 8 + YAHOO = 9 + NEWMAIL = 10 + RSS = 11 + WEATHER = 12 + MRIM = 13 + NO_TRANSPORT = 14 - ( - self.SUBSCRIPTION_NONE, - self.SUBSCRIPTION_TO, - self.SUBSCRIPTION_FROM, - self.SUBSCRIPTION_BOTH, - ) = range(4) - -constants = Constants() +class SubscriptionConstant(IntEnum): + NONE = 0 + TO = 1 + FROM = 2 + BOTH = 3 class Logger: def __init__(self): @@ -231,7 +223,7 @@ class Logger: if row is None: return None else: - if row[0] == constants.JID_ROOM_TYPE: + if row[0] == JIDConstant.ROOM_TYPE: return True return False @@ -255,9 +247,9 @@ class Logger: return row[0] # oh! a new jid :), we add it now if typestr == 'ROOM': - typ = constants.JID_ROOM_TYPE + typ = JIDConstant.ROOM_TYPE else: - typ = constants.JID_NORMAL_TYPE + typ = JIDConstant.NORMAL_TYPE try: self.cur.execute('INSERT INTO jids (jid, type) VALUES (?, ?)', (jid, typ)) @@ -277,34 +269,34 @@ class Logger: Convert from string style to constant ints for db """ if kind == 'status': - kind_col = constants.KIND_STATUS + kind_col = KindConstant.STATUS elif kind == 'gcstatus': - kind_col = constants.KIND_GCSTATUS + kind_col = KindConstant.GCSTATUS elif kind == 'gc_msg': - kind_col = constants.KIND_GC_MSG + kind_col = KindConstant.GC_MSG elif kind == 'single_msg_recv': - kind_col = constants.KIND_SINGLE_MSG_RECV + kind_col = KindConstant.SINGLE_MSG_RECV elif kind == 'single_msg_sent': - kind_col = constants.KIND_SINGLE_MSG_SENT + kind_col = KindConstant.SINGLE_MSG_SENT elif kind == 'chat_msg_recv': - kind_col = constants.KIND_CHAT_MSG_RECV + kind_col = KindConstant.CHAT_MSG_RECV elif kind == 'chat_msg_sent': - kind_col = constants.KIND_CHAT_MSG_SENT + kind_col = KindConstant.CHAT_MSG_SENT elif kind == 'error': - kind_col = constants.KIND_ERROR + kind_col = KindConstant.ERROR if show == 'online': - show_col = constants.SHOW_ONLINE + show_col = ShowConstant.ONLINE elif show == 'chat': - show_col = constants.SHOW_CHAT + show_col = ShowConstant.CHAT elif show == 'away': - show_col = constants.SHOW_AWAY + show_col = ShowConstant.AWAY elif show == 'xa': - show_col = constants.SHOW_XA + show_col = ShowConstant.XA elif show == 'dnd': - show_col = constants.SHOW_DND + show_col = ShowConstant.DND elif show == 'offline': - show_col = constants.SHOW_OFFLINE + show_col = ShowConstant.OFFLINE elif show is None: show_col = None else: # invisible in GC when someone goes invisible @@ -318,70 +310,70 @@ class Logger: Convert from string style to constant ints for db """ if type_ == 'aim': - return constants.TYPE_AIM + return TypeConstant.AIM if type_ == 'gadu-gadu': - return constants.TYPE_GG + return TypeConstant.GG if type_ == 'http-ws': - return constants.TYPE_HTTP_WS + return TypeConstant.HTTP_WS if type_ == 'icq': - return constants.TYPE_ICQ + return TypeConstant.ICQ if type_ == 'msn': - return constants.TYPE_MSN + return TypeConstant.MSN if type_ == 'qq': - return constants.TYPE_QQ + return TypeConstant.QQ if type_ == 'sms': - return constants.TYPE_SMS + return TypeConstant.SMS if type_ == 'smtp': - return constants.TYPE_SMTP + return TypeConstant.SMTP if type_ in ('tlen', 'x-tlen'): - return constants.TYPE_TLEN + return TypeConstant.TLEN if type_ == 'yahoo': - return constants.TYPE_YAHOO + return TypeConstant.YAHOO if type_ == 'newmail': - return constants.TYPE_NEWMAIL + return TypeConstant.NEWMAIL if type_ == 'rss': - return constants.TYPE_RSS + return TypeConstant.RSS if type_ == 'weather': - return constants.TYPE_WEATHER + return TypeConstant.WEATHER if type_ == 'mrim': - return constants.TYPE_MRIM + return TypeConstant.MRIM if type_ == 'jabber': - return constants.TYPE_NO_TRANSPORT + return TypeConstant.NO_TRANSPORT return None def convert_api_values_to_human_transport_type(self, type_id): """ Convert from constant ints for db to string style """ - if type_id == constants.TYPE_AIM: + if type_id == TypeConstant.AIM: return 'aim' - if type_id == constants.TYPE_GG: + if type_id == TypeConstant.GG: return 'gadu-gadu' - if type_id == constants.TYPE_HTTP_WS: + if type_id == TypeConstant.HTTP_WS: return 'http-ws' - if type_id == constants.TYPE_ICQ: + if type_id == TypeConstant.ICQ: return 'icq' - if type_id == constants.TYPE_MSN: + if type_id == TypeConstant.MSN: return 'msn' - if type_id == constants.TYPE_QQ: + if type_id == TypeConstant.QQ: return 'qq' - if type_id == constants.TYPE_SMS: + if type_id == TypeConstant.SMS: return 'sms' - if type_id == constants.TYPE_SMTP: + if type_id == TypeConstant.SMTP: return 'smtp' - if type_id == constants.TYPE_TLEN: + if type_id == TypeConstant.TLEN: return 'tlen' - if type_id == constants.TYPE_YAHOO: + if type_id == TypeConstant.YAHOO: return 'yahoo' - if type_id == constants.TYPE_NEWMAIL: + if type_id == TypeConstant.NEWMAIL: return 'newmail' - if type_id == constants.TYPE_RSS: + if type_id == TypeConstant.RSS: return 'rss' - if type_id == constants.TYPE_WEATHER: + if type_id == TypeConstant.WEATHER: return 'weather' - if type_id == constants.TYPE_MRIM: + if type_id == TypeConstant.MRIM: return 'mrim' - if type_id == constants.TYPE_NO_TRANSPORT: + if type_id == TypeConstant.NO_TRANSPORT: return 'jabber' def convert_human_subscription_values_to_db_api_values(self, sub): @@ -389,25 +381,25 @@ class Logger: Convert from string style to constant ints for db """ if sub == 'none': - return constants.SUBSCRIPTION_NONE + return SubscriptionConstant.NONE if sub == 'to': - return constants.SUBSCRIPTION_TO + return SubscriptionConstant.TO if sub == 'from': - return constants.SUBSCRIPTION_FROM + return SubscriptionConstant.FROM if sub == 'both': - return constants.SUBSCRIPTION_BOTH + return SubscriptionConstant.BOTH def convert_db_api_values_to_human_subscription_values(self, sub): """ Convert from constant ints for db to string style """ - if sub == constants.SUBSCRIPTION_NONE: + if sub == SubscriptionConstant.NONE: return 'none' - if sub == constants.SUBSCRIPTION_TO: + if sub == SubscriptionConstant.TO: return 'to' - if sub == constants.SUBSCRIPTION_FROM: + if sub == SubscriptionConstant.FROM: return 'from' - if sub == constants.SUBSCRIPTION_BOTH: + if sub == SubscriptionConstant.BOTH: return 'both' def commit_to_db(self, values, write_unread=False): @@ -539,12 +531,12 @@ class Logger: except exceptions.PysqliteOperationalError as e: raise exceptions.PysqliteOperationalError(str(e)) if show is None: # show is None (xmpp), but we say that 'online' - show_col = constants.SHOW_ONLINE + show_col = ShowConstant.ONLINE elif kind == 'gcstatus': # status in ROOM (for pm status see status) if show is None: # show is None (xmpp), but we say that 'online' - show_col = constants.SHOW_ONLINE + show_col = ShowConstant.ONLINE jid, nick = jid.split('/', 1) try: # re-get jid_id for the new jid @@ -608,9 +600,9 @@ class Logger: SELECT time, kind, message, subject, additional_data FROM logs WHERE (%s) AND kind IN (%d, %d, %d, %d, %d) AND time > %d ORDER BY time DESC LIMIT %d OFFSET %d - ''' % (where_sql, constants.KIND_SINGLE_MSG_RECV, - constants.KIND_CHAT_MSG_RECV, constants.KIND_SINGLE_MSG_SENT, - constants.KIND_CHAT_MSG_SENT, constants.KIND_ERROR, timed_out, + ''' % (where_sql, KindConstant.SINGLE_MSG_RECV, + KindConstant.CHAT_MSG_RECV, KindConstant.SINGLE_MSG_SENT, + KindConstant.CHAT_MSG_SENT, KindConstant.ERROR, timed_out, restore_how_many_rows, pending_how_many), jid_tuple) results = self.cur.fetchall() @@ -736,7 +728,7 @@ class Logger: AND kind NOT IN (%d, %d) ORDER BY time ''' % (where_sql, start_of_month, last_second_of_month, - constants.KIND_STATUS, constants.KIND_GCSTATUS), jid_tuple) + KindConstant.STATUS, KindConstant.GCSTATUS), jid_tuple) result = self.cur.fetchall() # convert timestamps to day of month @@ -765,7 +757,7 @@ class Logger: SELECT MAX(time) FROM logs WHERE (%s) AND kind NOT IN (%d, %d) - ''' % (where_sql, constants.KIND_STATUS, constants.KIND_GCSTATUS), + ''' % (where_sql, KindConstant.STATUS, KindConstant.GCSTATUS), jid_tuple) results = self.cur.fetchone() diff --git a/src/common/zeroconf/roster_zeroconf.py b/src/common/zeroconf/roster_zeroconf.py index ac88e9565..eeb5c8991 100644 --- a/src/common/zeroconf/roster_zeroconf.py +++ b/src/common/zeroconf/roster_zeroconf.py @@ -19,6 +19,7 @@ from common.zeroconf import zeroconf +from common.zeroconf.zeroconf import Constant, ConstantRI class Roster: def __init__(self, zeroconf): @@ -29,7 +30,7 @@ class Roster: def update_roster(self): for val in self.zeroconf.contacts.values(): - self.setItem(val[zeroconf.C_NAME]) + self.setItem(val[Constant.NAME]) def getRoster(self): if self._data is None: @@ -58,13 +59,13 @@ class Roster: addresses = [] i = 0 - for ri in contact[zeroconf.C_RESOLVED_INFO]: + for ri in contact[Constant.RESOLVED_INFO]: addresses += [{}] - addresses[i]['host'] = ri[zeroconf.C_RI_HOST] - addresses[i]['address'] = ri[zeroconf.C_RI_ADDRESS] - addresses[i]['port'] = ri[zeroconf.C_RI_PORT] + addresses[i]['host'] = ri[ConstantRI.HOST] + addresses[i]['address'] = ri[ConstantRI.ADDRESS] + addresses[i]['port'] = ri[ConstantRI.PORT] i += 1 - txt = contact[zeroconf.C_TXT] + txt = contact[Constant.TXT] self._data[jid]={} self._data[jid]['ask'] = 'none' diff --git a/src/common/zeroconf/zeroconf.py b/src/common/zeroconf/zeroconf.py index 377f8271f..1f8c28890 100644 --- a/src/common/zeroconf/zeroconf.py +++ b/src/common/zeroconf/zeroconf.py @@ -17,8 +17,22 @@ ## along with Gajim. If not, see . ## -C_NAME, C_DOMAIN, C_RESOLVED_INFO, C_BARE_NAME, C_TXT = range(5) -C_RI_INTERFACE, C_RI_PROTOCOL, C_RI_HOST, C_RI_APROTOCOL, C_RI_ADDRESS, C_RI_PORT = range(6) +from enum import IntEnum + +class Constant(IntEnum): + NAME = 0 + DOMAIN = 1 + RESOLVED_INFO = 2 + BARE_NAME = 3 + TXT = 4 + +class ConstantRI(IntEnum): + INTERFACE = 0 + PROTOCOL = 1 + HOST = 2 + APROTOCOL = 3 + ADDRESS = 4 + PORT = 5 def test_avahi(): try: diff --git a/src/common/zeroconf/zeroconf_avahi.py b/src/common/zeroconf/zeroconf_avahi.py index 497a0c374..51bad907e 100644 --- a/src/common/zeroconf/zeroconf_avahi.py +++ b/src/common/zeroconf/zeroconf_avahi.py @@ -25,8 +25,7 @@ try: except ImportError: pass -from common.zeroconf.zeroconf import C_BARE_NAME, C_RESOLVED_INFO, \ -C_RI_INTERFACE, C_RI_PROTOCOL, C_DOMAIN, C_TXT +from common.zeroconf.zeroconf import Constant, ConstantRI class Zeroconf: def __init__(self, new_serviceCB, remove_serviceCB, name_conflictCB, @@ -95,15 +94,15 @@ class Zeroconf: if name != self.name: for key in self.contacts.keys(): val = self.contacts[key] - if val[C_BARE_NAME] == name: + if val[Constant.BARE_NAME] == name: # try to reduce instead of delete first - resolved_info = val[C_RESOLVED_INFO] + resolved_info = val[Constant.RESOLVED_INFO] if len(resolved_info) > 1: for i in range(len(resolved_info)): - if resolved_info[i][C_RI_INTERFACE] == interface and resolved_info[i][C_RI_PROTOCOL] == protocol: - del self.contacts[key][C_RESOLVED_INFO][i] + if resolved_info[i][ConstantRI.INTERFACE] == interface and resolved_info[i][ConstantRI.PROTOCOL] == protocol: + del self.contacts[key][Constant.RESOLVED_INFO][i] # if still something left, don't remove - if len(self.contacts[key][C_RESOLVED_INFO]) > 1: return + if len(self.contacts[key][Constant.RESOLVED_INFO]) > 1: return del self.contacts[key] self.remove_serviceCB(key) return @@ -201,7 +200,7 @@ class Zeroconf: name = name + '@' + name # update TXT data only, as intended according to resolve_all comment old_contact = self.contacts[name] - self.contacts[name] = old_contact[0:C_TXT] + (txt,) + old_contact[C_TXT+1:] + self.contacts[name] = old_contact[0:Constant.TXT] + (txt,) + old_contact[Constant.TXT+1:] def service_added_callback(self): log.debug('Service successfully added') @@ -450,9 +449,9 @@ class Zeroconf: for val in self.contacts.values(): # get txt data from last recorded resolved info # TODO: Better try to get it from last IPv6 mDNS, then last IPv4? - ri = val[C_RESOLVED_INFO][0] - self.server.ResolveService(int(ri[C_RI_INTERFACE]), int(ri[C_RI_PROTOCOL]), - val[C_BARE_NAME], self.stype, val[C_DOMAIN], + ri = val[Constant.RESOLVED_INFO][0] + self.server.ResolveService(int(ri[ConstantRI.INTERFACE]), int(ri[ConstantRI.PROTOCOL]), + val[Constant.BARE_NAME], self.stype, val[Constant.DOMAIN], self.avahi.PROTO_UNSPEC, dbus.UInt32(0), reply_handler=self.service_resolved_all_callback, error_handler=self.error_callback) diff --git a/src/common/zeroconf/zeroconf_bonjour.py b/src/common/zeroconf/zeroconf_bonjour.py index 0016429d9..f68d412dd 100644 --- a/src/common/zeroconf/zeroconf_bonjour.py +++ b/src/common/zeroconf/zeroconf_bonjour.py @@ -20,7 +20,7 @@ from common import gajim import select import re -from common.zeroconf.zeroconf import C_BARE_NAME, C_DOMAIN, C_TXT +from common.zeroconf.zeroconf import Constant try: import pybonjour @@ -86,7 +86,7 @@ class Zeroconf: return if name != self.name: for key in self.contacts.keys(): - if self.contacts[key][C_BARE_NAME] == name: + if self.contacts[key][Constant.BARE_NAME] == name: del self.contacts[key] self.remove_serviceCB(key) return @@ -171,7 +171,7 @@ class Zeroconf: if name != self.name: # update TXT data only, as intended according to resolve_all comment old_contact = self.contacts[name] - self.contacts[name] = old_contact[0:C_TXT] + (self.txt,) + old_contact[C_TXT+1:] + self.contacts[name] = old_contact[0:Constant.TXT] + (self.txt,) + old_contact[Constant.TXT+1:] def service_added_callback(self, sdRef, flags, errorCode, name, regtype, domain): @@ -303,8 +303,8 @@ class Zeroconf: for val in self.contacts.values(): resolve_sdRef = pybonjour.DNSServiceResolve(0, - pybonjour.kDNSServiceInterfaceIndexAny, val[C_BARE_NAME], - self.stype + '.', val[C_DOMAIN] + '.', + pybonjour.kDNSServiceInterfaceIndexAny, val[Constant.BARE_NAME], + self.stype + '.', val[Constant.DOMAIN] + '.', self.service_resolved_all_callback) try: diff --git a/src/filetransfers_window.py b/src/filetransfers_window.py index b27230803..e9055d804 100644 --- a/src/filetransfers_window.py +++ b/src/filetransfers_window.py @@ -29,6 +29,8 @@ from gi.repository import Pango import os import time +from enum import IntEnum + import gtkgui_helpers import tooltips import dialogs @@ -42,14 +44,15 @@ from nbxmpp.protocol import NS_JINGLE_FILE_TRANSFER import logging log = logging.getLogger('gajim.filetransfer_window') -C_IMAGE = 0 -C_LABELS = 1 -C_FILE = 2 -C_TIME = 3 -C_PROGRESS = 4 -C_PERCENT = 5 -C_PULSE = 6 -C_SID = 7 +class Column(IntEnum): + IMAGE = 0 + LABELS = 1 + FILE = 2 + TIME = 3 + PROGRESS = 4 + PERCENT = 5 + PULSE = 6 + SID = 7 class FileTransfersWindow: @@ -85,11 +88,11 @@ class FileTransfersWindow: col = Gtk.TreeViewColumn(_('File')) renderer = Gtk.CellRendererText() col.pack_start(renderer, False) - col.add_attribute(renderer, 'markup', C_LABELS) + col.add_attribute(renderer, 'markup', Column.LABELS) renderer.set_property('yalign', 0.) renderer = Gtk.CellRendererText() col.pack_start(renderer, True) - col.add_attribute(renderer, 'markup', C_FILE) + col.add_attribute(renderer, 'markup', Column.FILE) renderer.set_property('xalign', 0.) renderer.set_property('yalign', 0.) renderer.set_property('ellipsize', Pango.EllipsizeMode.END) @@ -100,7 +103,7 @@ class FileTransfersWindow: col = Gtk.TreeViewColumn(_('Time')) renderer = Gtk.CellRendererText() col.pack_start(renderer, False) - col.add_attribute(renderer, 'markup', C_TIME) + col.add_attribute(renderer, 'markup', Column.TIME) renderer.set_property('yalign', 0.5) renderer.set_property('xalign', 0.5) renderer = Gtk.CellRendererText() @@ -114,9 +117,9 @@ class FileTransfersWindow: renderer.set_property('yalign', 0.5) renderer.set_property('xalign', 0.5) col.pack_start(renderer, False) - col.add_attribute(renderer, 'text', C_PROGRESS) - col.add_attribute(renderer, 'value', C_PERCENT) - col.add_attribute(renderer, 'pulse', C_PULSE) + col.add_attribute(renderer, 'text', Column.PROGRESS) + col.add_attribute(renderer, 'value', Column.PERCENT) + col.add_attribute(renderer, 'pulse', Column.PULSE) col.set_resizable(True) col.set_expand(False) self.tree.append_column(col) @@ -480,7 +483,7 @@ class FileTransfersWindow: iter_ = self.get_iter_by_sid(file_props.type_, file_props.sid) if iter_ is None: return - self.model[iter_][C_SID] + self.model[iter_][Column.SID] if status == 'stop': file_props.stopped = True elif status == 'ok': @@ -490,21 +493,21 @@ class FileTransfersWindow: full_size = file_props.size text += helpers.convert_bytes(received_size) + '/' + \ helpers.convert_bytes(full_size) - self.model.set(iter_, C_PROGRESS, text) - self.model.set(iter_, C_PULSE, GLib.MAXINT32) + self.model.set(iter_, Column.PROGRESS, text) + self.model.set(iter_, Column.PULSE, GLib.MAXINT32) elif status == 'computing': - self.model.set(iter_, C_PULSE, 1) + self.model.set(iter_, Column.PULSE, 1) text = _('Checking file…') + '\n' received_size = int(file_props.received_len) full_size = file_props.size text += helpers.convert_bytes(received_size) + '/' + \ helpers.convert_bytes(full_size) - self.model.set(iter_, C_PROGRESS, text) + self.model.set(iter_, Column.PROGRESS, text) def pulse(): - p = self.model.get(iter_, C_PULSE)[0] + p = self.model.get(iter_, Column.PULSE)[0] if p == GLib.MAXINT32: return False - self.model.set(iter_, C_PULSE, p + 1) + self.model.set(iter_, Column.PULSE, p + 1) return True GLib.timeout_add(100, pulse) elif status == 'hash_error': @@ -513,9 +516,9 @@ class FileTransfersWindow: full_size = file_props.size text += helpers.convert_bytes(received_size) + '/' + \ helpers.convert_bytes(full_size) - self.model.set(iter_, C_PROGRESS, text) - self.model.set(iter_, C_PULSE, GLib.MAXINT32) - self.model.set(iter_, C_IMAGE, self.get_icon(status)) + self.model.set(iter_, Column.PROGRESS, text) + self.model.set(iter_, Column.PULSE, GLib.MAXINT32) + self.model.set(iter_, Column.IMAGE, self.get_icon(status)) path = self.model.get_path(iter_) self.select_func(path) @@ -609,7 +612,7 @@ class FileTransfersWindow: iter_ = self.get_iter_by_sid(typ, sid) if iter_ is not None: just_began = False - if self.model[iter_][C_PERCENT] == 0 and int(percent > 0): + if self.model[iter_][Column.PERCENT] == 0 and int(percent > 0): just_began = True text = self._format_percent(percent) if transfered_size == 0: @@ -631,8 +634,8 @@ class FileTransfersWindow: eta, speed = self._get_eta_and_speed(full_size, transfered_size, file_props) - self.model.set(iter_, C_PROGRESS, text) - self.model.set(iter_, C_PERCENT, int(percent)) + self.model.set(iter_, Column.PROGRESS, text) + self.model.set(iter_, Column.PERCENT, int(percent)) text = self._format_time(eta) text += '\n' #This should make the string Kb/s, @@ -640,7 +643,7 @@ class FileTransfersWindow: #Only the 's' after / (which means second) should be translated. text += _('(%(filesize_unit)s/s)') % {'filesize_unit': helpers.convert_bytes(speed)} - self.model.set(iter_, C_TIME, text) + self.model.set(iter_, Column.TIME, text) # try to guess what should be the status image if file_props.type_ == 'r': @@ -673,7 +676,7 @@ class FileTransfersWindow: """ iter_ = self.model.get_iter_first() while iter_: - if typ + sid == self.model[iter_][C_SID]: + if typ + sid == self.model[iter_][Column.SID]: return iter_ iter_ = self.model.iter_next(iter_) @@ -736,7 +739,7 @@ class FileTransfersWindow: file_name = file_props.name text_props = GLib.markup_escape_text(file_name) + '\n' text_props += contact.get_shown_name() - self.model.set(iter_, 1, text_labels, 2, text_props, C_PULSE, -1, C_SID, + self.model.set(iter_, 1, text_labels, 2, text_props, Column.PULSE, -1, Column.SID, file_props.type_ + file_props.sid) self.set_progress(file_props.type_, file_props.sid, 0, iter_) if file_props.started is False: @@ -767,7 +770,7 @@ class FileTransfersWindow: except Exception: self.tooltip.hide_tooltip() return - sid = self.model[iter_][C_SID] + sid = self.model[iter_][Column.SID] file_props = FilesProp.getFilePropByType(sid[0], sid[1:]) if file_props is not None: if self.tooltip.timeout == 0 or self.tooltip.id != props[0]: @@ -825,7 +828,7 @@ class FileTransfersWindow: self.set_all_insensitive() return current_iter = self.model.get_iter(path) - sid = self.model[current_iter][C_SID] + sid = self.model[current_iter][Column.SID] file_props = FilesProp.getFilePropByType(sid[0], sid[1:]) self.remove_menuitem.set_sensitive(is_row_selected) self.open_folder_menuitem.set_sensitive(is_row_selected) @@ -883,7 +886,7 @@ class FileTransfersWindow: i = len(self.model) - 1 while i >= 0: iter_ = self.model.get_iter((i)) - sid = self.model[iter_][C_SID] + sid = self.model[iter_][Column.SID] file_props = FilesProp.getFilePropByType(sid[0], sid[1:]) if is_transfer_stopped(file_props): self._remove_transfer(iter_, sid, file_props) @@ -918,7 +921,7 @@ class FileTransfersWindow: if selected is None or selected[1] is None: return s_iter = selected[1] - sid = self.model[s_iter][C_SID] + sid = self.model[s_iter][Column.SID] file_props = FilesProp.getFilePropByType(sid[0], sid[1:]) if is_transfer_paused(file_props): file_props.last_time = time.time() @@ -940,7 +943,7 @@ class FileTransfersWindow: if selected is None or selected[1] is None: return s_iter = selected[1] - sid = self.model[s_iter][C_SID] + sid = self.model[s_iter][Column.SID] file_props = FilesProp.getFilePropByType(sid[0], sid[1:]) account = file_props.tt_account if account not in gajim.connections: @@ -966,7 +969,7 @@ class FileTransfersWindow: # as it was before setting the timeout if props and self.tooltip.id == props[0]: iter_ = self.model.get_iter(props[0]) - sid = self.model[iter_][C_SID] + sid = self.model[iter_][Column.SID] file_props = FilesProp.getFilePropByType(sid[0], sid[1:]) # bounding rectangle of coordinates for the cell within the treeview rect = self.tree.get_cell_area(props[0], props[1]) @@ -1054,7 +1057,7 @@ class FileTransfersWindow: if not selected or not selected[1]: return s_iter = selected[1] - sid = self.model[s_iter][C_SID] + sid = self.model[s_iter][Column.SID] file_props = FilesProp.getFilePropByType(sid[0], sid[1:]) if not file_props.file_name: return @@ -1076,7 +1079,7 @@ class FileTransfersWindow: if not selected or not selected[1]: return s_iter = selected[1] - sid = self.model[s_iter][C_SID] + sid = self.model[s_iter][Column.SID] file_props = FilesProp.getFilePropByType(sid[0], sid[1:]) self._remove_transfer(s_iter, sid, file_props) self.set_all_insensitive() diff --git a/src/groupchat_control.py b/src/groupchat_control.py index bf4a72c6a..cefd1747a 100644 --- a/src/groupchat_control.py +++ b/src/groupchat_control.py @@ -46,6 +46,8 @@ import cell_renderer_image import dataforms_widget import nbxmpp +from enum import IntEnum + from common import events from common import gajim from common import helpers @@ -63,14 +65,12 @@ from common.connection_handlers_events import GcMessageOutgoingEvent import logging log = logging.getLogger('gajim.groupchat_control') -#(status_image, type, nick, shown_nick) -( -C_IMG, # image to show state (online, new message etc) -C_NICK, # contact nickame or ROLE name -C_TYPE, # type of the row ('contact' or 'role') -C_TEXT, # text shown in the cellrenderer -C_AVATAR, # avatar of the contact -) = range(5) +class Column(IntEnum): + IMG = 0 # image to show state (online, new message etc) + NICK = 1 # contact nickame or ROLE name + TYPE = 2 # type of the row ('contact' or 'role') + TEXT = 3 # text shown in the cellrenderer + AVATAR = 4 # avatar of the contact empty_pixbuf = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, 1, 1) empty_pixbuf.fill(0xffffff00) @@ -99,7 +99,7 @@ def tree_cell_data_func(column, renderer, model, iter_, tv=None): renderer.set_property('xalign', 1) # align pixbuf to the right else: renderer.set_property('xalign', 0.5) - if parent_iter and (model[iter_][C_AVATAR] or avatar_position == \ + if parent_iter and (model[iter_][Column.AVATAR] or avatar_position == \ 'left'): renderer.set_property('visible', True) renderer.set_property('width', gajim.config.get( @@ -448,8 +448,8 @@ class GroupchatControl(ChatControlBase): #status_image, shown_nick, type, nickname, avatar self.columns = [Gtk.Image, str, str, str, GdkPixbuf.Pixbuf] self.model = Gtk.TreeStore(*self.columns) - self.model.set_sort_func(C_NICK, self.tree_compare_iters) - self.model.set_sort_column_id(C_NICK, Gtk.SortType.ASCENDING) + self.model.set_sort_func(Column.NICK, self.tree_compare_iters) + self.model.set_sort_column_id(Column.NICK, Gtk.SortType.ASCENDING) # columns column = Gtk.TreeViewColumn() @@ -469,14 +469,14 @@ class GroupchatControl(ChatControlBase): self.renderers_list += ( # status img ('icon', renderer_image, False, - 'image', C_IMG, tree_cell_data_func, self.list_treeview), + 'image', Column.IMG, tree_cell_data_func, self.list_treeview), # contact name ('name', renderer_text, True, - 'markup', C_TEXT, tree_cell_data_func, self.list_treeview)) + 'markup', Column.TEXT, tree_cell_data_func, self.list_treeview)) # avatar img avater_renderer = ('avatar', Gtk.CellRendererPixbuf(), - False, 'pixbuf', C_AVATAR, + False, 'pixbuf', Column.AVATAR, tree_cell_data_func, self.list_treeview) if gajim.config.get('avatar_position_in_roster') == 'right': @@ -549,8 +549,8 @@ class GroupchatControl(ChatControlBase): except Exception: return False - typ = self.model[iter_][C_TYPE] - nick = self.model[iter_][C_NICK] + typ = self.model[iter_][Column.TYPE] + nick = self.model[iter_][Column.NICK] if typ != 'contact': return False @@ -589,12 +589,12 @@ class GroupchatControl(ChatControlBase): """ Compare two iters to sort them """ - type1 = model[iter1][C_TYPE] - type2 = model[iter2][C_TYPE] + type1 = model[iter1][Column.TYPE] + type2 = model[iter2][Column.TYPE] if not type1 or not type2: return 0 - nick1 = model[iter1][C_NICK] - nick2 = model[iter2][C_NICK] + nick1 = model[iter1][Column.NICK] + nick2 = model[iter2][Column.NICK] if not nick1 or not nick2: return 0 if type1 == 'role': @@ -700,7 +700,7 @@ class GroupchatControl(ChatControlBase): """ # Get the room_jid from treeview for contact in self.iter_contact_rows(): - nick = contact[C_NICK] + nick = contact[Column.NICK] self.draw_contact(nick) def on_list_treeview_selection_changed(self, selection): @@ -712,9 +712,9 @@ class GroupchatControl(ChatControlBase): self._last_selected_contact = None return contact = model[selected_iter] - nick = contact[C_NICK] + nick = contact[Column.NICK] self._last_selected_contact = nick - if contact[C_TYPE] != 'contact': + if contact[Column.TYPE] != 'contact': return self.draw_contact(nick, selected=True, focus=True) @@ -782,7 +782,7 @@ class GroupchatControl(ChatControlBase): self.draw_contact(nick) def _change_style(self, model, path, iter_, option): - model[iter_][C_NICK] = model[iter_][C_NICK] + model[iter_][Column.NICK] = model[iter_][Column.NICK] def change_roster_style(self): self.model.foreach(self._change_style, None) @@ -1100,7 +1100,7 @@ class GroupchatControl(ChatControlBase): gajim.interface.roster.get_appropriate_state_images( self.room_jid, icon_name='event') image = state_images['event'] - self.model[iter_][C_IMG] = image + self.model[iter_][Column.IMG] = image if self.parent_win: self.parent_win.show_title() self.parent_win.redraw_tab(self) @@ -1122,7 +1122,7 @@ class GroupchatControl(ChatControlBase): while role_iter: user_iter = self.model.iter_children(role_iter) while user_iter: - if nick == self.model[user_iter][C_NICK]: + if nick == self.model[user_iter][Column.NICK]: return user_iter else: user_iter = self.model.iter_next(user_iter) @@ -1486,7 +1486,7 @@ class GroupchatControl(ChatControlBase): contact in a room """ if nick is None: - nick = model[iter_][C_NICK] + nick = model[iter_][Column.NICK] ctrl = self._start_private_message(nick) if ctrl and msg: @@ -1548,8 +1548,8 @@ class GroupchatControl(ChatControlBase): pixbuf2.get_property('height'), 0, 0, 1.0, 1.0, GdkPixbuf.InterpType.HYPER, 127) image = Gtk.Image.new_from_pixbuf(pixbuf1) - self.model[iter_][C_IMG] = image - self.model[iter_][C_TEXT] = name + self.model[iter_][Column.IMG] = image + self.model[iter_][Column.TEXT] = name def draw_avatar(self, nick): if not gajim.config.get('show_avatars_in_roster'): @@ -1565,7 +1565,7 @@ class GroupchatControl(ChatControlBase): scaled_pixbuf = gtkgui_helpers.get_scaled_pixbuf(pixbuf, 'roster') if not scaled_pixbuf: scaled_pixbuf = empty_pixbuf - self.model[iter_][C_AVATAR] = scaled_pixbuf + self.model[iter_][Column.AVATAR] = scaled_pixbuf def draw_role(self, role): role_iter = self.get_role_iter(role) @@ -1576,7 +1576,7 @@ class GroupchatControl(ChatControlBase): nbr_role, nbr_total = gajim.contacts.get_nb_role_total_gc_contacts( self.account, self.room_jid, role) role_name += ' (%s/%s)' % (repr(nbr_role), repr(nbr_total)) - self.model[role_iter][C_TEXT] = role_name + self.model[role_iter][Column.TEXT] = role_name def draw_all_roles(self): for role in ('visitor', 'participant', 'moderator'): @@ -1967,7 +1967,7 @@ class GroupchatControl(ChatControlBase): def get_role_iter(self, role): role_iter = self.model.get_iter_first() while role_iter: - role_name = self.model[role_iter][C_NICK] + role_name = self.model[role_iter][Column.NICK] if role == role_name: return role_iter role_iter = self.model.iter_next(role_iter) @@ -2429,7 +2429,7 @@ class GroupchatControl(ChatControlBase): """ model = widget.get_model() image = gajim.interface.jabber_state_images['16']['opened'] - model[iter_][C_IMG] = image + model[iter_][Column.IMG] = image def on_list_treeview_row_collapsed(self, widget, iter_, path): """ @@ -2437,7 +2437,7 @@ class GroupchatControl(ChatControlBase): """ model = widget.get_model() image = gajim.interface.jabber_state_images['16']['closed'] - model[iter_][C_IMG] = image + model[iter_][Column.IMG] = image def kick(self, widget, nick): """ @@ -2456,7 +2456,7 @@ class GroupchatControl(ChatControlBase): """ Make contact's popup menu """ - nick = self.model[iter_][C_NICK] + nick = self.model[iter_][Column.NICK] c = gajim.contacts.get_gc_contact(self.account, self.room_jid, nick) fjid = self.room_jid + '/' + nick jid = c.jid @@ -2619,7 +2619,7 @@ class GroupchatControl(ChatControlBase): else: widget.expand_row(path, False) else: # We want to send a private message - nick = self.model[path][C_NICK] + nick = self.model[path][Column.NICK] self._start_private_message(nick) def on_list_treeview_row_activated(self, widget, path, col=0): @@ -2650,7 +2650,7 @@ class GroupchatControl(ChatControlBase): widget.get_selection().select_path(path) iter_ = self.model.get_iter(path) if path.get_depth() == 2: - nick = self.model[iter_][C_NICK] + nick = self.model[iter_][Column.NICK] self._start_private_message(nick) return True @@ -2660,7 +2660,7 @@ class GroupchatControl(ChatControlBase): return True else: iter_ = self.model.get_iter(path) - nick = self.model[iter_][C_NICK] + nick = self.model[iter_][Column.NICK] if not nick in gajim.contacts.get_nick_list(self.account, self.room_jid): # it's a group diff --git a/src/history_manager.py b/src/history_manager.py index 873f32cea..8786a11db 100644 --- a/src/history_manager.py +++ b/src/history_manager.py @@ -99,13 +99,13 @@ status = dict((constants.__dict__[i], i[5:].lower()) for i in \ from common import helpers import dialogs -# time, message, subject -( -C_UNIXTIME, -C_MESSAGE, -C_SUBJECT, -C_NICKNAME -) = range(2, 6) +from enum import IntEnum + +class Column(IntEnum): + UNIXTIME = 2 + MESSAGE = 3 + SUBJECT = 4 + NICKNAME = 5 import sqlite3 as sqlite @@ -176,32 +176,32 @@ class HistoryManager: self.logs_listview.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE) renderer_text = Gtk.CellRendererText() # holds time - col = Gtk.TreeViewColumn(_('Date'), renderer_text, text=C_UNIXTIME) + col = Gtk.TreeViewColumn(_('Date'), renderer_text, text=Column.UNIXTIME) # user can click this header and sort - col.set_sort_column_id(C_UNIXTIME) + col.set_sort_column_id(Column.UNIXTIME) col.set_resizable(True) self.logs_listview.append_column(col) renderer_text = Gtk.CellRendererText() # holds nickname - col = Gtk.TreeViewColumn(_('Nickname'), renderer_text, text=C_NICKNAME) + col = Gtk.TreeViewColumn(_('Nickname'), renderer_text, text=Column.NICKNAME) # user can click this header and sort - col.set_sort_column_id(C_NICKNAME) + col.set_sort_column_id(Column.NICKNAME) col.set_resizable(True) col.set_visible(False) self.nickname_col_for_logs = col self.logs_listview.append_column(col) renderer_text = Gtk.CellRendererText() # holds message - col = Gtk.TreeViewColumn(_('Message'), renderer_text, markup=C_MESSAGE) + col = Gtk.TreeViewColumn(_('Message'), renderer_text, markup=Column.MESSAGE) # user can click this header and sort - col.set_sort_column_id(C_MESSAGE) + col.set_sort_column_id(Column.MESSAGE) col.set_resizable(True) self.message_col_for_logs = col self.logs_listview.append_column(col) renderer_text = Gtk.CellRendererText() # holds subject - col = Gtk.TreeViewColumn(_('Subject'), renderer_text, text=C_SUBJECT) - col.set_sort_column_id(C_SUBJECT) # user can click this header and sort + col = Gtk.TreeViewColumn(_('Subject'), renderer_text, text=Column.SUBJECT) + col.set_sort_column_id(Column.SUBJECT) # user can click this header and sort col.set_resizable(True) col.set_visible(False) self.subject_col_for_logs = col @@ -220,28 +220,28 @@ class HistoryManager: self.search_results_listview.append_column(col) renderer_text = Gtk.CellRendererText() # holds time - col = Gtk.TreeViewColumn(_('Date'), renderer_text, text=C_UNIXTIME) + col = Gtk.TreeViewColumn(_('Date'), renderer_text, text=Column.UNIXTIME) # user can click this header and sort - col.set_sort_column_id(C_UNIXTIME) + col.set_sort_column_id(Column.UNIXTIME) col.set_resizable(True) self.search_results_listview.append_column(col) renderer_text = Gtk.CellRendererText() # holds message - col = Gtk.TreeViewColumn(_('Message'), renderer_text, text=C_MESSAGE) - col.set_sort_column_id(C_MESSAGE) # user can click this header and sort + col = Gtk.TreeViewColumn(_('Message'), renderer_text, text=Column.MESSAGE) + col.set_sort_column_id(Column.MESSAGE) # user can click this header and sort col.set_resizable(True) self.search_results_listview.append_column(col) renderer_text = Gtk.CellRendererText() # holds subject - col = Gtk.TreeViewColumn(_('Subject'), renderer_text, text=C_SUBJECT) - col.set_sort_column_id(C_SUBJECT) # user can click this header and sort + col = Gtk.TreeViewColumn(_('Subject'), renderer_text, text=Column.SUBJECT) + col.set_sort_column_id(Column.SUBJECT) # user can click this header and sort col.set_resizable(True) self.search_results_listview.append_column(col) renderer_text = Gtk.CellRendererText() # holds nickname - col = Gtk.TreeViewColumn(_('Nickname'), renderer_text, text=C_NICKNAME) + col = Gtk.TreeViewColumn(_('Nickname'), renderer_text, text=Column.NICKNAME) # user can click this header and sort - col.set_sort_column_id(C_NICKNAME) + col.set_sort_column_id(Column.NICKNAME) col.set_resizable(True) self.search_results_listview.append_column(col) diff --git a/src/history_window.py b/src/history_window.py index 1a0a8d2f9..de3090ed7 100644 --- a/src/history_window.py +++ b/src/history_window.py @@ -31,6 +31,8 @@ from gi.repository import GLib import time import calendar +from enum import IntEnum + import gtkgui_helpers import conversation_textview import dialogs @@ -39,26 +41,21 @@ from common import gajim from common import helpers from common import exceptions -from common.logger import Constants +from common.logger import ShowConstant, KindConstant -constants = Constants() +class InfoColumn(IntEnum): + '''Completion dict''' + JID = 0 + ACCOUNT = 1 + NAME = 2 + COMPLETION = 3 -# Completion dict -( - C_INFO_JID, - C_INFO_ACCOUNT, - C_INFO_NAME, - C_INFO_COMPLETION -) = range(4) - -# contact_name, date, message, time -( - C_LOG_JID, - C_CONTACT_NAME, - C_UNIXTIME, - C_MESSAGE, - C_TIME -) = range(5) +class Column(IntEnum): + LOG_JID = 0 + CONTACT_NAME = 1 + UNIXTIME = 2 + MESSAGE = 3 + TIME = 4 class HistoryWindow: """ @@ -95,23 +92,23 @@ class HistoryWindow: self.results_treeview.append_column(col) renderer = Gtk.CellRendererText() col.pack_start(renderer, True) - col.add_attribute(renderer, 'text', C_CONTACT_NAME) - col.set_sort_column_id(C_CONTACT_NAME) # user can click this header and sort + col.add_attribute(renderer, 'text', Column.CONTACT_NAME) + col.set_sort_column_id(Column.CONTACT_NAME) # user can click this header and sort col.set_resizable(True) col = Gtk.TreeViewColumn(_('Date')) self.results_treeview.append_column(col) renderer = Gtk.CellRendererText() col.pack_start(renderer, True) - col.add_attribute(renderer, 'text', C_UNIXTIME) - col.set_sort_column_id(C_UNIXTIME) # user can click this header and sort + col.add_attribute(renderer, 'text', Column.UNIXTIME) + col.set_sort_column_id(Column.UNIXTIME) # user can click this header and sort col.set_resizable(True) col = Gtk.TreeViewColumn(_('Message')) self.results_treeview.append_column(col) renderer = Gtk.CellRendererText() col.pack_start(renderer, True) - col.add_attribute(renderer, 'text', C_MESSAGE) + col.add_attribute(renderer, 'text', Column.MESSAGE) col.set_resizable(True) self.jid = None # The history we are currently viewing @@ -372,17 +369,17 @@ class HistoryWindow: widget.mark_day(day) def _get_string_show_from_constant_int(self, show): - if show == constants.SHOW_ONLINE: + if show == ShowConstant.ONLINE: show = 'online' - elif show == constants.SHOW_CHAT: + elif show == ShowConstant.CHAT: show = 'chat' - elif show == constants.SHOW_AWAY: + elif show == ShowConstant.AWAY: show = 'away' - elif show == constants.SHOW_XA: + elif show == ShowConstant.XA: show = 'xa' - elif show == constants.SHOW_DND: + elif show == ShowConstant.DND: show = 'dnd' - elif show == constants.SHOW_OFFLINE: + elif show == ShowConstant.OFFLINE: show = 'offline' return show @@ -402,8 +399,8 @@ class HistoryWindow: # line[0] is contact_name, line[1] is time of message # line[2] is kind, line[3] is show, line[4] is message, line[5] is subject # line[6] is additional_data - if not show_status and line[2] in (constants.KIND_GCSTATUS, - constants.KIND_STATUS): + if not show_status and line[2] in (KindConstant.GCSTATUS, + KindConstant.STATUS): continue self._add_new_line(line[0], line[1], line[2], line[3], line[4], line[5], line[6]) @@ -412,8 +409,8 @@ class HistoryWindow: """ Add a new line in textbuffer """ - if not message and kind not in (constants.KIND_STATUS, - constants.KIND_GCSTATUS): + if not message and kind not in (KindConstant.STATUS, + KindConstant.GCSTATUS): return buf = self.history_buffer end_iter = buf.get_end_iter() @@ -444,15 +441,15 @@ class HistoryWindow: show = self._get_string_show_from_constant_int(show) - if kind == constants.KIND_GC_MSG: + if kind == KindConstant.GC_MSG: tag_name = 'incoming' - elif kind in (constants.KIND_SINGLE_MSG_RECV, - constants.KIND_CHAT_MSG_RECV): - contact_name = self.completion_dict[self.jid][C_INFO_NAME] + elif kind in (KindConstant.SINGLE_MSG_RECV, + KindConstant.CHAT_MSG_RECV): + contact_name = self.completion_dict[self.jid][InfoColumn.NAME] tag_name = 'incoming' tag_msg = 'incomingtxt' - elif kind in (constants.KIND_SINGLE_MSG_SENT, - constants.KIND_CHAT_MSG_SENT): + elif kind in (KindConstant.SINGLE_MSG_SENT, + KindConstant.CHAT_MSG_SENT): if self.account: contact_name = gajim.nicks[self.account] else: @@ -462,7 +459,7 @@ class HistoryWindow: contact_name = gajim.nicks[account] tag_name = 'outgoing' tag_msg = 'outgoingtxt' - elif kind == constants.KIND_GCSTATUS: + elif kind == KindConstant.GCSTATUS: # message here (if not None) is status message if message: message = _('%(nick)s is now %(status)s: %(status_msg)s') %\ @@ -492,7 +489,7 @@ class HistoryWindow: else: # do not do this if gcstats, avoid dupping contact_name # eg. nkour: nkour is now Offline - if contact_name and kind != constants.KIND_GCSTATUS: + if contact_name and kind != KindConstant.GCSTATUS: # add stuff before and after contact name before_str = gajim.config.get('before_nickname') before_str = helpers.from_one_line(before_str) @@ -532,7 +529,7 @@ class HistoryWindow: # perform search in preselected jids # jids are preselected with the query_entry for jid in self.jids_to_search: - account = self.completion_dict[jid][C_INFO_ACCOUNT] + account = self.completion_dict[jid][InfoColumn.ACCOUNT] if account is None: # We do not know an account. This can only happen if the contact is offine, # or if we browse a groupchat history. The account is not needed, a dummy can @@ -554,16 +551,16 @@ class HistoryWindow: # add "subject: | message: " in message column if kind is single # also do we need show at all? (we do not search on subject) for row in results: - if not show_status and row[2] in (constants.KIND_GCSTATUS, - constants.KIND_STATUS): + if not show_status and row[2] in (KindConstant.GCSTATUS, + KindConstant.STATUS): continue contact_name = row[0] if not contact_name: kind = row[2] - if kind == constants.KIND_CHAT_MSG_SENT: # it's us! :) + if kind == KindConstant.CHAT_MSG_SENT: # it's us! :) contact_name = gajim.nicks[account] else: - contact_name = self.completion_dict[jid][C_INFO_NAME] + contact_name = self.completion_dict[jid][InfoColumn.NAME] tim = row[1] message = row[4] local_time = time.localtime(tim) @@ -583,14 +580,14 @@ class HistoryWindow: cur_month = gtkgui_helpers.make_gtk_month_python_month(cur_month) model = widget.get_model() # make it a tupple (Y, M, D, 0, 0, 0...) - tim = time.strptime(model[path][C_UNIXTIME], '%Y-%m-%d') + tim = time.strptime(model[path][Column.UNIXTIME], '%Y-%m-%d') year = tim[0] gtk_month = tim[1] month = gtkgui_helpers.make_python_month_gtk_month(gtk_month) day = tim[2] # switch to belonging logfile if necessary - log_jid = model[path][C_LOG_JID] + log_jid = model[path][Column.LOG_JID] if log_jid != self.jid: self._load_history(log_jid, None) @@ -599,7 +596,7 @@ class HistoryWindow: self.calendar.select_month(month, year) self.calendar.select_day(day) - unix_time = model[path][C_TIME] + unix_time = model[path][Column.TIME] self._scroll_to_result(unix_time) #FIXME: one day do not search just for unix_time but the whole and user # specific format of the textbuffer line [time] nick: message diff --git a/src/plugins/gui.py b/src/plugins/gui.py index f544c9242..46c48d1fc 100644 --- a/src/plugins/gui.py +++ b/src/plugins/gui.py @@ -32,6 +32,8 @@ from gi.repository import GdkPixbuf from gi.repository import GLib import os +from enum import IntEnum + import gtkgui_helpers from dialogs import WarningDialog, YesNoDialog, ArchiveChooserDialog from htmltextview import HtmlTextView @@ -41,13 +43,12 @@ from plugins.helpers import GajimPluginActivateException from plugins.plugins_i18n import _ from common.exceptions import PluginsystemError -( -PLUGIN, -NAME, -ACTIVE, -ACTIVATABLE, -ICON, -) = range(5) +class Column(IntEnum): + PLUGIN = 0 + NAME = 1 + ACTIVE = 2 + ACTIVATABLE = 3 + ICON = 4 class PluginsWindow(object): @@ -78,19 +79,19 @@ class PluginsWindow(object): self.installed_plugins_treeview.set_rules_hint(True) renderer = Gtk.CellRendererText() - col = Gtk.TreeViewColumn(_('Plugin'))#, renderer, text=NAME) + col = Gtk.TreeViewColumn(_('Plugin'))#, renderer, text=Column.NAME) cell = Gtk.CellRendererPixbuf() col.pack_start(cell, False) - col.add_attribute(cell, 'pixbuf', ICON) + col.add_attribute(cell, 'pixbuf', Column.ICON) col.pack_start(renderer, True) - col.add_attribute(renderer, 'text', NAME) + col.add_attribute(renderer, 'text', Column.NAME) col.set_property('expand', True) self.installed_plugins_treeview.append_column(col) renderer = Gtk.CellRendererToggle() renderer.connect('toggled', self.installed_plugins_toggled_cb) - col = Gtk.TreeViewColumn(_('Active'), renderer, active=ACTIVE, - activatable=ACTIVATABLE) + col = Gtk.TreeViewColumn(_('Active'), renderer, active=Column.ACTIVE, + activatable=Column.ACTIVATABLE) self.installed_plugins_treeview.append_column(col) self.def_icon = gtkgui_helpers.get_icon_pixmap('preferences-desktop') @@ -124,9 +125,9 @@ class PluginsWindow(object): def installed_plugins_treeview_selection_changed(self, treeview_selection): model, iter = treeview_selection.get_selected() if iter: - plugin = model.get_value(iter, PLUGIN) - plugin_name = model.get_value(iter, NAME) - is_active = model.get_value(iter, ACTIVE) + plugin = model.get_value(iter, Column.PLUGIN) + plugin_name = model.get_value(iter, Column.NAME) + is_active = model.get_value(iter, Column.ACTIVE) self._display_installed_plugin_info(plugin) else: @@ -195,8 +196,8 @@ class PluginsWindow(object): @log_calls('PluginsWindow') def installed_plugins_toggled_cb(self, cell, path): - is_active = self.installed_plugins_model[path][ACTIVE] - plugin = self.installed_plugins_model[path][PLUGIN] + is_active = self.installed_plugins_model[path][Column.ACTIVE] + plugin = self.installed_plugins_model[path][Column.PLUGIN] if is_active: gajim.plugin_manager.deactivate_plugin(plugin) @@ -208,7 +209,7 @@ class PluginsWindow(object): transient_for=self.window) return - self.installed_plugins_model[path][ACTIVE] = not is_active + self.installed_plugins_model[path][Column.ACTIVE] = not is_active @log_calls('PluginsWindow') def on_plugins_window_destroy(self, widget): @@ -224,9 +225,9 @@ class PluginsWindow(object): selection = self.installed_plugins_treeview.get_selection() model, iter = selection.get_selected() if iter: - plugin = model.get_value(iter, PLUGIN) - plugin_name = model.get_value(iter, NAME) - is_active = model.get_value(iter, ACTIVE) + plugin = model.get_value(iter, Column.PLUGIN) + plugin_name = model.get_value(iter, Column.NAME) + is_active = model.get_value(iter, Column.ACTIVE) result = plugin.config_dialog.run(self.window) @@ -242,9 +243,9 @@ class PluginsWindow(object): selection = self.installed_plugins_treeview.get_selection() model, iter = selection.get_selected() if iter: - plugin = model.get_value(iter, PLUGIN) - plugin_name = model.get_value(iter, NAME) - is_active = model.get_value(iter, ACTIVE) + plugin = model.get_value(iter, Column.PLUGIN) + plugin_name = model.get_value(iter, Column.NAME) + is_active = model.get_value(iter, Column.ACTIVE) try: gajim.plugin_manager.remove_plugin(plugin) except PluginsystemError as e: @@ -271,8 +272,8 @@ class PluginsWindow(object): model = self.installed_plugins_model for i, row in enumerate(model): - if plugin == row[PLUGIN]: - model.remove(model.get_iter((i, PLUGIN))) + if plugin == row[Column.PLUGIN]: + model.remove(model.get_iter((i, Column.PLUGIN))) break iter_ = model.append([plugin, plugin.name, False, diff --git a/src/roster_window.py b/src/roster_window.py index 0039acfe3..da6a68cab 100644 --- a/src/roster_window.py +++ b/src/roster_window.py @@ -43,6 +43,8 @@ import sys import time import locale +from enum import IntEnum + import common.sleepy import history_window import dialogs @@ -72,20 +74,18 @@ from message_window import MessageWindowMgr from nbxmpp.protocol import NS_FILE, NS_ROSTERX, NS_CONFERENCE -#(icon, name, type, jid, account, editable, second pixbuf) -( - C_IMG, # image to show state (online, new message etc) - C_NAME, # cellrenderer text that holds contact nickame - C_TYPE, # account, group or contact? - C_JID, # the jid of the row - C_ACCOUNT, # cellrenderer text that holds account name - C_MOOD_PIXBUF, - C_ACTIVITY_PIXBUF, - C_TUNE_PIXBUF, - C_LOCATION_PIXBUF, - C_AVATAR_PIXBUF, # avatar_pixbuf - C_PADLOCK_PIXBUF, # use for account row only -) = range(11) +class Column(IntEnum): + IMG = 0 # image to show state (online, new message etc) + NAME = 1 # cellrenderer text that holds contact nickame + TYPE = 2 # account, group or contact? + JID = 3 # the jid of the row + ACCOUNT = 4 # cellrenderer text that holds account name + MOOD_PIXBUF = 5 + ACTIVITY_PIXBUF = 6 + TUNE_PIXBUF = 7 + LOCATION_PIXBUF = 8 + AVATAR_PIXBUF = 9 # avatar_pixbuf + PADLOCK_PIXBUF = 10 # use for account row only empty_pixbuf = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, 1, 1) empty_pixbuf.fill(0xffffff00) @@ -434,7 +434,7 @@ class RosterWindow: assert iters, '%s shall be removed but is not in roster' % contact.jid parent_iter = self.model.iter_parent(iters[0]) - parent_type = self.model[parent_iter][C_TYPE] + parent_type = self.model[parent_iter][Column.TYPE] if groups: # Only remove from specified groups @@ -451,12 +451,12 @@ class RosterWindow: return False # Remove us and empty groups from the model for i in iters: - assert self.model[i][C_JID] == contact.jid and \ - self.model[i][C_ACCOUNT] == account, \ + assert self.model[i][Column.JID] == contact.jid and \ + self.model[i][Column.ACCOUNT] == account, \ "Invalidated iters of %s" % contact.jid parent_i = self.model.iter_parent(i) - parent_type = self.model[parent_i][C_TYPE] + parent_type = self.model[parent_i][Column.TYPE] to_be_removed = i while parent_type == 'group' and \ @@ -465,13 +465,13 @@ class RosterWindow: account_group = 'MERGED' else: account_group = account - group = self.model[parent_i][C_JID] + group = self.model[parent_i][Column.JID] if group in gajim.groups[account]: del gajim.groups[account][group] to_be_removed = parent_i del self._iters[account_group]['groups'][group] parent_i = self.model.iter_parent(parent_i) - parent_type = self.model[parent_i][C_TYPE] + parent_type = self.model[parent_i][Column.TYPE] self.model.remove(to_be_removed) del self._iters[account]['contacts'][contact.jid] @@ -555,7 +555,7 @@ class RosterWindow: family_in_roster = True parent_iter = self.model.iter_parent(iters[0]) - parent_type = self.model[parent_iter][C_TYPE] + parent_type = self.model[parent_iter][Column.TYPE] if parent_type != 'contact': # The contact on top @@ -603,7 +603,7 @@ class RosterWindow: big_brother_account, model=self.model) if child_iters: parent_iter = self.model.iter_parent(child_iters[0]) - parent_type = self.model[parent_iter][C_TYPE] + parent_type = self.model[parent_iter][Column.TYPE] # Check if the current BigBrother has even been before. if parent_type == 'contact': @@ -629,7 +629,7 @@ class RosterWindow: if not child_iters: continue parent_iter = self.model.iter_parent(child_iters[0]) - parent_type = self.model[parent_iter][C_TYPE] + parent_type = self.model[parent_iter][Column.TYPE] if parent_type != 'contact': _contact = gajim.contacts.get_contact(_account, _jid) self._remove_entity(_contact, _account) @@ -810,7 +810,7 @@ class RosterWindow: self_iter = self._get_self_contact_iter(account, model=self.model) if not self_iter: return - self.model[self_iter][C_JID] = new_jid + self.model[self_iter][Column.JID] = new_jid self.draw_contact(new_jid, account) def add_groupchat(self, jid, account, status=''): @@ -1048,9 +1048,9 @@ class RosterWindow: # the only way to create a pixbuf from stock # tls_pixbuf = self.window.render_icon_pixbuf( # Gtk.STOCK_DIALOG_AUTHENTICATION, Gtk.IconSize.MENU) - self.model[child_iter][C_PADLOCK_PIXBUF] = tls_pixbuf + self.model[child_iter][Column.PADLOCK_PIXBUF] = tls_pixbuf else: - self.model[child_iter][C_PADLOCK_PIXBUF] = empty_pixbuf + self.model[child_iter][Column.PADLOCK_PIXBUF] = empty_pixbuf if self.regroup: account_name = _('Merged accounts') @@ -1070,34 +1070,34 @@ class RosterWindow: accounts = accounts) account_name += ' (%s/%s)' % (repr(nbr_on), repr(nbr_total)) - self.model[child_iter][C_NAME] = account_name + self.model[child_iter][Column.NAME] = account_name pep_dict = gajim.connections[account].pep if gajim.config.get('show_mood_in_roster') and 'mood' in pep_dict: - self.model[child_iter][C_MOOD_PIXBUF] = \ + self.model[child_iter][Column.MOOD_PIXBUF] = \ gtkgui_helpers.get_pep_as_pixbuf(pep_dict['mood']) else: - self.model[child_iter][C_MOOD_PIXBUF] = empty_pixbuf + self.model[child_iter][Column.MOOD_PIXBUF] = empty_pixbuf if gajim.config.get('show_activity_in_roster') and 'activity' in \ pep_dict: - self.model[child_iter][C_ACTIVITY_PIXBUF] = \ + self.model[child_iter][Column.ACTIVITY_PIXBUF] = \ gtkgui_helpers.get_pep_as_pixbuf(pep_dict['activity']) else: - self.model[child_iter][C_ACTIVITY_PIXBUF] = empty_pixbuf + self.model[child_iter][Column.ACTIVITY_PIXBUF] = empty_pixbuf if gajim.config.get('show_tunes_in_roster') and 'tune' in pep_dict: - self.model[child_iter][C_TUNE_PIXBUF] = \ + self.model[child_iter][Column.TUNE_PIXBUF] = \ gtkgui_helpers.get_pep_as_pixbuf(pep_dict['tune']) else: - self.model[child_iter][C_TUNE_PIXBUF] = empty_pixbuf + self.model[child_iter][Column.TUNE_PIXBUF] = empty_pixbuf if gajim.config.get('show_location_in_roster') and 'location' in \ pep_dict: - self.model[child_iter][C_LOCATION_PIXBUF] = \ + self.model[child_iter][Column.LOCATION_PIXBUF] = \ gtkgui_helpers.get_pep_as_pixbuf(pep_dict['location']) else: - self.model[child_iter][C_LOCATION_PIXBUF] = empty_pixbuf + self.model[child_iter][Column.LOCATION_PIXBUF] = empty_pixbuf def _really_draw_accounts(self): for acct in self.accounts_to_draw: @@ -1130,7 +1130,7 @@ class RosterWindow: accounts = accounts, groups = [group]) text += ' (%s/%s)' % (repr(nbr_on), repr(nbr_total)) - self.model[child_iter][C_NAME] = text + self.model[child_iter][Column.NAME] = text def _really_draw_groups(self): for ag in self.groups_to_draw.values(): @@ -1153,11 +1153,11 @@ class RosterWindow: if not child_iters: return False parent_iter = self.model.iter_parent(child_iters[0]) - if self.model[parent_iter][C_TYPE] != 'contact': + if self.model[parent_iter][Column.TYPE] != 'contact': # parent is not a contact return - parent_jid = self.model[parent_iter][C_JID] - parent_account = self.model[parent_iter][C_ACCOUNT] + parent_jid = self.model[parent_iter][Column.JID] + parent_account = self.model[parent_iter][Column.ACCOUNT] self.draw_contact(parent_jid, parent_account) return False @@ -1269,8 +1269,8 @@ class RosterWindow: iterC = self.model.iter_children(child_iter) while iterC: # a child has awaiting messages? - jidC = self.model[iterC][C_JID] - accountC = self.model[iterC][C_ACCOUNT] + jidC = self.model[iterC][Column.JID] + accountC = self.model[iterC][Column.ACCOUNT] if len(gajim.events.get_events(accountC, jidC)): icon_name = 'event' break @@ -1288,8 +1288,8 @@ class RosterWindow: # Expand/collapse icon might differ per iter # (group) img = state_images[icon_name] - self.model[child_iter][C_IMG] = img - self.model[child_iter][C_NAME] = name + self.model[child_iter][Column.IMG] = img + self.model[child_iter][Column.NAME] = name else: # A normal contact or little brother state_images = self.get_appropriate_state_images(jid, @@ -1298,8 +1298,8 @@ class RosterWindow: # All iters have the same icon (no expand/collapse) img = state_images[icon_name] for child_iter in child_iters: - self.model[child_iter][C_IMG] = img - self.model[child_iter][C_NAME] = name + self.model[child_iter][Column.IMG] = img + self.model[child_iter][Column.NAME] = name # We are a little brother if family and not is_big_brother and not self.starting: @@ -1316,7 +1316,7 @@ class RosterWindow: iterG = self._get_group_iter(g, account, model=self.model) if iterG: # it's not self contact - self.model[iterG][C_JID] = self.model[iterG][C_JID] + self.model[iterG][Column.JID] = self.model[iterG][Column.JID] i += 1 gajim.plugin_manager.gui_extension_point('roster_draw_contact', self, @@ -1363,14 +1363,14 @@ class RosterWindow: iters = self._get_contact_iter(jid, account, model=self.model) if not iters or not gajim.config.get('show_avatars_in_roster'): return - jid = self.model[iters[0]][C_JID] + jid = self.model[iters[0]][Column.JID] pixbuf = gtkgui_helpers.get_avatar_pixbuf_from_cache(jid) if pixbuf in (None, 'ask'): scaled_pixbuf = empty_pixbuf else: scaled_pixbuf = gtkgui_helpers.get_scaled_pixbuf(pixbuf, 'roster') for child_iter in iters: - self.model[child_iter][C_AVATAR_PIXBUF] = scaled_pixbuf + self.model[child_iter][Column.AVATAR_PIXBUF] = scaled_pixbuf return False def draw_completely(self, jid, account): @@ -1513,9 +1513,9 @@ class RosterWindow: def _readjust_expand_collapse_state(self): def func(model, path, iter_, param): - type_ = model[iter_][C_TYPE] - acct = model[iter_][C_ACCOUNT] - jid = model[iter_][C_JID] + type_ = model[iter_][Column.TYPE] + acct = model[iter_][Column.ACCOUNT] + jid = model[iter_][Column.JID] key = None if type_ == 'account': key = acct @@ -1523,9 +1523,9 @@ class RosterWindow: key = acct + jid elif type_ == 'contact': parent_iter = model.iter_parent(iter_) - ptype = model[parent_iter][C_TYPE] + ptype = model[parent_iter][Column.TYPE] if ptype == 'group': - grp = model[parent_iter][C_JID] + grp = model[parent_iter][Column.JID] key = acct + grp + jid if key: if key in self.collapsed_rows: @@ -1620,18 +1620,18 @@ class RosterWindow: """ if self.starting_filtering: return False - type_ = model[titer][C_TYPE] + type_ = model[titer][Column.TYPE] if not type_: return False if type_ == 'account': # Always show account return True - account = model[titer][C_ACCOUNT] + account = model[titer][Column.ACCOUNT] if not account: return False - jid = model[titer][C_JID] + jid = model[titer][Column.JID] if not jid: return False @@ -1662,7 +1662,7 @@ class RosterWindow: return True if self.regroup: - # C_ACCOUNT for groups depends on the order + # Column.ACCOUNT for groups depends on the order # accounts were connected # Check all accounts for online group contacts accounts = gajim.contacts.get_accounts() @@ -1685,10 +1685,10 @@ class RosterWindow: if model.iter_has_child(titer): iter_c = model.iter_children(titer) while iter_c: - if self.rfilter_string in model[iter_c][C_NAME].lower(): + if self.rfilter_string in model[iter_c][Column.NAME].lower(): return True iter_c = model.iter_next(iter_c) - return self.rfilter_string in model[titer][C_NAME].lower() + return self.rfilter_string in model[titer][Column.NAME].lower() if gajim.config.get('showoffline'): return True bb_jid = None @@ -1713,7 +1713,7 @@ class RosterWindow: return self.contact_is_visible(contact, account) if type_ == 'agent': if self.rfilter_enabled: - return self.rfilter_string in model[titer][C_NAME].lower() + return self.rfilter_string in model[titer][Column.NAME].lower() contact = gajim.contacts.get_contact_with_highest_priority(account, jid) return self.contact_has_pending_roster_events(contact, account) or \ @@ -1721,30 +1721,30 @@ class RosterWindow: (gajim.account_is_connected(account) or \ gajim.config.get('showoffline'))) if type_ == 'groupchat' and self.rfilter_enabled: - return self.rfilter_string in model[titer][C_NAME].lower() + return self.rfilter_string in model[titer][Column.NAME].lower() return True def _compareIters(self, model, iter1, iter2, data=None): """ Compare two iters to sort them """ - name1 = model[iter1][C_NAME] - name2 = model[iter2][C_NAME] + name1 = model[iter1][Column.NAME] + name2 = model[iter2][Column.NAME] if not name1 or not name2: return 0 name1 = name1 name2 = name2 - type1 = model[iter1][C_TYPE] - type2 = model[iter2][C_TYPE] + type1 = model[iter1][Column.TYPE] + type2 = model[iter2][Column.TYPE] if type1 == 'self_contact': return -1 if type2 == 'self_contact': return 1 if type1 == 'group': - name1 = model[iter1][C_JID] + name1 = model[iter1][Column.JID] if name1: name1 = name1 - name2 = model[iter2][C_JID] + name2 = model[iter2][Column.JID] if name2: name2 = name2 if name1 == _('Transports'): @@ -1759,16 +1759,16 @@ class RosterWindow: return 1 if name2 == _('Groupchats'): return -1 - account1 = model[iter1][C_ACCOUNT] - account2 = model[iter2][C_ACCOUNT] + account1 = model[iter1][Column.ACCOUNT] + account2 = model[iter2][Column.ACCOUNT] if not account1 or not account2: return 0 account1 = account1 account2 = account2 if type1 == 'account': return locale.strcoll(account1, account2) - jid1 = model[iter1][C_JID] - jid2 = model[iter2][C_JID] + jid1 = model[iter1][Column.JID] + jid2 = model[iter2][Column.JID] if type1 == 'contact': lcontact1 = gajim.contacts.get_contacts(account1, jid1) contact1 = gajim.contacts.get_first_contact_from_jid(account1, jid1) @@ -2287,7 +2287,7 @@ class RosterWindow: else: # No need to redraw contacts if we're quitting if child_iterA: - self.model[child_iterA][C_AVATAR_PIXBUF] = empty_pixbuf + self.model[child_iterA][Column.AVATAR_PIXBUF] = empty_pixbuf if account in gajim.con_types: gajim.con_types[account] = None for jid in list(gajim.contacts.get_jid_list(account)): @@ -3049,7 +3049,7 @@ class RosterWindow: win.redraw_tab(ctrl) win.show_title() elif row_type == 'group': - # in C_JID column, we hold the group name (which is not escaped) + # in Column.JID column, we hold the group name (which is not escaped) self.rename_group(old_text, new_text, account) def on_canceled(): @@ -3327,10 +3327,10 @@ class RosterWindow: if len(list_of_paths) != 1: return path = list_of_paths[0] - type_ = model[path][C_TYPE] + type_ = model[path][Column.TYPE] if type_ in ('contact', 'group', 'agent'): - jid = model[path][C_JID] - account = model[path][C_ACCOUNT] + jid = model[path][Column.JID] + account = model[path][Column.ACCOUNT] self.on_rename(widget, type_, jid, account) elif event.keyval == Gdk.KEY_Delete: @@ -3338,17 +3338,17 @@ class RosterWindow: model, list_of_paths = treeselection.get_selected_rows() if not len(list_of_paths): return - type_ = model[list_of_paths[0]][C_TYPE] - account = model[list_of_paths[0]][C_ACCOUNT] + type_ = model[list_of_paths[0]][Column.TYPE] + account = model[list_of_paths[0]][Column.ACCOUNT] if type_ in ('account', 'group', 'self_contact') or \ - account == gajim.ZEROCONF_ACC_NAME: + account == gajim.ZEROCONF_ACConstant.NAME: return list_ = [] for path in list_of_paths: - if model[path][C_TYPE] != type_: + if model[path][Column.TYPE] != type_: return - jid = model[path][C_JID] - account = model[path][C_ACCOUNT] + jid = model[path][Column.JID] + account = model[path][Column.ACCOUNT] if not gajim.account_is_connected(account): continue contact = gajim.contacts.get_contact_with_highest_priority( @@ -3462,11 +3462,11 @@ class RosterWindow: if list_of_paths != [path]: self.tree.get_selection().unselect_all() self.tree.get_selection().select_path(path) - type_ = model[path][C_TYPE] + type_ = model[path][Column.TYPE] if type_ in ('agent', 'contact', 'self_contact', 'groupchat'): self.on_row_activated(widget, path) elif type_ == 'account': - account = model[path][C_ACCOUNT] + account = model[path][Column.ACCOUNT] if account != 'all': show = gajim.connections[account].connected if show > 1: # We are connected @@ -3491,7 +3491,7 @@ class RosterWindow: elif event.button == 1: # Left click model = self.modelfilter - type_ = model[path][C_TYPE] + type_ = model[path][Column.TYPE] # x_min is the x start position of status icon column if gajim.config.get('avatar_position_in_roster') == 'left': x_min = gajim.config.get('roster_avatar_width') @@ -3532,9 +3532,9 @@ class RosterWindow: iter = self.modelfilter.get_iter(path) child_iter = self.modelfilter.iter_children(iter) while child_iter: - type_ = self.modelfilter[child_iter][C_TYPE] - account = self.modelfilter[child_iter][C_ACCOUNT] - group = self.modelfilter[child_iter][C_JID] + type_ = self.modelfilter[child_iter][Column.TYPE] + account = self.modelfilter[child_iter][Column.ACCOUNT] + group = self.modelfilter[child_iter][Column.JID] if type_ == 'group' and account + group not in self.collapsed_rows: self.expand_group_row(self.modelfilter.get_path(child_iter)) child_iter = self.modelfilter.iter_next(child_iter) @@ -3940,10 +3940,10 @@ class RosterWindow: treeselection = self.tree.get_selection() model, list_of_paths = treeselection.get_selected_rows() for path in list_of_paths: - type_ = model[path][C_TYPE] + type_ = model[path][Column.TYPE] if type_ in ('contact', 'agent'): - jid = model[path][C_JID] - account = model[path][C_ACCOUNT] + jid = model[path][Column.JID] + account = model[path][Column.ACCOUNT] contact = gajim.contacts.get_first_contact_from_jid(account, jid) self.on_info(widget, contact, account) @@ -3954,10 +3954,10 @@ class RosterWindow: if len(list_of_paths) != 1: return path = list_of_paths[0] - type_ = model[path][C_TYPE] + type_ = model[path][Column.TYPE] if type_ in ('contact', 'agent'): - jid = model[path][C_JID] - account = model[path][C_ACCOUNT] + jid = model[path][Column.JID] + account = model[path][Column.ACCOUNT] contact = gajim.contacts.get_first_contact_from_jid(account, jid) self.on_history(widget, contact, account) @@ -3972,8 +3972,8 @@ class RosterWindow: this way) """ model = self.modelfilter - account = model[path][C_ACCOUNT] - type_ = model[path][C_TYPE] + account = model[path][Column.ACCOUNT] + type_ = model[path][Column.TYPE] if type_ in ('group', 'account'): if self.tree.row_expanded(path): self.tree.collapse_row(path) @@ -3982,7 +3982,7 @@ class RosterWindow: return if self.rfilter_enabled: GObject.idle_add(self.disable_rfilter) - jid = model[path][C_JID] + jid = model[path][Column.JID] resource = None contact = gajim.contacts.get_contact_with_highest_priority(account, jid) titer = model.get_iter(path) @@ -4009,7 +4009,7 @@ class RosterWindow: if not first_ev and model.iter_has_child(titer): child_iter = model.iter_children(titer) while not first_ev and child_iter: - child_jid = model[child_iter][C_JID] + child_jid = model[child_iter][Column.JID] first_ev = gajim.events.get_first_event(account, child_jid) if first_ev: jid = child_jid @@ -4054,12 +4054,12 @@ class RosterWindow: if self.regroup: # merged accounts accounts = list(gajim.connections.keys()) else: - accounts = [model[titer][C_ACCOUNT]] + accounts = [model[titer][Column.ACCOUNT]] - type_ = model[titer][C_TYPE] + type_ = model[titer][Column.TYPE] if type_ == 'group': - group = model[titer][C_JID] - child_model[child_iter][C_IMG] = \ + group = model[titer][Column.JID] + child_model[child_iter][Column.IMG] = \ gajim.interface.jabber_state_images['16']['opened'] if self.rfilter_enabled: return @@ -4091,8 +4091,8 @@ class RosterWindow: self.tree.expand_row(path, False) elif type_ == 'contact': # Metacontact got toggled, update icon - jid = model[titer][C_JID] - account = model[titer][C_ACCOUNT] + jid = model[titer][Column.JID] + account = model[titer][Column.ACCOUNT] contact = gajim.contacts.get_contact(account, jid) for group in contact.groups: if account + group + jid in self.collapsed_rows: @@ -4118,15 +4118,15 @@ class RosterWindow: if self.regroup: # merged accounts accounts = list(gajim.connections.keys()) else: - accounts = [model[titer][C_ACCOUNT]] + accounts = [model[titer][Column.ACCOUNT]] - type_ = model[titer][C_TYPE] + type_ = model[titer][Column.TYPE] if type_ == 'group': - child_model[child_iter][C_IMG] = gajim.interface.\ + child_model[child_iter][Column.IMG] = gajim.interface.\ jabber_state_images['16']['closed'] if self.rfilter_enabled: return - group = model[titer][C_JID] + group = model[titer][Column.JID] for account in accounts: if group in gajim.groups[account]: # This account has this group gajim.groups[account][group]['expand'] = False @@ -4139,8 +4139,8 @@ class RosterWindow: self.draw_account(account) elif type_ == 'contact': # Metacontact got toggled, update icon - jid = model[titer][C_JID] - account = model[titer][C_ACCOUNT] + jid = model[titer][Column.JID] + account = model[titer][Column.ACCOUNT] contact = gajim.contacts.get_contact(account, jid) groups = contact.groups if not groups: @@ -4167,8 +4167,8 @@ class RosterWindow: # Signal is emitted when we write to our model return - type_ = model[titer][C_TYPE] - account = model[titer][C_ACCOUNT] + type_ = model[titer][Column.TYPE] + account = model[titer][Column.ACCOUNT] if not account: return @@ -4179,10 +4179,10 @@ class RosterWindow: # redraw us to show/hide expand icon if self.filtering: # Prevent endless loops - jid = model[titer][C_JID] + jid = model[titer][Column.JID] GLib.idle_add(self.draw_contact, jid, account) elif type_ == 'group': - group = model[titer][C_JID] + group = model[titer][Column.JID] GLib.idle_add(self._adjust_group_expand_collapse_state, group, account) elif type_ == 'account': GLib.idle_add(self._adjust_account_expand_collapse_state, account) @@ -4209,11 +4209,11 @@ class RosterWindow: # return # for path in list_of_paths: # row = model[path] -# if row[C_TYPE] != 'contact': +# if row[Column.TYPE] != 'contact': # self._last_selected_contact = [] # return -# jid = row[C_JID] -# account = row[C_ACCOUNT] +# jid = row[Column.JID] +# account = row[Column.ACCOUNT] # self._last_selected_contact.append((jid, account)) # GLib.idle_add(self.draw_contact, jid, account, True) @@ -4283,8 +4283,8 @@ class RosterWindow: # select first row self.tree.get_selection().unselect_all() def _func(model, path, iter_, param): - if model[iter_][C_TYPE] == 'contact' and self.rfilter_string in \ - model[iter_][C_NAME].lower(): + if model[iter_][Column.TYPE] == 'contact' and self.rfilter_string in \ + model[iter_][Column.NAME].lower(): col = self.tree.get_column(0) self.tree.set_cursor_on_cell(path, col, None, False) return True @@ -4361,7 +4361,7 @@ class RosterWindow: path = list_of_paths[0] data = '' if path.get_depth() >= 2: - data = model[path][C_JID] + data = model[path][Column.JID] selection.set_text(data, -1) def drag_begin(self, treeview, context): @@ -4570,9 +4570,9 @@ class RosterWindow: path_dest = (path_dest[0], path_dest[1]-1) # destination: the row something got dropped on iter_dest = model.get_iter(path_dest) - type_dest = model[iter_dest][C_TYPE] - jid_dest = model[iter_dest][C_JID] - account_dest = model[iter_dest][C_ACCOUNT] + type_dest = model[iter_dest][Column.TYPE] + jid_dest = model[iter_dest][Column.JID] + account_dest = model[iter_dest][Column.ACCOUNT] # drop on account row in merged mode, we cannot know the desired account if account_dest == 'all': @@ -4635,8 +4635,8 @@ class RosterWindow: # source: the row that was dragged path_source = treeview.get_selection().get_selected_rows()[1][0] iter_source = model.get_iter(path_source) - type_source = model[iter_source][C_TYPE] - account_source = model[iter_source][C_ACCOUNT] + type_source = model[iter_source][Column.TYPE] + account_source = model[iter_source][Column.ACCOUNT] if gajim.config.get_per('accounts', account_source, 'is_zeroconf'): return @@ -4654,18 +4654,18 @@ class RosterWindow: if account_source != account_dest: # drop on another account return - grp_source = model[iter_source][C_JID] + grp_source = model[iter_source][Column.JID] delimiter = gajim.connections[account_source].nested_group_delimiter grp_source_list = grp_source.split(delimiter) new_grp = None if type_dest == 'account': new_grp = grp_source_list[-1] elif type_dest == 'group': - grp_dest = model[iter_dest][C_JID] + grp_dest = model[iter_dest][Column.JID] grp_dest_list = grp_dest.split(delimiter) # Do not allow to drop on a subgroup of source group if grp_source_list[0] != grp_dest_list[0]: - new_grp = model[iter_dest][C_JID] + delimiter + \ + new_grp = model[iter_dest][Column.JID] + delimiter + \ grp_source_list[-1] if new_grp: self.move_group(grp_source, new_grp, account_source) @@ -4685,9 +4685,9 @@ class RosterWindow: # Get valid source group, jid and contact it = iter_source - while model[it][C_TYPE] == 'contact': + while model[it][Column.TYPE] == 'contact': it = model.iter_parent(it) - grp_source = model[it][C_JID] + grp_source = model[it][Column.JID] if grp_source in helpers.special_groups and \ grp_source not in ('Not in Roster', 'Observers'): # a transport or a minimized groupchat was dragged @@ -4701,12 +4701,12 @@ class RosterWindow: # Get destination group grp_dest = None if type_dest == 'group': - grp_dest = model[iter_dest][C_JID] + grp_dest = model[iter_dest][Column.JID] elif type_dest in ('contact', 'agent'): it = iter_dest - while model[it][C_TYPE] != 'group': + while model[it][Column.TYPE] != 'group': it = model.iter_parent(it) - grp_dest = model[it][C_JID] + grp_dest = model[it][Column.JID] if grp_dest in helpers.special_groups: return @@ -4865,7 +4865,7 @@ class RosterWindow: show = gajim.SHOW_LIST[status] else: # accounts merged show = helpers.get_global_show() - self.model[child_iterA][C_IMG] = gajim.interface.jabber_state_images[ + self.model[child_iterA][Column.IMG] = gajim.interface.jabber_state_images[ '16'][show] ################################################################################ @@ -4906,9 +4906,9 @@ class RosterWindow: gtkgui_helpers.set_unset_urgency_hint(self.window, nb_unread) def _change_style(self, model, path, titer, option): - if option is None or model[titer][C_TYPE] == option: + if option is None or model[titer][Column.TYPE] == option: # We changed style for this type of row - model[titer][C_NAME] = model[titer][C_NAME] + model[titer][Column.NAME] = model[titer][Column.NAME] def change_roster_style(self, option): self.model.foreach(self._change_style, option) @@ -4954,7 +4954,7 @@ class RosterWindow: When a row is added, set properties for icon renderer """ try: - type_ = model[titer][C_TYPE] + type_ = model[titer][Column.TYPE] except TypeError: return if type_ == 'account': @@ -4963,20 +4963,20 @@ class RosterWindow: elif type_ == 'group': self._set_group_row_background_color(renderer) parent_iter = model.iter_parent(titer) - if model[parent_iter][C_TYPE] == 'group': + if model[parent_iter][Column.TYPE] == 'group': renderer.set_property('xalign', 0.4) else: renderer.set_property('xalign', 0.2) elif type_: # prevent type_ = None, see http://trac.gajim.org/ticket/2534 - if not model[titer][C_JID] or not model[titer][C_ACCOUNT]: + if not model[titer][Column.JID] or not model[titer][Column.ACCOUNT]: # This can append when at the moment we add the row return - jid = model[titer][C_JID] - account = model[titer][C_ACCOUNT] + jid = model[titer][Column.JID] + account = model[titer][Column.ACCOUNT] self._set_contact_row_background_color(renderer, jid, account) parent_iter = model.iter_parent(titer) - if model[parent_iter][C_TYPE] == 'contact': + if model[parent_iter][Column.TYPE] == 'contact': renderer.set_property('xalign', 1) else: renderer.set_property('xalign', 0.6) @@ -4987,7 +4987,7 @@ class RosterWindow: When a row is added, set properties for name renderer """ try: - type_ = model[titer][C_TYPE] + type_ = model[titer][Column.TYPE] except TypeError: return theme = gajim.config.get('roster_theme') @@ -5011,18 +5011,18 @@ class RosterWindow: renderer.set_property('font', gtkgui_helpers.get_theme_font_for_option(theme, 'groupfont')) parent_iter = model.iter_parent(titer) - if model[parent_iter][C_TYPE] == 'group': + if model[parent_iter][Column.TYPE] == 'group': renderer.set_property('xpad', 8) else: renderer.set_property('xpad', 4) self._set_group_row_background_color(renderer) elif type_: # prevent type_ = None, see http://trac.gajim.org/ticket/2534 - if not model[titer][C_JID] or not model[titer][C_ACCOUNT]: + if not model[titer][Column.JID] or not model[titer][Column.ACCOUNT]: # This can append when at the moment we add the row return - jid = model[titer][C_JID] - account = model[titer][C_ACCOUNT] + jid = model[titer][Column.JID] + account = model[titer][Column.ACCOUNT] color = None if type_ == 'groupchat': ctrl = gajim.interface.minimized_controls[account].get(jid, @@ -5042,7 +5042,7 @@ class RosterWindow: renderer.set_property('font', gtkgui_helpers.get_theme_font_for_option(theme, 'contactfont')) parent_iter = model.iter_parent(titer) - if model[parent_iter][C_TYPE] == 'contact': + if model[parent_iter][Column.TYPE] == 'contact': renderer.set_property('xpad', 16) else: renderer.set_property('xpad', 12) @@ -5053,7 +5053,7 @@ class RosterWindow: When a row is added, draw the respective pep icon """ try: - type_ = model[titer][C_TYPE] + type_ = model[titer][Column.TYPE] except TypeError: return @@ -5067,11 +5067,11 @@ class RosterWindow: self._set_account_row_background_color(renderer) renderer.set_property('xalign', 1) elif type_: - if not model[titer][C_JID] or not model[titer][C_ACCOUNT]: + if not model[titer][Column.JID] or not model[titer][Column.ACCOUNT]: # This can append at the moment we add the row return - jid = model[titer][C_JID] - account = model[titer][C_ACCOUNT] + jid = model[titer][Column.JID] + account = model[titer][Column.ACCOUNT] self._set_contact_row_background_color(renderer, jid, account) def _fill_avatar_pixbuf_renderer(self, column, renderer, model, titer, @@ -5080,7 +5080,7 @@ class RosterWindow: When a row is added, set properties for avatar renderer """ try: - type_ = model[titer][C_TYPE] + type_ = model[titer][Column.TYPE] except TypeError: return @@ -5089,20 +5089,20 @@ class RosterWindow: return # allocate space for the icon only if needed - if model[titer][C_AVATAR_PIXBUF] or \ + if model[titer][Column.AVATAR_PIXBUF] or \ gajim.config.get('avatar_position_in_roster') == 'left': renderer.set_property('visible', True) if type_: # prevent type_ = None, see http://trac.gajim.org/ticket/2534 - if not model[titer][C_JID] or not model[titer][C_ACCOUNT]: + if not model[titer][Column.JID] or not model[titer][Column.ACCOUNT]: # This can append at the moment we add the row return - jid = model[titer][C_JID] - account = model[titer][C_ACCOUNT] + jid = model[titer][Column.JID] + account = model[titer][Column.ACCOUNT] self._set_contact_row_background_color(renderer, jid, account) else: renderer.set_property('visible', False) - if model[titer][C_AVATAR_PIXBUF] == empty_pixbuf and \ + if model[titer][Column.AVATAR_PIXBUF] == empty_pixbuf and \ gajim.config.get('avatar_position_in_roster') != 'left': renderer.set_property('visible', False) @@ -5119,12 +5119,12 @@ class RosterWindow: When a row is added, set properties for padlock renderer """ try: - type_ = model[titer][C_TYPE] + type_ = model[titer][Column.TYPE] except TypeError: return # allocate space for the icon only if needed - if type_ == 'account' and model[titer][C_PADLOCK_PIXBUF]: + if type_ == 'account' and model[titer][Column.PADLOCK_PIXBUF]: renderer.set_property('visible', True) self._set_account_row_background_color(renderer) renderer.set_property('xalign', 1) # align pixbuf to the right @@ -5596,7 +5596,7 @@ class RosterWindow: Make account's popup menu """ model = self.modelfilter - account = model[titer][C_ACCOUNT] + account = model[titer][Column.ACCOUNT] if account != 'all': # not in merged mode menu = self.build_account_menu(account) @@ -5627,14 +5627,14 @@ class RosterWindow: """ model = self.modelfilter path = model.get_path(titer) - group = model[titer][C_JID] - account = model[titer][C_ACCOUNT] + group = model[titer][Column.JID] + account = model[titer][Column.ACCOUNT] list_ = [] # list of (contact, account) tuples list_online = [] # list of (contact, account) tuples show_bookmarked = True - group = model[titer][C_JID] + group = model[titer][Column.JID] for jid in gajim.contacts.get_jid_list(account): contact = gajim.contacts.get_contact_with_highest_priority(account, jid) @@ -5773,8 +5773,8 @@ class RosterWindow: Make contact's popup menu """ model = self.modelfilter - jid = model[titer][C_JID] - account = model[titer][C_ACCOUNT] + jid = model[titer][Column.JID] + account = model[titer][Column.ACCOUNT] contact = gajim.contacts.get_contact_with_highest_priority(account, jid) menu = gui_menu_builder.get_contact_menu(contact, account) event_button = gtkgui_helpers.get_possible_button_event(event) @@ -5791,8 +5791,8 @@ class RosterWindow: is_blocked = True privacy_rules_supported = True for titer in iters: - jid = model[titer][C_JID] - account = model[titer][C_ACCOUNT] + jid = model[titer][Column.JID] + account = model[titer][Column.ACCOUNT] if gajim.connections[account].connected < 2: one_account_offline = True if not gajim.connections[account].privacy_rules_supported: @@ -5881,9 +5881,9 @@ class RosterWindow: Make transport's popup menu """ model = self.modelfilter - jid = model[titer][C_JID] + jid = model[titer][Column.JID] path = model.get_path(titer) - account = model[titer][C_ACCOUNT] + account = model[titer][Column.ACCOUNT] contact = gajim.contacts.get_contact_with_highest_priority(account, jid) menu = gui_menu_builder.get_transport_menu(contact, account) event_button = gtkgui_helpers.get_possible_button_event(event) @@ -5893,8 +5893,8 @@ class RosterWindow: def make_groupchat_menu(self, event, titer): model = self.modelfilter - jid = model[titer][C_JID] - account = model[titer][C_ACCOUNT] + jid = model[titer][Column.JID] + account = model[titer][Column.ACCOUNT] contact = gajim.contacts.get_contact_with_highest_priority(account, jid) menu = Gtk.Menu() @@ -6063,9 +6063,9 @@ class RosterWindow: def show_appropriate_context_menu(self, event, iters): # iters must be all of the same type model = self.modelfilter - type_ = model[iters[0]][C_TYPE] + type_ = model[iters[0]][Column.TYPE] for titer in iters[1:]: - if model[titer][C_TYPE] != type_: + if model[titer][Column.TYPE] != type_: return if type_ == 'group' and len(iters) == 1: self.make_group_menu(event, iters[0]) @@ -6137,9 +6137,9 @@ class RosterWindow: except Exception: return False - typ = model[iter_][C_TYPE] - account = model[iter_][C_ACCOUNT] - jid = model[iter_][C_JID] + typ = model[iter_][Column.TYPE] + account = model[iter_][Column.ACCOUNT] + jid = model[iter_][Column.JID] connected_contacts = [] if typ in ('contact', 'self_contact'): @@ -6340,9 +6340,9 @@ class RosterWindow: # cell_data_func, func_arg) self.renderers_list = [] self.renderers_propertys ={} - self._pep_type_to_model_column = {'mood': C_MOOD_PIXBUF, - 'activity': C_ACTIVITY_PIXBUF, 'tune': C_TUNE_PIXBUF, - 'location': C_LOCATION_PIXBUF} + self._pep_type_to_model_column = {'mood': Column.MOOD_PIXBUF, + 'activity': Column.ACTIVITY_PIXBUF, 'tune': Column.TUNE_PIXBUF, + 'location': Column.LOCATION_PIXBUF} renderer_text = Gtk.CellRendererText() self.renderers_propertys[renderer_text] = ('ellipsize', @@ -6350,7 +6350,7 @@ class RosterWindow: def add_avatar_renderer(): self.renderers_list.append(('avatar', Gtk.CellRendererPixbuf(), - False, 'pixbuf', C_AVATAR_PIXBUF, + False, 'pixbuf', Column.AVATAR_PIXBUF, self._fill_avatar_pixbuf_renderer, None)) if gajim.config.get('avatar_position_in_roster') == 'left': @@ -6358,32 +6358,32 @@ class RosterWindow: self.renderers_list += ( ('icon', cell_renderer_image.CellRendererImage(0, 0), False, - 'image', C_IMG, self._iconCellDataFunc, None), + 'image', Column.IMG, self._iconCellDataFunc, None), ('name', renderer_text, True, - 'markup', C_NAME, self._nameCellDataFunc, None), + 'markup', Column.NAME, self._nameCellDataFunc, None), ('mood', Gtk.CellRendererPixbuf(), False, - 'pixbuf', C_MOOD_PIXBUF, - self._fill_pep_pixbuf_renderer, C_MOOD_PIXBUF), + 'pixbuf', Column.MOOD_PIXBUF, + self._fill_pep_pixbuf_renderer, Column.MOOD_PIXBUF), ('activity', Gtk.CellRendererPixbuf(), False, - 'pixbuf', C_ACTIVITY_PIXBUF, - self._fill_pep_pixbuf_renderer, C_ACTIVITY_PIXBUF), + 'pixbuf', Column.ACTIVITY_PIXBUF, + self._fill_pep_pixbuf_renderer, Column.ACTIVITY_PIXBUF), ('tune', Gtk.CellRendererPixbuf(), False, - 'pixbuf', C_TUNE_PIXBUF, - self._fill_pep_pixbuf_renderer, C_TUNE_PIXBUF), + 'pixbuf', Column.TUNE_PIXBUF, + self._fill_pep_pixbuf_renderer, Column.TUNE_PIXBUF), ('location', Gtk.CellRendererPixbuf(), False, - 'pixbuf', C_LOCATION_PIXBUF, - self._fill_pep_pixbuf_renderer, C_LOCATION_PIXBUF)) + 'pixbuf', Column.LOCATION_PIXBUF, + self._fill_pep_pixbuf_renderer, Column.LOCATION_PIXBUF)) if gajim.config.get('avatar_position_in_roster') == 'right': add_avatar_renderer() self.renderers_list.append(('padlock', Gtk.CellRendererPixbuf(), False, - 'pixbuf', C_PADLOCK_PIXBUF, + 'pixbuf', Column.PADLOCK_PIXBUF, self._fill_padlock_pixbuf_renderer, None)) # fill and append column From a7349dc603f310c06c7138afccdb079266b604bd Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 7 Feb 2017 20:48:58 +0000 Subject: [PATCH 10/16] common.connection: Fix indentation. --- src/common/connection.py | 66 ++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/src/common/connection.py b/src/common/connection.py index b2ee7d0f4..0c5192227 100644 --- a/src/common/connection.py +++ b/src/common/connection.py @@ -71,39 +71,39 @@ import logging log = logging.getLogger('gajim.c.connection') ssl_error = { -2: _("Unable to get issuer certificate"), -3: _("Unable to get certificate CRL"), -4: _("Unable to decrypt certificate's signature"), -5: _("Unable to decrypt CRL's signature"), -6: _("Unable to decode issuer public key"), -7: _("Certificate signature failure"), -8: _("CRL signature failure"), -9: _("Certificate is not yet valid"), -10: _("Certificate has expired"), -11: _("CRL is not yet valid"), -12: _("CRL has expired"), -13: _("Format error in certificate's notBefore field"), -14: _("Format error in certificate's notAfter field"), -15: _("Format error in CRL's lastUpdate field"), -16: _("Format error in CRL's nextUpdate field"), -17: _("Out of memory"), -18: _("Self signed certificate"), -19: _("Self signed certificate in certificate chain"), -20: _("Unable to get local issuer certificate"), -21: _("Unable to verify the first certificate"), -22: _("Certificate chain too long"), -23: _("Certificate revoked"), -24: _("Invalid CA certificate"), -25: _("Path length constraint exceeded"), -26: _("Unsupported certificate purpose"), -27: _("Certificate not trusted"), -28: _("Certificate rejected"), -29: _("Subject issuer mismatch"), -30: _("Authority and subject key identifier mismatch"), -31: _("Authority and issuer serial number mismatch"), -32: _("Key usage does not include certificate signing"), -50: _("Application verification failure") -#100 is for internal usage: host not correct + 2: _("Unable to get issuer certificate"), + 3: _("Unable to get certificate CRL"), + 4: _("Unable to decrypt certificate's signature"), + 5: _("Unable to decrypt CRL's signature"), + 6: _("Unable to decode issuer public key"), + 7: _("Certificate signature failure"), + 8: _("CRL signature failure"), + 9: _("Certificate is not yet valid"), + 10: _("Certificate has expired"), + 11: _("CRL is not yet valid"), + 12: _("CRL has expired"), + 13: _("Format error in certificate's notBefore field"), + 14: _("Format error in certificate's notAfter field"), + 15: _("Format error in CRL's lastUpdate field"), + 16: _("Format error in CRL's nextUpdate field"), + 17: _("Out of memory"), + 18: _("Self signed certificate"), + 19: _("Self signed certificate in certificate chain"), + 20: _("Unable to get local issuer certificate"), + 21: _("Unable to verify the first certificate"), + 22: _("Certificate chain too long"), + 23: _("Certificate revoked"), + 24: _("Invalid CA certificate"), + 25: _("Path length constraint exceeded"), + 26: _("Unsupported certificate purpose"), + 27: _("Certificate not trusted"), + 28: _("Certificate rejected"), + 29: _("Subject issuer mismatch"), + 30: _("Authority and subject key identifier mismatch"), + 31: _("Authority and issuer serial number mismatch"), + 32: _("Key usage does not include certificate signing"), + 50: _("Application verification failure") + #100 is for internal usage: host not correct } class CommonConnection: From 381a8f2be857a1a82c3a4202a809e836ca2f79b9 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 7 Feb 2017 20:56:47 +0000 Subject: [PATCH 11/16] Remove unnecessary semicolons. --- src/common/jingle_xtls.py | 2 +- src/history_window.py | 4 ++-- src/ipython_view.py | 2 +- src/logind_listener.py | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/common/jingle_xtls.py b/src/common/jingle_xtls.py index 25e182291..abc2c8170 100644 --- a/src/common/jingle_xtls.py +++ b/src/common/jingle_xtls.py @@ -152,7 +152,7 @@ def send_cert(con, jid_from, sid): certpath = os.path.join(gajim.MY_CERT_DIR, SELF_SIGNED_CERTIFICATE) + \ '.cert' certificate = read_cert(certpath) - iq = nbxmpp.Iq('result', to=jid_from); + iq = nbxmpp.Iq('result', to=jid_from) iq.setAttr('id', sid) pubkey = iq.setTag('pubkeys') diff --git a/src/history_window.py b/src/history_window.py index de3090ed7..659c73f32 100644 --- a/src/history_window.py +++ b/src/history_window.py @@ -663,5 +663,5 @@ class HistoryWindow: gajim.config.set('history_window_x-position', x) gajim.config.set('history_window_y-position', y) - gajim.config.set('history_window_width', width); - gajim.config.set('history_window_height', height); + gajim.config.set('history_window_width', width) + gajim.config.set('history_window_height', height) diff --git a/src/ipython_view.py b/src/ipython_view.py index 12218e1f9..6d9902ff1 100644 --- a/src/ipython_view.py +++ b/src/ipython_view.py @@ -166,7 +166,7 @@ class IterableIPShell: sys.stdout = IPython.utils.io.stdout orig_stdin = sys.stdin - sys.stdin = IPython.utils.io.stdin; + sys.stdin = IPython.utils.io.stdin self.prompt = self.generatePrompt(self.iter_more) self.IP.hooks.pre_prompt_hook() diff --git a/src/logind_listener.py b/src/logind_listener.py index 8b1285ce0..b447fdb1a 100644 --- a/src/logind_listener.py +++ b/src/logind_listener.py @@ -57,7 +57,7 @@ def on_suspend(active): # close the file descriptor and let the computer suspend if fd >= 0: os.close(fd) - fd = -1; + fd = -1 else: # something is wrong, the system is suspending but we don't have # a lock file From 1f9ac730ced97f3c8340bc204409f12918d8bf03 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 7 Feb 2017 21:14:25 +0000 Subject: [PATCH 12/16] Replace long() in remaining python2 code with int(). --- src/common/protocol/bytestream.py | 4 ++-- src/common/stanza_session.py | 2 +- src/remote_control.py | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/common/protocol/bytestream.py b/src/common/protocol/bytestream.py index ce0f471bf..840112f4f 100644 --- a/src/common/protocol/bytestream.py +++ b/src/common/protocol/bytestream.py @@ -435,8 +435,8 @@ class ConnectionSocks5Bytestream(ConnectionBytestream): # it's an IPv6 return True ip_s = ip.split('.') - ip_l = long(ip_s[0])<<24 | long(ip_s[1])<<16 | long(ip_s[2])<<8 | \ - long(ip_s[3]) + ip_l = int(ip_s[0])<<24 | int(ip_s[1])<<16 | int(ip_s[2])<<8 | \ + int(ip_s[3]) # 10/8 if ip_l & (255<<24) == 10<<24: return True diff --git a/src/common/stanza_session.py b/src/common/stanza_session.py index 346815312..523d8f64c 100644 --- a/src/common/stanza_session.py +++ b/src/common/stanza_session.py @@ -553,7 +553,7 @@ class EncryptedStanzaSession(ArchivingStanzaSession): n, e = (crypto.decode_mpi(base64.b64decode( keyvalue.getTagData(x))) for x in ('Modulus', 'Exponent')) - eir_pubkey = RSA.construct((n, long(e))) + eir_pubkey = RSA.construct((n, int(e))) pubkey_o = nbxmpp.c14n.c14n(keyvalue, self._is_buggy_gajim()) else: diff --git a/src/remote_control.py b/src/remote_control.py index 7424170e4..7209b967e 100644 --- a/src/remote_control.py +++ b/src/remote_control.py @@ -698,7 +698,7 @@ class SignalObject(dbus.service.Object): if self._is_first(): win.window.focus(Gtk.get_current_event_time()) else: - win.window.focus(long(time())) + win.window.focus(int(time())) @dbus.service.method(INTERFACE, in_signature='', out_signature='') def show_roster(self): @@ -711,7 +711,7 @@ class SignalObject(dbus.service.Object): if self._is_first(): win.window.focus(Gtk.get_current_event_time()) else: - win.window.focus(long(time())) + win.window.focus(int(time())) @dbus.service.method(INTERFACE, in_signature='', out_signature='') def toggle_ipython(self): From 57fb80f1faf878b7f5d6d40a9f1821b6a7bfe68b Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Wed, 8 Feb 2017 02:12:41 +0000 Subject: [PATCH 13/16] Remove every default argument using [] or {}. --- src/chat_control.py | 5 ++++- src/chat_control_base.py | 16 ++++++++++++++-- src/common/caps_cache.py | 4 +++- src/common/connection.py | 10 +++++++--- src/common/contacts.py | 14 ++++++++++---- src/common/events.py | 31 +++++++++++++++++++++---------- src/common/jingle_content.py | 4 +++- src/common/location_listener.py | 8 ++++++-- src/common/logger.py | 8 ++++++-- src/common/optparser.py | 10 ++++++++-- src/common/rst_xhtml_generator.py | 11 +++++++---- src/conversation_textview.py | 17 ++++++++++++----- src/disco.py | 10 ++++++++-- src/gui_menu_builder.py | 4 +++- src/session.py | 5 ++++- 15 files changed, 116 insertions(+), 41 deletions(-) diff --git a/src/chat_control.py b/src/chat_control.py index 6ecc7b8db..487d995fe 100644 --- a/src/chat_control.py +++ b/src/chat_control.py @@ -1151,7 +1151,7 @@ class ChatControl(ChatControlBase): def print_conversation(self, text, frm='', tim=None, encrypted=False, subject=None, xhtml=None, simple=False, xep0184_id=None, displaymarking=None, msg_log_id=None, correct_id=None, - msg_stanza_id=None, additional_data={}): + msg_stanza_id=None, additional_data=None): """ Print a line in the conversation @@ -1166,6 +1166,9 @@ class ChatControl(ChatControlBase): """ contact = self.contact + if additional_data is None: + additional_data = {} + if frm == 'status': if not gajim.config.get('print_status_in_chats'): return diff --git a/src/chat_control_base.py b/src/chat_control_base.py index b38b6874b..d05d5ceb0 100644 --- a/src/chat_control_base.py +++ b/src/chat_control_base.py @@ -737,7 +737,7 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools): return label def send_message(self, message, keyID='', type_='chat', chatstate=None, - msg_id=None, resource=None, xhtml=None, callback=None, callback_args=[], + msg_id=None, resource=None, xhtml=None, callback=None, callback_args=None, process_commands=True, attention=False): """ Send the given message to the active tab. Doesn't return None if error @@ -745,6 +745,9 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools): if not message or message == '\n': return None + if callback_args is None: + callback_args = [] + if process_commands and self.process_as_command(message): return @@ -807,7 +810,7 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools): other_tags_for_name=[], other_tags_for_time=[], other_tags_for_text=[], count_as_new=True, subject=None, old_kind=None, xhtml=None, simple=False, xep0184_id=None, graphics=True, displaymarking=None, msg_log_id=None, - msg_stanza_id=None, correct_id=None, additional_data={}): + msg_stanza_id=None, correct_id=None, additional_data=None): """ Print 'chat' type messages correct_id = (message_id, correct_id) @@ -819,6 +822,15 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools): if self.was_at_the_end or kind == 'outgoing': end = True + if other_tags_for_name is None: + other_tags_for_name = [] + if other_tags_for_time is None: + other_tags_for_time = [] + if other_tags_for_text is None: + other_tags_for_text = [] + if additional_data is None: + additional_data = {} + textview.print_conversation_line(text, jid, kind, name, tim, other_tags_for_name, other_tags_for_time, other_tags_for_text, subject, old_kind, xhtml, simple=simple, graphics=graphics, diff --git a/src/common/caps_cache.py b/src/common/caps_cache.py index 2d1ed9d2b..9be689575 100644 --- a/src/common/caps_cache.py +++ b/src/common/caps_cache.py @@ -94,13 +94,15 @@ def create_suitable_client_caps(node, caps_hash, hash_method, fjid=None): client_caps = ClientCaps(caps_hash, node, hash_method) return client_caps -def compute_caps_hash(identities, features, dataforms=[], hash_method='sha-1'): +def compute_caps_hash(identities, features, dataforms=None, hash_method='sha-1'): """ Compute caps hash according to XEP-0115, V1.5 dataforms are nbxmpp.DataForms objects as common.dataforms don't allow several values without a field type list-multi """ + if dataforms is None: + dataforms = [] def sort_identities_func(i1, i2): cat1 = i1['category'] cat2 = i2['category'] diff --git a/src/common/connection.py b/src/common/connection.py index 0c5192227..29b66f4f4 100644 --- a/src/common/connection.py +++ b/src/common/connection.py @@ -526,7 +526,9 @@ class CommonConnection: subject, type_, msg_iq, xhtml) def log_message(self, jid, msg, forward_from, session, original_message, - subject, type_, xhtml=None, additional_data={}): + subject, type_, xhtml=None, additional_data=None): + if additional_data is None: + additional_data = {} if not forward_from and session and session.is_loggable(): ji = gajim.get_jid_without_resource(jid) if gajim.config.should_log(self.name, ji): @@ -567,7 +569,7 @@ class CommonConnection: """ raise NotImplementedError - def request_subscription(self, jid, msg='', name='', groups=[], + def request_subscription(self, jid, msg='', name='', groups=None, auto_auth=False): """ To be implemented by derivated classes @@ -2251,10 +2253,12 @@ class Connection(CommonConnection, ConnectionHandlers): p = nbxmpp.Presence(jid, 'unsubscribe') self.connection.send(p) - def request_subscription(self, jid, msg='', name='', groups=[], + def request_subscription(self, jid, msg='', name='', groups=None, auto_auth=False, user_nick=''): if not gajim.account_is_connected(self.name): return + if groups is None: + groups = [] log.debug('subscription request for %s' % jid) if auto_auth: self.jids_for_auto_auth.append(jid) diff --git a/src/common/contacts.py b/src/common/contacts.py index 33a66dd7b..483131e12 100644 --- a/src/common/contacts.py +++ b/src/common/contacts.py @@ -92,12 +92,14 @@ class Contact(CommonContact): """ Information concerning a contact """ - def __init__(self, jid, account, name='', groups=[], show='', status='', + def __init__(self, jid, account, name='', groups=None, show='', status='', sub='', ask='', resource='', priority=0, keyID='', client_caps=None, our_chatstate=None, chatstate=None, last_status_time=None, msg_log_id=None, last_activity_time=None): if not isinstance(jid, str): print('no str') + if groups is None: + groups = [] CommonContact.__init__(self, jid, account, resource, show, status, name, our_chatstate, chatstate, client_caps=client_caps) @@ -244,10 +246,12 @@ class LegacyContactsAPI: del self._accounts[account] self._metacontact_manager.remove_account(account) - def create_contact(self, jid, account, name='', groups=[], show='', + def create_contact(self, jid, account, name='', groups=None, show='', status='', sub='', ask='', resource='', priority=0, keyID='', client_caps=None, our_chatstate=None, chatstate=None, last_status_time=None, last_activity_time=None): + if groups is None: + groups = [] # Use Account object if available account = self._accounts.get(account, account) return Contact(jid=jid, account=account, name=name, groups=groups, @@ -348,12 +352,14 @@ class LegacyContactsAPI: return contact return self.get_highest_prio_contact_from_contacts(contacts) - def get_nb_online_total_contacts(self, accounts=[], groups=[]): + def get_nb_online_total_contacts(self, accounts=None, groups=None): """ Return the number of online contacts and the total number of contacts """ - if accounts == []: + if not accounts: accounts = self.get_accounts() + if groups is None: + groups = [] nbr_online = 0 nbr_total = 0 for account in accounts: diff --git a/src/common/events.py b/src/common/events.py index 4715d1fc2..9322679fd 100644 --- a/src/common/events.py +++ b/src/common/events.py @@ -247,11 +247,13 @@ class Events: event.account = account self.fire_event_added(event) - def remove_events(self, account, jid, event = None, types = []): + def remove_events(self, account, jid, event=None, types=None): """ If event is not specified, remove all events from this jid, optionally only from given type return True if no such event found """ + if types is None: + types = [] if account not in self._events: return True if jid not in self._events[account]: @@ -297,15 +299,19 @@ class Events: self._events[account][new_jid] = self._events[account][old_jid] del self._events[account][old_jid] - def get_nb_events(self, types = [], account = None): + def get_nb_events(self, types=None, account=None): + if types is None: + types = [] return self._get_nb_events(types = types, account = account) - def get_events(self, account, jid = None, types = []): + def get_events(self, account, jid=None, types=None): """ Return all events from the given account of the form {jid1: [], jid2: []}. If jid is given, returns all events from the given jid in a list: [] optionally only from given type """ + if types is None: + types = [] if account not in self._events: return [] if not jid: @@ -342,11 +348,12 @@ class Events: first_event = event return first_event - def _get_nb_events(self, account = None, jid = None, attribute = None, types - = []): + def _get_nb_events(self, account=None, jid=None, attribute=None, types=None): """ Return the number of pending events """ + if types is None: + types = [] nb = 0 if account: accounts = [account] @@ -411,11 +418,13 @@ class Events: first_event = event return first_account, first_jid, first_event - def get_nb_systray_events(self, types = []): + def get_nb_systray_events(self, types=None): """ Return the number of events displayed in roster """ - return self._get_nb_events(attribute = 'systray', types = types) + if types is None: + types = [] + return self._get_nb_events(attribute='systray', types=types) def get_systray_events(self): """ @@ -428,12 +437,14 @@ class Events: events = self.get_systray_events() return self._get_first_event_with_attribute(events) - def get_nb_roster_events(self, account = None, jid = None, types = []): + def get_nb_roster_events(self, account=None, jid=None, types=None): """ Return the number of events displayed in roster """ - return self._get_nb_events(attribute = 'roster', account = account, - jid = jid, types = types) + if types is None: + types = [] + return self._get_nb_events(attribute='roster', account=account, + jid=jid, types=types) def get_roster_events(self): """ diff --git a/src/common/jingle_content.py b/src/common/jingle_content.py index 3442c8ae7..946681afc 100644 --- a/src/common/jingle_content.py +++ b/src/common/jingle_content.py @@ -127,10 +127,12 @@ class JingleContent(object): if candidates: self.add_remote_candidates(candidates) - def __content(self, payload=[]): + def __content(self, payload=None): """ Build a XML content-wrapper for our data """ + if payload is None: + payload = [] return nbxmpp.Node('content', attrs={'name': self.name, 'creator': self.creator}, payload=payload) diff --git a/src/common/location_listener.py b/src/common/location_listener.py index 88c12c8f9..6542244f4 100644 --- a/src/common/location_listener.py +++ b/src/common/location_listener.py @@ -89,9 +89,11 @@ class LocationListener: def shut_down(self): pass - def _on_geoclue_address_changed(self, timestamp=None, address={}, + def _on_geoclue_address_changed(self, timestamp=None, address=None, accuracy=None): # update data with info we just received + if address is None: + address = {} for field in ['country', 'countrycode', 'locality', 'postalcode', 'region', 'street']: self._data[field] = address.get(field, None) @@ -102,8 +104,10 @@ class LocationListener: self._data['accuracy'] = accuracy[1] self._send_location() - def _on_geoclue_position_changed(self, fields=[], timestamp=None, lat=None, + def _on_geoclue_position_changed(self, fields=None, timestamp=None, lat=None, lon=None, alt=None, accuracy=None): + if fields is None: + fields = [] # update data with info we just received _dict = {'lat': lat, 'lon': lon, 'alt': alt} for field in _dict: diff --git a/src/common/logger.py b/src/common/logger.py index 1a8781728..78f384c29 100644 --- a/src/common/logger.py +++ b/src/common/logger.py @@ -490,7 +490,7 @@ class Logger: all_messages.append(results[0]) return all_messages - def write(self, kind, jid, message=None, show=None, tim=None, subject=None, additional_data={}): + def write(self, kind, jid, message=None, show=None, tim=None, subject=None, additional_data=None): """ Write a row (status, gcstatus, message etc) to logs database @@ -504,6 +504,8 @@ class Logger: ROOM_JID/nick if pm-related. """ + if additional_data is None: + additional_data = {} if self.jids_already_in == []: # only happens if we just created the db self.open_db() @@ -1101,7 +1103,9 @@ class Logger: (account_jid_id,)) self._timeout_commit() - def save_if_not_exists(self, with_, direction, tim, msg='', nick=None, additional_data={}): + def save_if_not_exists(self, with_, direction, tim, msg='', nick=None, additional_data=None): + if additional_data is None: + additional_data = {} if tim: time_col = float(tim) else: diff --git a/src/common/optparser.py b/src/common/optparser.py index 4bfed3e2e..c13ee79da 100644 --- a/src/common/optparser.py +++ b/src/common/optparser.py @@ -241,7 +241,8 @@ class OptionsParser: caps_cache.capscache.initialize_from_db() - def assert_unread_msgs_table_exists(self): + @staticmethod + def assert_unread_msgs_table_exists(): """ Create table unread_messages if there is no such table """ @@ -265,7 +266,12 @@ class OptionsParser: pass con.close() - def update_ft_proxies(self, to_remove=[], to_add=[]): + @staticmethod + def update_ft_proxies(to_remove=None, to_add=None): + if to_remove is None: + to_remove = [] + if to_add is None: + to_add = [] for account in gajim.config.get_per('accounts'): proxies_str = gajim.config.get_per('accounts', account, 'file_transfer_proxies') diff --git a/src/common/rst_xhtml_generator.py b/src/common/rst_xhtml_generator.py index 16b1d3a6d..77d73e562 100644 --- a/src/common/rst_xhtml_generator.py +++ b/src/common/rst_xhtml_generator.py @@ -62,7 +62,9 @@ else: should return the validated text, or raise ValueError """ def uri_reference_role(role, rawtext, text, lineno, inliner, - options={}, content=[]): + options=None, content=None): + if options is None: + options = {} try: valid_text = validator(text) except ValueError as e: @@ -102,9 +104,10 @@ else: It reuses the docutils.core.Publisher class, which means it is *not* threadsafe. """ - def __init__(self, settings_spec=None, - settings_overrides=dict(report_level=5, halt_level=5), - config_section='general'): + def __init__(self, settings_spec=None, settings_overrides=None, + config_section='general'): + if settings_overrides is None: + settings_overrides = {'report_level': 5, 'halt_level': 5} self.pub = Publisher(reader=None, parser=None, writer=None, settings=None, source_class=io.StringInput, diff --git a/src/conversation_textview.py b/src/conversation_textview.py index 0c2b2a452..065f59119 100644 --- a/src/conversation_textview.py +++ b/src/conversation_textview.py @@ -448,9 +448,10 @@ class ConversationTextview(GObject.GObject): self.auto_scrolling = False return False # when called in an idle_add, just do it once - def bring_scroll_to_end(self, diff_y = 0, - use_smooth=gajim.config.get('use_smooth_scrolling')): + def bring_scroll_to_end(self, diff_y=0, use_smooth=None): ''' scrolls to the end of textview if end is not visible ''' + if use_smooth is None: + use_smooth = gajim.config.get('use_smooth_scrolling') buffer_ = self.tv.get_buffer() end_iter = buffer_.get_end_iter() end_rect = self.tv.get_iter_location(end_iter) @@ -1014,7 +1015,7 @@ class ConversationTextview(GObject.GObject): helpers.launch_browser_mailer(kind, word) def detect_and_print_special_text(self, otext, other_tags, graphics=True, - iter_=None, additional_data={}): + iter_=None, additional_data=None): """ Detect special text (emots & links & formatting), print normal text before any special text it founds, then print special text (that happens @@ -1024,6 +1025,8 @@ class ConversationTextview(GObject.GObject): """ if not otext: return + if additional_data is None: + additional_data = {} buffer_ = self.tv.get_buffer() if other_tags: insert_tags_func = buffer_.insert_with_tags_by_name @@ -1079,11 +1082,13 @@ class ConversationTextview(GObject.GObject): return end_iter def print_special_text(self, special_text, other_tags, graphics=True, - iter_=None, additional_data={}): + iter_=None, additional_data=None): """ Is called by detect_and_print_special_text and prints special text (emots, links, formatting) """ + if additional_data is None: + additional_data = {} # PluginSystem: adding GUI extension point for ConversationTextview self.plugin_modified = False @@ -1538,10 +1543,12 @@ class ConversationTextview(GObject.GObject): self.print_empty_line(end_iter) def print_real_text(self, text, text_tags=[], name=None, xhtml=None, - graphics=True, mark=None, additional_data={}): + graphics=True, mark=None, additional_data=None): """ Add normal and special text. call this to add text """ + if additional_data is None: + additional_data = {} buffer_ = self.tv.get_buffer() if not mark: iter_ = buffer_.get_end_iter() diff --git a/src/disco.py b/src/disco.py index 3519a3af5..de8b9d8c0 100644 --- a/src/disco.py +++ b/src/disco.py @@ -299,10 +299,12 @@ class ServicesCache: if not self._cbs[cbkey]: del self._cbs[cbkey] - def get_icon(self, identities = [], addr=''): + def get_icon(self, identities=None, addr=''): """ Return the icon for an agent """ + if identities is None: + identities = [] # Grab the first identity with an icon quiet = False for identity in identities: @@ -334,10 +336,14 @@ class ServicesCache: _icon_cache['jabber'] = pix return pix - def get_browser(self, identities=[], features=[]): + def get_browser(self, identities=None, features=None): """ Return the browser class for an agent """ + if identities is None: + identities = [] + if features is None: + features = [] # First pass, we try to find a ToplevelAgentBrowser for identity in identities: try: diff --git a/src/gui_menu_builder.py b/src/gui_menu_builder.py index 5a643c6e1..1865746af 100644 --- a/src/gui_menu_builder.py +++ b/src/gui_menu_builder.py @@ -59,13 +59,15 @@ def build_resources_submenu(contacts, account, action, room_jid=None, return sub_menu -def build_invite_submenu(invite_menuitem, list_, ignore_rooms=[], +def build_invite_submenu(invite_menuitem, list_, ignore_rooms=None, show_bookmarked=False, force_resource=False): """ list_ in a list of (contact, account) force_resource means we want to send invitation even if there is only one resource """ + if ignore_rooms is None: + ignore_rooms = [] roster = gajim.interface.roster # used if we invite only one contact with several resources contact_list = [] diff --git a/src/session.py b/src/session.py index 84f8c674d..fe568ba75 100644 --- a/src/session.py +++ b/src/session.py @@ -267,13 +267,16 @@ class ChatControlSession(stanza_session.EncryptedStanzaSession): def roster_message(self, jid, msg, tim, encrypted=False, msg_type='', subject=None, resource='', msg_log_id=None, user_nick='', xhtml=None, - form_node=None, displaymarking=None, additional_data={}): + form_node=None, displaymarking=None, additional_data=None): """ Display the message or show notification in the roster """ contact = None fjid = jid + if additional_data is None: + additional_data = {} + # Try to catch the contact with correct resource if resource: fjid = jid + '/' + resource From ad9370afa8e89cbeee669c5c9dadf798c81876fd Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Wed, 8 Feb 2017 02:49:33 +0000 Subject: [PATCH 14/16] Fix a bunch of issues in common.jingle*. --- src/common/gajim.py | 4 + src/common/jingle.py | 27 ++-- src/common/jingle_content.py | 93 +++++------ src/common/jingle_ft.py | 214 +++++++++++++------------ src/common/jingle_ftstates.py | 69 ++++---- src/common/jingle_rtp.py | 100 +++++++----- src/common/jingle_session.py | 283 ++++++++++++++++++--------------- src/common/jingle_transport.py | 135 +++++++++------- src/common/jingle_xtls.py | 42 ++--- 9 files changed, 527 insertions(+), 440 deletions(-) diff --git a/src/common/gajim.py b/src/common/gajim.py index b738b018f..1346d10ea 100644 --- a/src/common/gajim.py +++ b/src/common/gajim.py @@ -142,6 +142,10 @@ SHOW_LIST = ['offline', 'connecting', 'online', 'chat', 'away', 'xa', 'dnd', # zeroconf account name ZEROCONF_ACC_NAME = 'Local' +# These will be set in gajim.gui_interface. +idlequeue = None +socks5queue = None + HAVE_ZEROCONF = True try: __import__('avahi') diff --git a/src/common/jingle.py b/src/common/jingle.py index 95b6d6b1e..8a915a02b 100644 --- a/src/common/jingle.py +++ b/src/common/jingle.py @@ -28,19 +28,21 @@ Handles the jingle signalling protocol # * config: # - codecs +import logging + import nbxmpp from common import helpers from common import gajim from common.jingle_session import JingleSession, JingleStates -if gajim.HAVE_FARSTREAM: - from common.jingle_rtp import JingleAudio, JingleVideo from common.jingle_ft import JingleFileTransfer from common.jingle_transport import JingleTransportSocks5, JingleTransportIBB +if gajim.HAVE_FARSTREAM: + from common.jingle_rtp import JingleAudio, JingleVideo -import logging logger = logging.getLogger('gajim.c.jingle') + class ConnectionJingle(object): """ This object depends on that it is a part of Connection class. @@ -80,7 +82,7 @@ class ConnectionJingle(object): try: jid = helpers.get_full_jid_from_iq(stanza) except helpers.InvalidFormat: - logger.warn('Invalid JID: %s, ignoring it' % stanza.getFrom()) + logger.warning('Invalid JID: %s, ignoring it', stanza.getFrom()) return id_ = stanza.getID() if (jid, id_) in self.__iq_responses.keys(): @@ -102,14 +104,14 @@ class ConnectionJingle(object): if sid not in self._sessions: #TODO: tie-breaking and other things... newjingle = JingleSession(con=self, weinitiate=False, jid=jid, - iq_id=id_, sid=sid) + iq_id=id_, sid=sid) self._sessions[sid] = newjingle # we already have such session in dispatcher... self._sessions[sid].collect_iq_id(id_) self._sessions[sid].on_stanza(stanza) # Delete invalid/unneeded sessions if sid in self._sessions and \ - self._sessions[sid].state == JingleStates.ended: + self._sessions[sid].state == JingleStates.ENDED: self.delete_jingle_session(sid) raise nbxmpp.NodeProcessed @@ -132,20 +134,20 @@ class ConnectionJingle(object): jingle = self.get_jingle_session(jid, media='audio') if jingle: jingle.add_content('video', JingleVideo(jingle, in_xid=in_xid, - out_xid=out_xid)) + out_xid=out_xid)) else: jingle = JingleSession(self, weinitiate=True, jid=jid) self._sessions[jingle.sid] = jingle jingle.add_content('video', JingleVideo(jingle, in_xid=in_xid, - out_xid=out_xid)) + out_xid=out_xid)) jingle.start_session() return jingle.sid def start_file_transfer(self, jid, file_props, request=False): - logger.info("start file transfer with file: %s" % file_props) + logger.info("start file transfer with file: %s", file_props) contact = gajim.contacts.get_contact_with_highest_priority(self.name, - gajim.get_jid_without_resource(jid)) - if gajim.contacts.is_gc_contact(self.name,jid): + gajim.get_jid_without_resource(jid)) + if gajim.contacts.is_gc_contact(self.name, jid): gcc = jid.split('/') if len(gcc) == 2: contact = gajim.contacts.get_gc_contact(self.name, gcc[0], gcc[1]) @@ -162,7 +164,8 @@ class ConnectionJingle(object): elif contact.supports(nbxmpp.NS_JINGLE_IBB): transport = JingleTransportIBB() c = JingleFileTransfer(jingle, transport=transport, - file_props=file_props, use_security=use_security) + file_props=file_props, + use_security=use_security) file_props.algo = self.__hash_support(contact) jingle.add_content('file' + helpers.get_random_string_16(), c) jingle.start_session() diff --git a/src/common/jingle_content.py b/src/common/jingle_content.py index 946681afc..ee665d293 100644 --- a/src/common/jingle_content.py +++ b/src/common/jingle_content.py @@ -37,7 +37,7 @@ class JingleContentSetupException(Exception): """ -class JingleContent(object): +class JingleContent: """ An abstraction of content in Jingle sessions """ @@ -48,8 +48,8 @@ class JingleContent(object): # will be filled by JingleSession.add_content() # don't uncomment these lines, we will catch more buggy code then # (a JingleContent not added to session shouldn't send anything) - #self.creator = None - #self.name = None + self.creator = None + self.name = None self.accepted = False self.sent = False self.negotiated = False @@ -59,35 +59,39 @@ class JingleContent(object): self.senders = 'both' #FIXME self.allow_sending = True # Used for stream direction, attribute 'senders' + # These were found by the Politie + self.file_props = None + self.use_security = None + self.callbacks = { - # these are called when *we* get stanzas - 'content-accept': [self.__on_transport_info, - self.__on_content_accept], - 'content-add': [self.__on_transport_info], - 'content-modify': [], - 'content-reject': [], - 'content-remove': [], - 'description-info': [], - 'security-info': [], - 'session-accept': [self.__on_transport_info, - self.__on_content_accept], - 'session-info': [], - 'session-initiate': [self.__on_transport_info], - 'session-terminate': [], - 'transport-info': [self.__on_transport_info], - 'transport-replace': [self.__on_transport_replace], - 'transport-accept': [], - 'transport-reject': [], - 'iq-result': [], - 'iq-error': [], - # these are called when *we* sent these stanzas - 'content-accept-sent': [self.__fill_jingle_stanza, - self.__on_content_accept], - 'content-add-sent': [self.__fill_jingle_stanza], - 'session-initiate-sent': [self.__fill_jingle_stanza], - 'session-accept-sent': [self.__fill_jingle_stanza, - self.__on_content_accept], - 'session-terminate-sent': [], + # these are called when *we* get stanzas + 'content-accept': [self.__on_transport_info, + self.__on_content_accept], + 'content-add': [self.__on_transport_info], + 'content-modify': [], + 'content-reject': [], + 'content-remove': [], + 'description-info': [], + 'security-info': [], + 'session-accept': [self.__on_transport_info, + self.__on_content_accept], + 'session-info': [], + 'session-initiate': [self.__on_transport_info], + 'session-terminate': [], + 'transport-info': [self.__on_transport_info], + 'transport-replace': [self.__on_transport_replace], + 'transport-accept': [], + 'transport-reject': [], + 'iq-result': [], + 'iq-error': [], + # these are called when *we* sent these stanzas + 'content-accept-sent': [self.__fill_jingle_stanza, + self.__on_content_accept], + 'content-add-sent': [self.__fill_jingle_stanza], + 'session-initiate-sent': [self.__fill_jingle_stanza], + 'session-accept-sent': [self.__fill_jingle_stanza, + self.__on_content_accept], + 'session-terminate-sent': [], } def is_ready(self): @@ -134,8 +138,8 @@ class JingleContent(object): if payload is None: payload = [] return nbxmpp.Node('content', - attrs={'name': self.name, 'creator': self.creator}, - payload=payload) + attrs={'name': self.name, 'creator': self.creator}, + payload=payload) def send_candidate(self, candidate): """ @@ -191,17 +195,16 @@ class JingleContent(object): file_tag.addChild(node=node) if self.file_props.type_ == 'r': if self.file_props.hash_: - h = file_tag.addChild('hash', attrs={ - 'algo': self.file_props.algo}, namespace=nbxmpp.NS_HASHES, - payload=self.file_props.hash_) + file_tag.addChild('hash', attrs={'algo': self.file_props.algo}, + namespace=nbxmpp.NS_HASHES, + payload=self.file_props.hash_) else: # if the file is less than 10 mb, then it is small # lets calculate it right away - if self.file_props.size < 10000000 and not \ - self.file_props.hash_: - h = self._calcHash() - if h: - file_tag.addChild(node=h) + if self.file_props.size < 10000000 and not self.file_props.hash_: + hash_data = content._compute_hash() + if hash_data: + file_tag.addChild(node=hash_data) pjid = gajim.get_jid_without_resource(self.session.peerjid) file_info = {'name' : self.file_props.name, 'file-name' : self.file_props.file_name, @@ -223,9 +226,9 @@ class JingleContent(object): cert = load_cert_file(certpath) if cert: try: - digest_algo = cert.get_signature_algorithm().decode('utf-8' - ).split('With')[0] - except AttributeError as e: + digest_algo = (cert.get_signature_algorithm() + .decode('utf-8').split('With')[0]) + except AttributeError: # Old py-OpenSSL is missing get_signature_algorithm digest_algo = "sha256" security.addChild('fingerprint').addData(cert.digest( @@ -240,5 +243,3 @@ class JingleContent(object): def destroy(self): self.callbacks = None del self.session.contents[(self.creator, self.name)] - - diff --git a/src/common/jingle_ft.py b/src/common/jingle_ft.py index 091025e21..bc7ee385c 100644 --- a/src/common/jingle_ft.py +++ b/src/common/jingle_ft.py @@ -19,41 +19,47 @@ Handles Jingle File Transfer (XEP 0234) """ -import os import hashlib -from common import gajim +import logging +import os +import threading +from enum import IntEnum import nbxmpp +from common import gajim from common import configpaths -from . import jingle_xtls +from common import jingle_xtls from common.jingle_content import contents, JingleContent -from common.jingle_transport import * +from common.jingle_transport import JingleTransportSocks5, TransportType from common import helpers from common.connection_handlers_events import FileRequestReceivedEvent -import threading -import logging -from common.jingle_ftstates import * +from common.jingle_ftstates import ( + StateInitialized, StateCandSent, StateCandReceived, StateTransfering, + StateCandSentAndRecv, StateTransportReplace) + log = logging.getLogger('gajim.c.jingle_ft') -STATE_NOT_STARTED = 0 -STATE_INITIALIZED = 1 -# We send the candidates and we are waiting for a reply -STATE_CAND_SENT = 2 -# We received the candidates and we are waiting to reply -STATE_CAND_RECEIVED = 3 -# We have sent and received the candidates -# This also includes any candidate-error received or sent -STATE_CAND_SENT_AND_RECEIVED = 4 -STATE_TRANSPORT_REPLACE = 5 -# We are transfering the file -STATE_TRANSFERING = 6 + +class State(IntEnum): + NOT_STARTED = 0 + INITIALIZED = 1 + # We send the candidates and we are waiting for a reply + CAND_SENT = 2 + # We received the candidates and we are waiting to reply + CAND_RECEIVED = 3 + # We have sent and received the candidates + # This also includes any candidate-error received or sent + CAND_SENT_AND_RECEIVED = 4 + TRANSPORT_REPLACE = 5 + # We are transfering the file + TRANSFERING = 6 class JingleFileTransfer(JingleContent): def __init__(self, session, transport=None, file_props=None, - use_security=False): + use_security=False): JingleContent.__init__(self, session, transport) - log.info("transport value: %s" % transport) + log.info("transport value: %s", transport) # events we might be interested in self.callbacks['session-initiate'] += [self.__on_session_initiate] self.callbacks['session-initiate-sent'] += [ @@ -85,29 +91,31 @@ class JingleFileTransfer(JingleContent): self.file_props.sid = session.sid self.file_props.transfered_size = [] self.file_props.transport_sid = self.transport.sid - log.info("FT request: %s" % file_props) + log.info("FT request: %s", file_props) if transport is None: self.transport = JingleTransportSocks5() self.transport.set_connection(session.connection) self.transport.set_file_props(self.file_props) self.transport.set_our_jid(session.ourjid) - log.info('ourjid: %s' % session.ourjid) + log.info('ourjid: %s', session.ourjid) self.session = session self.media = 'file' self.nominated_cand = {} if gajim.contacts.is_gc_contact(session.connection.name, - session.peerjid): + session.peerjid): roomjid = session.peerjid.split('/')[0] dstaddr = hashlib.sha1(('%s%s%s' % (self.file_props.sid, - session.ourjid, roomjid)).encode('utf-8')).hexdigest() + session.ourjid, roomjid)) + .encode('utf-8')).hexdigest() self.file_props.dstaddr = dstaddr - self.state = STATE_NOT_STARTED - self.states = {STATE_INITIALIZED : StateInitialized(self), - STATE_CAND_SENT : StateCandSent(self), - STATE_CAND_RECEIVED : StateCandReceived(self), - STATE_TRANSFERING : StateTransfering(self), - STATE_TRANSPORT_REPLACE : StateTransportReplace(self), - STATE_CAND_SENT_AND_RECEIVED : StateCandSentAndRecv(self) + self.state = State.NOT_STARTED + self.states = { + State.INITIALIZED : StateInitialized(self), + State.CAND_SENT : StateCandSent(self), + State.CAND_RECEIVED : StateCandReceived(self), + State.TRANSFERING : StateTransfering(self), + State.TRANSPORT_REPLACE : StateTransportReplace(self), + State.CAND_SENT_AND_RECEIVED : StateCandSentAndRecv(self) } if jingle_xtls.PYOPENSSL_PRESENT: @@ -129,8 +137,10 @@ class JingleFileTransfer(JingleContent): def __on_session_initiate(self, stanza, content, error, action): log.debug("Jingle FT request received") gajim.nec.push_incoming_event(FileRequestReceivedEvent(None, - conn=self.session.connection, stanza=stanza, jingle_content=content, - FT_content=self)) + conn=self.session.connection, + stanza=stanza, + jingle_content=content, + FT_content=self)) if self.session.request: # accept the request self.session.approve_content(self.media, self.name) @@ -141,10 +151,11 @@ class JingleFileTransfer(JingleContent): def __send_hash(self): # Send hash in a session info - checksum = nbxmpp.Node(tag='checksum', payload=[nbxmpp.Node(tag='file', - payload=[self._calcHash()])]) + checksum = nbxmpp.Node(tag='checksum', + payload=[nbxmpp.Node(tag='file', + payload=[self._compute_hash()])]) checksum.setNamespace(nbxmpp.NS_JINGLE_FILE_TRANSFER) - self.session.__session_info(checksum ) + self.session.__session_info(checksum) pjid = gajim.get_jid_without_resource(self.session.peerjid) file_info = {'name' : self.file_props.name, 'file-name' : self.file_props.file_name, @@ -155,13 +166,13 @@ class JingleFileTransfer(JingleContent): } self.session.connection.set_file_info(file_info) - def _calcHash(self): + def _compute_hash(self): # Caculates the hash and returns a xep-300 hash stanza - if self.file_props.algo == None: + if self.file_props.algo is None: return try: file_ = open(self.file_props.file_name, 'rb') - except: + except IOError: # can't open file return h = nbxmpp.Hashes() @@ -192,30 +203,31 @@ class JingleFileTransfer(JingleContent): fingerprint = fingerprint.getData() self.x509_fingerprint = fingerprint if not jingle_xtls.check_cert(gajim.get_jid_without_resource( - self.session.responder), fingerprint): + self.session.responder), fingerprint): id_ = jingle_xtls.send_cert_request(con, - self.session.responder) + self.session.responder) jingle_xtls.key_exchange_pend(id_, - self.continue_session_accept, [stanza]) + self.continue_session_accept, + [stanza]) raise nbxmpp.NodeProcessed self.continue_session_accept(stanza) def continue_session_accept(self, stanza): con = self.session.connection - if self.state == STATE_TRANSPORT_REPLACE: + if self.state == State.TRANSPORT_REPLACE: # If we are requesting we don't have the file if self.session.werequest: raise nbxmpp.NodeProcessed # We send the file - self.__state_changed(STATE_TRANSFERING) + self.__state_changed(State.TRANSFERING) raise nbxmpp.NodeProcessed self.file_props.streamhosts = self.transport.remote_candidates # Calculate file hash in a new thread # if we haven't sent the hash already. if self.file_props.hash_ is None and self.file_props.algo and \ - not self.werequest: - self.hashThread = threading.Thread(target=self.__send_hash) - self.hashThread.start() + not self.werequest: + self.hash_thread = threading.Thread(target=self.__send_hash) + self.hash_thread.start() for host in self.file_props.streamhosts: host['initiator'] = self.session.initiator host['target'] = self.session.responder @@ -225,11 +237,13 @@ class JingleFileTransfer(JingleContent): fingerprint = 'client' if self.transport.type_ == TransportType.SOCKS5: gajim.socks5queue.connect_to_hosts(self.session.connection.name, - self.file_props.sid, self.on_connect, - self._on_connect_error, fingerprint=fingerprint, - receiving=False) + self.file_props.sid, + self.on_connect, + self._on_connect_error, + fingerprint=fingerprint, + receiving=False) raise nbxmpp.NodeProcessed - self.__state_changed(STATE_TRANSFERING) + self.__state_changed(State.TRANSFERING) raise nbxmpp.NodeProcessed def __on_session_terminate(self, stanza, content, error, action): @@ -249,78 +263,78 @@ class JingleFileTransfer(JingleContent): def __on_transport_info(self, stanza, content, error, action): log.info("__on_transport_info") - candError = content.getTag('transport').getTag('candidate-error') - candUsed = content.getTag('transport').getTag('candidate-used') - if (candError or candUsed) and \ - self.state >= STATE_CAND_SENT_AND_RECEIVED: + cand_error = content.getTag('transport').getTag('candidate-error') + cand_used = content.getTag('transport').getTag('candidate-used') + if (cand_error or cand_used) and \ + self.state >= State.CAND_SENT_AND_RECEIVED: raise nbxmpp.NodeProcessed - if candError: + if cand_error: if not gajim.socks5queue.listener.connections: gajim.socks5queue.listener.disconnect() self.nominated_cand['peer-cand'] = False - if self.state == STATE_CAND_SENT: + if self.state == State.CAND_SENT: if not self.nominated_cand['our-cand'] and \ not self.nominated_cand['peer-cand']: if not self.weinitiate: return - self.__state_changed(STATE_TRANSPORT_REPLACE) + self.__state_changed(State.TRANSPORT_REPLACE) else: response = stanza.buildReply('result') response.delChild(response.getQuery()) self.session.connection.connection.send(response) - self.__state_changed(STATE_TRANSFERING) + self.__state_changed(State.TRANSFERING) raise nbxmpp.NodeProcessed else: - args = {'candError' : True} - self.__state_changed(STATE_CAND_RECEIVED, args) + args = {'cand_error' : True} + self.__state_changed(State.CAND_RECEIVED, args) return - if candUsed: - streamhost_cid = candUsed.getAttr('cid') + if cand_used: + streamhost_cid = cand_used.getAttr('cid') streamhost_used = None for cand in self.transport.candidates: if cand['candidate_id'] == streamhost_cid: streamhost_used = cand break - if streamhost_used == None or streamhost_used['type'] == 'proxy': + if streamhost_used is None or streamhost_used['type'] == 'proxy': if gajim.socks5queue.listener and \ not gajim.socks5queue.listener.connections: gajim.socks5queue.listener.disconnect() if content.getTag('transport').getTag('activated'): - self.state = STATE_TRANSFERING + self.state = State.TRANSFERING jid = gajim.get_jid_without_resource(self.session.ourjid) gajim.socks5queue.send_file(self.file_props, - self.session.connection.name, 'client') + self.session.connection.name, 'client') return - args = {'content' : content, - 'sendCand' : False} - if self.state == STATE_CAND_SENT: - self.__state_changed(STATE_CAND_SENT_AND_RECEIVED, args) - self.__state_changed(STATE_TRANSFERING) + args = {'content': content, + 'sendCand': False} + if self.state == State.CAND_SENT: + self.__state_changed(State.CAND_SENT_AND_RECEIVED, args) + self.__state_changed(State.TRANSFERING) raise nbxmpp.NodeProcessed else: - self.__state_changed(STATE_CAND_RECEIVED, args) + self.__state_changed(State.CAND_RECEIVED, args) def __on_iq_result(self, stanza, content, error, action): log.info("__on_iq_result") - if self.state == STATE_NOT_STARTED: - self.__state_changed(STATE_INITIALIZED) - elif self.state == STATE_CAND_SENT_AND_RECEIVED: + if self.state == State.NOT_STARTED: + self.__state_changed(State.INITIALIZED) + elif self.state == State.CAND_SENT_AND_RECEIVED: if not self.nominated_cand['our-cand'] and \ not self.nominated_cand['peer-cand']: if not self.weinitiate: return - self.__state_changed(STATE_TRANSPORT_REPLACE) + self.__state_changed(State.TRANSPORT_REPLACE) return # initiate transfer - self.__state_changed(STATE_TRANSFERING) + self.__state_changed(State.TRANSFERING) def __transport_setup(self, stanza=None, content=None, error=None, - action=None): + action=None): # Sets up a few transport specific things for the file transfer if self.transport.type_ == TransportType.IBB: # No action required, just set the state to transfering - self.state = STATE_TRANSFERING + self.state = State.TRANSFERING else: self._listen_host() @@ -334,19 +348,19 @@ class JingleFileTransfer(JingleContent): args = {'streamhost' : streamhost, 'sendCand' : True} self.nominated_cand['our-cand'] = streamhost - self.__sendCand(args) + self.__send_candidate(args) def _on_connect_error(self, sid): log.info('connect error, sid=' + sid) args = {'candError' : True, 'sendCand' : True} - self.__sendCand(args) + self.__send_candidate(args) - def __sendCand(self, args): - if self.state == STATE_CAND_RECEIVED: - self.__state_changed(STATE_CAND_SENT_AND_RECEIVED, args) + def __send_candidate(self, args): + if self.state == State.CAND_RECEIVED: + self.__state_changed(State.CAND_SENT_AND_RECEIVED, args) else: - self.__state_changed(STATE_CAND_SENT, args) + self.__state_changed(State.CAND_SENT, args) def _store_socks5_sid(self, sid, hash_id): # callback from socsk5queue.start_listener @@ -356,44 +370,40 @@ class JingleFileTransfer(JingleContent): receiver = self.file_props.receiver sender = self.file_props.sender sha_str = helpers.get_auth_sha(self.file_props.sid, sender, - receiver) + receiver) self.file_props.sha_str = sha_str port = gajim.config.get('file_transfers_port') fingerprint = None if self.use_security: fingerprint = 'server' - if self.weinitiate: - listener = gajim.socks5queue.start_listener(port, sha_str, - self._store_socks5_sid, self.file_props, - fingerprint=fingerprint, typ='sender') - else: - listener = gajim.socks5queue.start_listener(port, sha_str, - self._store_socks5_sid, self.file_props, - fingerprint=fingerprint, typ='receiver') + listener = gajim.socks5queue.start_listener(port, sha_str, + self._store_socks5_sid, + self.file_props, + fingerprint=fingerprint, + typ='sender' if self.weinitiate else 'receiver') if not listener: # send error message, notify the user return - def isOurCandUsed(self): + def is_our_candidate_used(self): ''' If this method returns true then the candidate we nominated will be used, if false, the candidate nominated by peer will be used ''' - if self.nominated_cand['peer-cand'] == False: + if not self.nominated_cand['peer-cand']: return True - if self.nominated_cand['our-cand'] == False: + if not self.nominated_cand['our-cand']: return False peer_pr = int(self.nominated_cand['peer-cand']['priority']) our_pr = int(self.nominated_cand['our-cand']['priority']) if peer_pr != our_pr: return our_pr > peer_pr - else: - return self.weinitiate + return self.weinitiate - def start_IBB_transfer(self): + def start_ibb_transfer(self): if self.file_props.type_ == 's': - self.__state_changed(STATE_TRANSFERING) + self.__state_changed(State.TRANSFERING) def get_content(desc): diff --git a/src/common/jingle_ftstates.py b/src/common/jingle_ftstates.py index d2329a0d3..3d5d6b9dc 100644 --- a/src/common/jingle_ftstates.py +++ b/src/common/jingle_ftstates.py @@ -13,11 +13,14 @@ ## You should have received a copy of the GNU General Public License ## along with Gajim. If not, see . -from common import gajim import nbxmpp -from common.jingle_transport import * +from common import gajim +from common.jingle_transport import TransportType from common.socks5 import Socks5ReceiverClient, Socks5SenderClient +import logging +log = logging.getLogger('gajim.c.jingle_ftstates') + class JingleFileTransferStates: ''' @@ -31,7 +34,7 @@ class JingleFileTransferStates: ''' This method MUST be overriden by a subclass ''' - raise Exception('This is an abstract method!!') + raise NotImplementedError('This is an abstract method!') class StateInitialized(JingleFileTransferStates): @@ -50,8 +53,10 @@ class StateInitialized(JingleFileTransferStates): fingerprint = 'client' # Connect to the candidate host, on success call on_connect method gajim.socks5queue.connect_to_hosts(self.jft.session.connection.name, - self.jft.file_props.sid, self.jft.on_connect, - self.jft._on_connect_error, fingerprint=fingerprint) + self.jft.file_props.sid, + self.jft.on_connect, + self.jft._on_connect_error, + fingerprint=fingerprint) class StateCandSent(JingleFileTransferStates): @@ -59,7 +64,7 @@ class StateCandSent(JingleFileTransferStates): This state sends our nominated candidate ''' - def _sendCand(self, args): + def _send_candidate(self, args): if 'candError' in args: self.jft.nominated_cand['our-cand'] = False self.jft.send_error_candidate() @@ -80,16 +85,16 @@ class StateCandSent(JingleFileTransferStates): self.jft.session.send_transport_info(content) def action(self, args=None): - self._sendCand(args) + self._send_candidate(args) -class StateCandReceived(JingleFileTransferStates): +class StateCandReceived(JingleFileTransferStates): ''' This state happens when we receive a candidate. It takes the arguments: canError if we receive a candidate-error ''' - def _recvCand(self, args): + def _recv_candidate(self, args): if 'candError' in args: return content = args['content'] @@ -100,17 +105,17 @@ class StateCandReceived(JingleFileTransferStates): if cand['candidate_id'] == streamhost_cid: streamhost_used = cand break - if streamhost_used == None: + if streamhost_used is None: log.info("unknow streamhost") return # We save the candidate nominated by peer self.jft.nominated_cand['peer-cand'] = streamhost_used def action(self, args=None): - self._recvCand(args) + self._recv_candidate(args) -class StateCandSentAndRecv( StateCandSent, StateCandReceived): +class StateCandSentAndRecv(StateCandSent, StateCandReceived): ''' This state happens when we have received and sent the candidates. It takes the boolean argument: sendCand in order to decide whether @@ -119,9 +124,9 @@ class StateCandSentAndRecv( StateCandSent, StateCandReceived): def action(self, args=None): if args['sendCand']: - self._sendCand(args) + self._send_candidate(args) else: - self._recvCand(args) + self._recv_candidate(args) class StateTransportReplace(JingleFileTransferStates): @@ -139,16 +144,16 @@ class StateTransfering(JingleFileTransferStates): we have. ''' - def __start_IBB_transfer(self, con): + def _start_ibb_transfer(self, con): self.jft.file_props.transport_sid = self.jft.transport.sid fp = open(self.jft.file_props.file_name, 'r') - con.OpenStream( self.jft.file_props.sid, self.jft.session.peerjid, fp, - blocksize=4096) + con.OpenStream(self.jft.file_props.sid, self.jft.session.peerjid, fp, + blocksize=4096) - def __start_SOCK5_transfer(self): + def _start_sock5_transfer(self): # It tells wether we start the transfer as client or server mode = None - if self.jft.isOurCandUsed(): + if self.jft.is_our_candidate_used(): mode = 'client' streamhost_used = self.jft.nominated_cand['our-cand'] gajim.socks5queue.remove_server(self.jft.file_props.sid) @@ -191,34 +196,34 @@ class StateTransfering(JingleFileTransferStates): gajim.socks5queue.idx += 1 idx = gajim.socks5queue.idx sockobj = Socks5SenderClient(gajim.idlequeue, idx, - gajim.socks5queue, _sock=None, - host=str(streamhost_used['host']), - port=int(streamhost_used['port']), fingerprint=None, - connected=False, file_props=self.jft.file_props) + gajim.socks5queue, _sock=None, + host=str(streamhost_used['host']), + port=int(streamhost_used['port']), + fingerprint=None, connected=False, + file_props=self.jft.file_props) else: sockobj = Socks5ReceiverClient(gajim.idlequeue, streamhost_used, - sid=self.jft.file_props.sid, - file_props=self.jft.file_props, fingerprint=None) + sid=self.jft.file_props.sid, + file_props=self.jft.file_props, + fingerprint=None) sockobj.proxy = True sockobj.streamhost = streamhost_used gajim.socks5queue.add_sockobj(self.jft.session.connection.name, - sockobj) + sockobj) streamhost_used['idx'] = sockobj.queue_idx # If we offered the nominated candidate used, we activate # the proxy - if not self.jft.isOurCandUsed(): + if not self.jft.is_our_candidate_used(): gajim.socks5queue.on_success[self.jft.file_props.sid] = \ self.jft.transport._on_proxy_auth_ok # TODO: add on failure else: jid = gajim.get_jid_without_resource(self.jft.session.ourjid) gajim.socks5queue.send_file(self.jft.file_props, - self.jft.session.connection.name, mode) + self.jft.session.connection.name, mode) def action(self, args=None): if self.jft.transport.type_ == TransportType.IBB: - self.__start_IBB_transfer(self.jft.session.connection) + self._start_ibb_transfer(self.jft.session.connection) elif self.jft.transport.type_ == TransportType.SOCKS5: - self.__start_SOCK5_transfer() - - + self._start_sock5_transfer() diff --git a/src/common/jingle_rtp.py b/src/common/jingle_rtp.py index c94666922..12fc9a7e8 100644 --- a/src/common/jingle_rtp.py +++ b/src/common/jingle_rtp.py @@ -17,6 +17,7 @@ Handles Jingle RTP sessions (XEP 0167) """ +import logging import socket import nbxmpp import gi @@ -35,7 +36,6 @@ from common.jingle_session import FailedApplication from collections import deque -import logging log = logging.getLogger('gajim.c.jingle_rtp') @@ -46,7 +46,8 @@ class JingleRTPContent(JingleContent): JingleContent.__init__(self, session, transport) self.media = media self._dtmf_running = False - self.farstream_media = {'audio': Farstream.MediaType.AUDIO, + self.farstream_media = { + 'audio': Farstream.MediaType.AUDIO, 'video': Farstream.MediaType.VIDEO}[media] self.pipeline = None @@ -55,6 +56,12 @@ class JingleRTPContent(JingleContent): self.candidates_ready = False # True when local candidates are prepared + # TODO + self.conference = None + self.funnel = None + self.p2psession = None + self.p2pstream = None + self.callbacks['session-initiate'] += [self.__on_remote_codecs] self.callbacks['content-add'] += [self.__on_remote_codecs] self.callbacks['description-info'] += [self.__on_remote_codecs] @@ -90,32 +97,32 @@ class JingleRTPContent(JingleContent): if stun_server: try: ip = socket.getaddrinfo(stun_server, 0, socket.AF_UNSPEC, - socket.SOCK_STREAM)[0][4][0] + socket.SOCK_STREAM)[0][4][0] except socket.gaierror as e: - log.warning('Lookup of stun ip failed: %s' % str(e)) + log.warning('Lookup of stun ip failed: %s', str(e)) else: params['stun-ip'] = ip self.p2pstream = self.p2psession.new_stream(participant, - Farstream.StreamDirection.BOTH) + Farstream.StreamDirection.BOTH) self.p2pstream.connect('src-pad-added', on_src_pad_added) self.p2pstream.set_transmitter_ht('nice', params) def is_ready(self): - return (JingleContent.is_ready(self) and self.candidates_ready) + return JingleContent.is_ready(self) and self.candidates_ready def make_bin_from_config(self, config_key, pipeline, text): pipeline = pipeline % gajim.config.get(config_key) try: - bin = Gst.parse_bin_from_description(pipeline, True) - return bin + gst_bin = Gst.parse_bin_from_description(pipeline, True) + return gst_bin except GLib.GError as e: - gajim.nec.push_incoming_event(InformationEvent(None, - conn=self.session.connection, level='error', - pri_txt=_('%s configuration error') % text.capitalize(), - sec_txt=_("Couldn't setup %s. Check your configuration.\n\n" - "Pipeline was:\n%s\n\nError was:\n%s") % (text, pipeline, - str(e)))) + gajim.nec.push_incoming_event( + InformationEvent( + None, conn=self.session.connection, level='error', + pri_txt=_('%s configuration error') % text.capitalize(), + sec_txt=_('Couldn’t setup %s. Check your configuration.\n\n' + 'Pipeline was:\n%s\n\nError was:\n%s') % (text, pipeline, str(e)))) raise JingleContentSetupException def add_remote_candidates(self, candidates): @@ -147,7 +154,7 @@ class JingleRTPContent(JingleContent): def _start_dtmf(self, event): if event in ('*', '#'): event = {'*': Farstream.DTMFEvent.STAR, - '#': Farstream.DTMFEvent.POUND}[event] + '#': Farstream.DTMFEvent.POUND}[event] else: event = int(event) self.p2psession.start_telephony_event(event, 2) @@ -157,7 +164,8 @@ class JingleRTPContent(JingleContent): def _fill_content(self, content): content.addChild(nbxmpp.NS_JINGLE_RTP + ' description', - attrs={'media': self.media}, payload=list(self.iter_codecs())) + attrs={'media': self.media}, + payload=list(self.iter_codecs())) def _setup_funnel(self): self.funnel = Gst.ElementFactory.make('funnel', None) @@ -174,7 +182,7 @@ class JingleRTPContent(JingleContent): def _on_gst_message(self, bus, message): if message.type == Gst.MessageType.ELEMENT: name = message.get_structure().get_name() - log.debug('gst element message: %s: %s' % (name, message)) + log.debug('gst element message: %s: %s', name, message) if name == 'farstream-new-active-candidate-pair': pass elif name == 'farstream-recv-codecs-changed': @@ -189,7 +197,7 @@ class JingleRTPContent(JingleContent): self.transport.remote_candidates) self.transport.remote_candidates = [] self.p2pstream.set_property('direction', - Farstream.StreamDirection.BOTH) + Farstream.StreamDirection.BOTH) elif name == 'farstream-local-candidates-prepared': self.candidates_ready = True @@ -208,19 +216,21 @@ class JingleRTPContent(JingleContent): reason.setTag('failed-transport') self.session.remove_content(self.creator, self.name, reason) elif name == 'farstream-error': - log.error('Farstream error #%d!\nMessage: %s' % ( - message.get_structure().get_value('error-no'), - message.get_structure().get_value('error-msg'))) + log.error('Farstream error #%d!\nMessage: %s', + message.get_structure().get_value('error-no'), + message.get_structure().get_value('error-msg')) elif message.type == Gst.MessageType.ERROR: # TODO: Fix it to fallback to videotestsrc anytime an error occur, # or raise an error, Jingle way # or maybe one-sided stream? if not self.stream_failed_once: - gajim.nec.push_incoming_event(InformationEvent(None, - conn=self.session.connection, level='error', - pri_txt=_('GStreamer error'), sec_txt=_('Error: %s\nDebug: ' - '%s' % (message.get_structure().get_value('gerror'), - message.get_structure().get_value('debug'))))) + gajim.nec.push_incoming_event( + InformationEvent( + None, conn=self.session.connection, level='error', + pri_txt=_('GStreamer error'), + sec_txt=_('Error: %s\nDebug: %s' % + (message.get_structure().get_value('gerror'), + message.get_structure().get_value('debug'))))) sink_pad = self.p2psession.get_property('sink-pad') @@ -243,7 +253,8 @@ class JingleRTPContent(JingleContent): # Start playing again self.pipeline.set_state(Gst.State.PLAYING) - def get_fallback_src(self): + @staticmethod + def get_fallback_src(): return Gst.ElementFactory.make('fakesrc', None) def on_negotiated(self): @@ -270,7 +281,7 @@ class JingleRTPContent(JingleContent): # ignore invalid payload-types continue c = Farstream.Codec.new(int(codec['id']), codec['name'], - self.farstream_media, int(codec['clockrate'])) + self.farstream_media, int(codec['clockrate'])) if 'channels' in codec: c.channels = int(codec['channels']) else: @@ -288,14 +299,17 @@ class JingleRTPContent(JingleContent): def iter_codecs(self): codecs = self.p2psession.props.codecs_without_config for codec in codecs: - attrs = {'name': codec.encoding_name, + attrs = { + 'name': codec.encoding_name, 'id': codec.id, - 'channels': codec.channels} + 'channels': codec.channels + } if codec.clock_rate: attrs['clockrate'] = codec.clock_rate if codec.optional_params: - payload = list(nbxmpp.Node('parameter', {'name': p.name, - 'value': p.value}) for p in codec.optional_params) + payload = [nbxmpp.Node('parameter', + {'name': p.name, 'value': p.value}) + for p in codec.optional_params] else: payload = [] yield nbxmpp.Node('payload-type', attrs, payload) @@ -343,19 +357,22 @@ class JingleAudio(JingleRTPContent): # place 16kHz before 8kHz, as buggy psi versions will take in # account only the first codec - codecs = [Farstream.Codec.new(Farstream.CODEC_ID_ANY, 'SPEEX', - Farstream.MediaType.AUDIO, 16000), + codecs = [ Farstream.Codec.new(Farstream.CODEC_ID_ANY, 'SPEEX', - Farstream.MediaType.AUDIO, 8000)] + Farstream.MediaType.AUDIO, 16000), + Farstream.Codec.new(Farstream.CODEC_ID_ANY, 'SPEEX', + Farstream.MediaType.AUDIO, 8000)] self.p2psession.set_codec_preferences(codecs) # the local parts # TODO: Add queues? self.src_bin = self.make_bin_from_config('audio_input_device', - '%s ! audioconvert', _("audio input")) + '%s ! audioconvert', + _("audio input")) self.sink = self.make_bin_from_config('audio_output_device', - 'audioconvert ! volume name=gajim_out_vol ! %s', _("audio output")) + 'audioconvert ! volume name=gajim_out_vol ! %s', + _("audio output")) self.mic_volume = self.src_bin.get_by_name('gajim_vol') self.out_volume = self.sink.get_by_name('gajim_out_vol') @@ -411,15 +428,16 @@ class JingleVideo(JingleRTPContent): tee = '' self.src_bin = self.make_bin_from_config('video_input_device', - '%%s %s! %svideoscale ! %svideoconvert' % (tee, framerate, - video_size), _("video input")) + '%%s %s! %svideoscale ! %svideoconvert' % + (tee, framerate, video_size), + _("video input")) self.pipeline.add(self.src_bin) self.pipeline.set_state(Gst.State.PLAYING) self.sink = self.make_bin_from_config('video_output_device', - 'videoscale ! videoconvert ! %s', - _("video output")) + 'videoscale ! videoconvert ! %s', + _("video output")) self.pipeline.add(self.sink) diff --git a/src/common/jingle_session.py b/src/common/jingle_session.py index 4efd4541e..63a6be14f 100644 --- a/src/common/jingle_session.py +++ b/src/common/jingle_session.py @@ -28,24 +28,28 @@ Handles Jingle sessions (XEP 0166) # - Tie-breaking # * timeout -from common import gajim -import nbxmpp -from common.jingle_transport import get_jingle_transport, JingleTransportIBB -from common.jingle_content import get_jingle_content, JingleContentSetupException -from common.jingle_content import JingleContent -from common.jingle_ft import STATE_TRANSPORT_REPLACE -from common.connection_handlers_events import * import logging +from enum import Enum +import nbxmpp +from common import gajim +from common.jingle_transport import get_jingle_transport, JingleTransportIBB +from common.jingle_content import get_jingle_content, JingleContentSetupException, JingleContent +from common.jingle_ft import State +from common.connection_handlers_events import ( + FilesProp, JingleRequestReceivedEvent, JingleDisconnectedReceivedEvent, + JingleTransferCancelledEvent, JingleConnectedReceivedEvent, + JingleErrorReceivedEvent) + log = logging.getLogger("gajim.c.jingle_session") # FIXME: Move it to JingleSession.States? -class JingleStates(object): +class JingleStates(Enum): """ States in which jingle session may exist """ - ended = 0 - pending = 1 - active = 2 + ENDED = 0 + PENDING = 1 + ACTIVE = 2 class OutOfOrder(Exception): """ @@ -61,17 +65,18 @@ class TieBreak(Exception): class FailedApplication(Exception): """ - Exception that should be raised in case responder supports none of the payload-types offered by the initiator + Exception that should be raised in case responder supports none of the + payload-types offered by the initiator """ -class JingleSession(object): +class JingleSession: """ This represents one jingle session, that is, one or more content types negotiated between an initiator and a responder. """ def __init__(self, con, weinitiate, jid, iq_id=None, sid=None, - werequest=False): + werequest=False): """ con -- connection object, weinitiate -- boolean, are we the initiator? @@ -85,16 +90,16 @@ class JingleSession(object): self.ourjid = self.ourjid + '/' + con.server_resource self.peerjid = jid # jid we connect to # jid we use as the initiator - self.initiator = weinitiate and self.ourjid or self.peerjid + self.initiator = self.ourjid if weinitiate else self.peerjid # jid we use as the responder - self.responder = weinitiate and self.peerjid or self.ourjid + self.responder = self.peerjid if weinitiate else self.ourjid # are we an initiator? self.weinitiate = weinitiate # Are we requesting or offering a file? self.werequest = werequest self.request = False # what state is session in? (one from JingleStates) - self.state = JingleStates.ended + self.state = JingleStates.ENDED if not sid: sid = con.connection.getAnID() self.sid = sid # sessionid @@ -106,37 +111,37 @@ class JingleSession(object): self.iq_ids = [] self.accepted = True # is this session accepted by user # Tells whether this session is a file transfer or not - self.session_type_FT = False + self.session_type_ft = False # callbacks to call on proper contents # use .prepend() to add new callbacks, especially when you're going # to send error instead of ack self.callbacks = { - 'content-accept': [self.__ack, self.__on_content_accept, - self.__broadcast], - 'content-add': [self.__ack, - self.__on_content_add, self.__broadcast - ], #TODO - 'content-modify': [self.__ack], #TODO - 'content-reject': [self.__ack, self.__on_content_remove], - 'content-remove': [self.__ack, self.__on_content_remove], - 'description-info': [self.__ack, self.__broadcast], #TODO - 'security-info': [self.__ack], #TODO - 'session-accept': [self.__ack, self.__on_session_accept, - self.__on_content_accept, - self.__broadcast], - 'session-info': [self.__ack, self.__broadcast, - self.__on_session_info ], - 'session-initiate': [self.__ack, self.__on_session_initiate, - self.__broadcast], - 'session-terminate': [self.__ack,self.__on_session_terminate, - self.__broadcast_all], - 'transport-info': [self.__ack, self.__broadcast], - 'transport-replace': [self.__ack, self.__broadcast, - self.__on_transport_replace], #TODO - 'transport-accept': [self.__ack], #TODO - 'transport-reject': [self.__ack], #TODO - 'iq-result': [self.__broadcast], - 'iq-error': [self.__on_error], + 'content-accept': [self.__ack, self.__on_content_accept, + self.__broadcast], + 'content-add': [self.__ack, + self.__on_content_add, self.__broadcast + ], #TODO + 'content-modify': [self.__ack], #TODO + 'content-reject': [self.__ack, self.__on_content_remove], + 'content-remove': [self.__ack, self.__on_content_remove], + 'description-info': [self.__ack, self.__broadcast], #TODO + 'security-info': [self.__ack], #TODO + 'session-accept': [self.__ack, self.__on_session_accept, + self.__on_content_accept, + self.__broadcast], + 'session-info': [self.__ack, self.__broadcast, + self.__on_session_info], + 'session-initiate': [self.__ack, self.__on_session_initiate, + self.__broadcast], + 'session-terminate': [self.__ack, self.__on_session_terminate, + self.__broadcast_all], + 'transport-info': [self.__ack, self.__broadcast], + 'transport-replace': [self.__ack, self.__broadcast, + self.__on_transport_replace], #TODO + 'transport-accept': [self.__ack], #TODO + 'transport-reject': [self.__ack], #TODO + 'iq-result': [self.__broadcast], + 'iq-error': [self.__on_error], } def collect_iq_id(self, iq_id): @@ -174,7 +179,7 @@ class JingleSession(object): def reject_content(self, media, name=None): content = self.get_content(media, name) if content: - if self.state == JingleStates.active: + if self.state == JingleStates.ACTIVE: self.__content_reject(content) content.destroy() self.on_session_state_changed() @@ -184,7 +189,7 @@ class JingleSession(object): Called when user stops or cancel session in UI """ reason = nbxmpp.Node('reason') - if self.state == JingleStates.active: + if self.state == JingleStates.ACTIVE: reason.addChild('success') else: reason.addChild('cancel') @@ -232,11 +237,11 @@ class JingleSession(object): if not self.contents: self.end_session() - def modify_content(self, creator, name, transport = None): + def modify_content(self, creator, name, transport=None): ''' Currently used for transport replacement ''' - content = self.contents[(creator,name)] + content = self.contents[(creator, name)] transport.set_sid(content.transport.sid) transport.set_file_props(content.transport.file_props) content.transport = transport @@ -245,11 +250,11 @@ class JingleSession(object): content.accepted = True def on_session_state_changed(self, content=None): - if self.state == JingleStates.ended: + if self.state == JingleStates.ENDED: # Session not yet started, only one action possible: session-initiate if self.is_ready() and self.weinitiate: self.__session_initiate() - elif self.state == JingleStates.pending: + elif self.state == JingleStates.PENDING: # We can either send a session-accept or a content-add if self.is_ready() and not self.weinitiate: self.__session_accept() @@ -257,7 +262,7 @@ class JingleSession(object): self.__content_add(content) elif content and self.weinitiate: self.__content_accept(content) - elif self.state == JingleStates.active: + elif self.state == JingleStates.ACTIVE: # We can either send a content-add or a content-accept. However, if # we are sending a file we can only use session_initiate. if not content: @@ -278,7 +283,7 @@ class JingleSession(object): Return True when all codecs and candidates are ready (for all contents) """ return (any((content.is_ready() for content in self.contents.values())) - and self.accepted) + and self.accepted) def accept_session(self): """ @@ -298,20 +303,20 @@ class JingleSession(object): pass def send_content_accept(self, content): - assert self.state != JingleStates.ended + assert self.state != JingleStates.ENDED stanza, jingle = self.__make_jingle('content-accept') jingle.addChild(node=content) self.connection.connection.send(stanza) def send_transport_info(self, content): - assert self.state != JingleStates.ended + assert self.state != JingleStates.ENDED stanza, jingle = self.__make_jingle('transport-info') jingle.addChild(node=content) self.connection.connection.send(stanza) self.collect_iq_id(stanza.getID()) def send_description_info(self, content): - assert self.state != JingleStates.ended + assert self.state != JingleStates.ENDED stanza, jingle = self.__make_jingle('description-info') jingle.addChild(node=content) self.connection.connection.send(stanza) @@ -334,8 +339,8 @@ class JingleSession(object): self.__send_error(stanza, 'bad-request') return # FIXME: If we aren't initiated and it's not a session-initiate... - if action not in ['session-initiate','session-terminate'] \ - and self.state == JingleStates.ended: + if action not in ['session-initiate', 'session-terminate'] \ + and self.state == JingleStates.ENDED: self.__send_error(stanza, 'item-not-found', 'unknown-session') return else: @@ -381,7 +386,7 @@ class JingleSession(object): transport = JingleTransportIBB() # For debug only, delete this and replace for a function # that will identify contents by its sid - for creator, name in self.contents.keys(): + for creator, name in self.contents: self.modify_content(creator, name, transport) cont = self.contents[(creator, name)] cont.transport = transport @@ -389,7 +394,7 @@ class JingleSession(object): self.__append_contents(jingle) self.__broadcast(stanza, jingle, None, 'transport-replace') self.connection.connection.send(stanza) - self.state = JingleStates.pending + self.state = JingleStates.PENDING def __on_transport_replace(self, stanza, jingle, error, action): for content in jingle.iterTags('content'): @@ -405,15 +410,15 @@ class JingleSession(object): elif transport_ns == nbxmpp.NS_JINGLE_IBB: transport = JingleTransportIBB() self.modify_content(creator, name, transport) - self.state = JingleStates.pending - self.contents[(creator,name)].state = STATE_TRANSPORT_REPLACE + self.state = JingleStates.PENDING + self.contents[(creator, name)].state = State.TRANSPORT_REPLACE self.__ack(stanza, jingle, error, action) self.__session_accept() - self.contents[(creator,name)].start_IBB_transfer() + self.contents[(creator, name)].start_IBB_transfer() else: stanza, jingle = self.__make_jingle('transport-reject') content = jingle.setTag('content', attrs={'creator': creator, - 'name': name}) + 'name': name}) content.setTag('transport', namespace=transport_ns) self.connection.connection.send(stanza) raise nbxmpp.NodeProcessed @@ -421,9 +426,9 @@ class JingleSession(object): # FIXME: This ressource is unknown to us, what should we do? # For now, reject the transport stanza, jingle = self.__make_jingle('transport-reject') - c = jingle.setTag('content', attrs={'creator': creator, - 'name': name}) - c.setTag('transport', namespace=transport_ns) + content = jingle.setTag('content', attrs={'creator': creator, + 'name': name}) + content.setTag('transport', namespace=transport_ns) self.connection.connection.send(stanza) raise nbxmpp.NodeProcessed @@ -433,12 +438,12 @@ class JingleSession(object): if payload[0].getName() == 'ringing': # ignore ringing raise nbxmpp.NodeProcessed - if self.state != JingleStates.active: + if self.state != JingleStates.ACTIVE: raise OutOfOrder - for p in payload: - if p.getName() == 'checksum': - hash_ = p.getTag('file').getTag(name='hash', - namespace=nbxmpp.NS_HASHES) + for child in payload: + if child.getName() == 'checksum': + hash_ = child.getTag('file').getTag(name='hash', + namespace=nbxmpp.NS_HASHES) algo = hash_.getAttr('algo') if algo in nbxmpp.Hashes.supported: file_props = FilesProp.getFileProp(self.connection.name, @@ -468,11 +473,12 @@ class JingleSession(object): def __on_session_accept(self, stanza, jingle, error, action): # FIXME - if self.state != JingleStates.pending: + if self.state != JingleStates.PENDING: raise OutOfOrder - self.state = JingleStates.active + self.state = JingleStates.ACTIVE - def __on_content_accept(self, stanza, jingle, error, action): + @staticmethod + def __on_content_accept(stanza, jingle, error, action): """ Called when we get content-accept stanza or equivalent one (like session-accept) @@ -484,7 +490,7 @@ class JingleSession(object): name = content['name'] def __on_content_add(self, stanza, jingle, error, action): - if self.state == JingleStates.ended: + if self.state == JingleStates.ENDED: raise OutOfOrder parse_result = self.__parse_contents(jingle) contents = parse_result[0] @@ -496,14 +502,16 @@ class JingleSession(object): self.__content_reject(content) self.contents[(content.creator, content.name)].destroy() gajim.nec.push_incoming_event(JingleRequestReceivedEvent(None, - conn=self.connection, jingle_session=self, contents=contents)) + conn=self.connection, + jingle_session=self, + contents=contents)) def __on_session_initiate(self, stanza, jingle, error, action): """ We got a jingle session request from other entity, therefore we are the receiver... Unpack the data, inform the user """ - if self.state != JingleStates.ended: + if self.state != JingleStates.ENDED: raise OutOfOrder self.initiator = jingle['initiator'] self.responder = self.ourjid @@ -533,18 +541,17 @@ class JingleSession(object): jingle.getTag('content').getTag('description').getTag('request') if request: self.request = True - h = request.getTag('file').getTag('hash') - h = h.getData() if h else None + hash_tag = request.getTag('file').getTag('hash') + hash_data = hash_tag.getData() if hash_tag else None n = request.getTag('file').getTag('name') n = n.getData() if n else None pjid = gajim.get_jid_without_resource(self.peerjid) - file_info = self.connection.get_file_info(pjid, h, n, - self.connection.name) + file_info = self.connection.get_file_info(pjid, hash_data, n, + self.connection.name) if not file_info: - log.warning('The peer ' + pjid + \ - ' is requesting a ' + \ - 'file that we dont have or ' + \ - 'it is not allowed to request') + log.warning('The peer %s is requesting a ' \ + 'file that we dont have or ' \ + 'it is not allowed to request', pjid) self.decline_session() raise nbxmpp.NodeProcessed # If there's no content we understand... @@ -555,10 +562,12 @@ class JingleSession(object): self.__ack(stanza, jingle, error, action) self._session_terminate(reason) raise nbxmpp.NodeProcessed - self.state = JingleStates.pending + self.state = JingleStates.PENDING # Send event about starting a session gajim.nec.push_incoming_event(JingleRequestReceivedEvent(None, - conn=self.connection, jingle_session=self, contents=contents)) + conn=self.connection, + jingle_session=self, + contents=contents)) def __broadcast(self, stanza, jingle, error, action): """ @@ -594,10 +603,12 @@ class JingleSession(object): else: # TODO text = reason - if reason == 'cancel' and self.session_type_FT: + if reason == 'cancel' and self.session_type_ft: gajim.nec.push_incoming_event(JingleTransferCancelledEvent(None, - conn=self.connection, jingle_session=self, media=None, - reason=text)) + conn=self.connection, + jingle_session=self, + media=None, + reason=text)) def __broadcast_all(self, stanza, jingle, error, action): """ @@ -621,7 +632,7 @@ class JingleSession(object): if transport: content = content_type(self, transport) self.add_content(element['name'], - content, 'peer') + content, 'peer') contents.append((content.media,)) else: reasons.add('unsupported-transports') @@ -634,7 +645,7 @@ class JingleSession(object): failure_reason = None # Store the first reason of failure for reason in ('failed-application', 'unsupported-transports', - 'unsupported-applications'): + 'unsupported-applications'): if reason in reasons: failure_reason = reason break @@ -645,17 +656,21 @@ class JingleSession(object): text = '%s (%s)' % (error, text) if type_ != 'modify': gajim.nec.push_incoming_event(JingleErrorReceivedEvent(None, - conn=self.connection, jingle_session=self, - reason=text or error)) + conn=self.connection, + jingle_session=self, + reason=text or error)) - def __reason_from_stanza(self, stanza): + @staticmethod + def __reason_from_stanza(stanza): # TODO: Move to GUI? reason = 'success' - reasons = ['success', 'busy', 'cancel', 'connectivity-error', - 'decline', 'expired', 'failed-application', 'failed-transport', - 'general-error', 'gone', 'incompatible-parameters', 'media-error', - 'security-error', 'timeout', 'unsupported-applications', - 'unsupported-transports'] + reasons = [ + 'success', 'busy', 'cancel', 'connectivity-error', 'decline', + 'expired', 'failed-application', 'failed-transport', + 'general-error', 'gone', 'incompatible-parameters', 'media-error', + 'security-error', 'timeout', 'unsupported-applications', + 'unsupported-transports' + ] tag = stanza.getTag('reason') text = '' if tag: @@ -668,12 +683,14 @@ class JingleSession(object): def __make_jingle(self, action, reason=None): stanza = nbxmpp.Iq(typ='set', to=nbxmpp.JID(self.peerjid), - frm=self.ourjid) - attrs = {'action': action, - 'sid': self.sid, - 'initiator' : self.initiator} + frm=self.ourjid) + attrs = { + 'action': action, + 'sid': self.sid, + 'initiator' : self.initiator + } jingle = stanza.addChild('jingle', attrs=attrs, - namespace=nbxmpp.NS_JINGLE) + namespace=nbxmpp.NS_JINGLE) if reason is not None: jingle.addChild(node=reason) return stanza, jingle @@ -690,13 +707,15 @@ class JingleSession(object): self.connection.connection.send(err_stanza) self.__dispatch_error(jingle_error or error, text, type_) - def __append_content(self, jingle, content): + @staticmethod + def __append_content(jingle, content): """ Append element to element, with (full=True) or without (full=False) children """ jingle.addChild('content', - attrs={'name': content.name, 'creator': content.creator}) + attrs={'name': content.name, + 'creator': content.creator}) def __append_contents(self, jingle): """ @@ -709,36 +728,36 @@ class JingleSession(object): self.__append_content(jingle, content) def __session_initiate(self): - assert self.state == JingleStates.ended + assert self.state == JingleStates.ENDED stanza, jingle = self.__make_jingle('session-initiate') self.__append_contents(jingle) self.__broadcast(stanza, jingle, None, 'session-initiate-sent') self.connection.connection.send(stanza) self.collect_iq_id(stanza.getID()) - self.state = JingleStates.pending + self.state = JingleStates.PENDING def __session_accept(self): - assert self.state == JingleStates.pending + assert self.state == JingleStates.PENDING stanza, jingle = self.__make_jingle('session-accept') self.__append_contents(jingle) self.__broadcast(stanza, jingle, None, 'session-accept-sent') self.connection.connection.send(stanza) self.collect_iq_id(stanza.getID()) - self.state = JingleStates.active + self.state = JingleStates.ACTIVE def __session_info(self, payload=None): - assert self.state != JingleStates.ended + assert self.state != JingleStates.ENDED stanza, jingle = self.__make_jingle('session-info') if payload: jingle.addChild(node=payload) self.connection.connection.send(stanza) - def _JingleFileTransfer__session_info(self, p): + def _JingleFileTransfer__session_info(self, payload): # For some strange reason when I call - # self.session.__session_info(h) from the jingleFileTransfer object + # self.session.__session_info(payload) from the jingleFileTransfer object # within a thread, this method gets called instead. Even though, it # isn't being called explicitly. - self.__session_info(p) + self.__session_info(payload) def _session_terminate(self, reason=None): stanza, jingle = self.__make_jingle('session-terminate', reason=reason) @@ -755,12 +774,14 @@ class JingleSession(object): text = reason self.connection.delete_jingle_session(self.sid) gajim.nec.push_incoming_event(JingleDisconnectedReceivedEvent(None, - conn=self.connection, jingle_session=self, media=None, - reason=text)) + conn=self.connection, + jingle_session=self, + media=None, + reason=text)) def __content_add(self, content): # TODO: test - assert self.state != JingleStates.ended + assert self.state != JingleStates.ENDED stanza, jingle = self.__make_jingle('content-add') self.__append_content(jingle, content) self.__broadcast(stanza, jingle, None, 'content-add-sent') @@ -769,7 +790,7 @@ class JingleSession(object): def __content_accept(self, content): # TODO: test - assert self.state != JingleStates.ended + assert self.state != JingleStates.ENDED stanza, jingle = self.__make_jingle('content-accept') self.__append_content(jingle, content) self.__broadcast(stanza, jingle, None, 'content-accept-sent') @@ -777,31 +798,35 @@ class JingleSession(object): self.collect_iq_id(id_) def __content_reject(self, content): - assert self.state != JingleStates.ended + assert self.state != JingleStates.ENDED stanza, jingle = self.__make_jingle('content-reject') self.__append_content(jingle, content) self.connection.connection.send(stanza) # TODO: this will fail if content is not an RTP content gajim.nec.push_incoming_event(JingleDisconnectedReceivedEvent(None, - conn=self.connection, jingle_session=self, media=content.media, - reason='rejected')) + conn=self.connection, + jingle_session=self, + media=content.media, + reason='rejected')) def __content_modify(self): - assert self.state != JingleStates.ended + assert self.state != JingleStates.ENDED def __content_remove(self, content, reason=None): - assert self.state != JingleStates.ended + assert self.state != JingleStates.ENDED if self.connection.connection and self.connection.connected > 1: stanza, jingle = self.__make_jingle('content-remove', reason=reason) self.__append_content(jingle, content) self.connection.connection.send(stanza) # TODO: this will fail if content is not an RTP content gajim.nec.push_incoming_event(JingleDisconnectedReceivedEvent(None, - conn=self.connection, jingle_session=self, media=content.media, - reason='removed')) + conn=self.connection, + jingle_session=self, + media=content.media, + reason='removed')) def content_negotiated(self, media): gajim.nec.push_incoming_event(JingleConnectedReceivedEvent(None, - conn=self.connection, jingle_session=self, media=media)) - - + conn=self.connection, + jingle_session=self, + media=media)) diff --git a/src/common/jingle_transport.py b/src/common/jingle_transport.py index 29073e766..04bf51eb5 100644 --- a/src/common/jingle_transport.py +++ b/src/common/jingle_transport.py @@ -17,11 +17,11 @@ Handles Jingle Transports (currently only ICE-UDP) """ -import nbxmpp -import socket -from common import gajim import logging +import socket from enum import IntEnum +import nbxmpp +from common import gajim log = logging.getLogger('gajim.c.jingle_transport') @@ -43,16 +43,24 @@ class TransportType(IntEnum): IBB = 3 -class JingleTransport(object): +class JingleTransport: """ An abstraction of a transport in Jingle sessions """ + __slots__ = ['type_', 'candidates', 'remote_candidates', 'connection', + 'file_props', 'ourjid', 'sid'] + def __init__(self, type_): self.type_ = type_ self.candidates = [] self.remote_candidates = [] + self.connection = None + self.file_props = None + self.ourjid = None + self.sid = None + def _iter_candidates(self): for candidate in self.candidates: yield self.make_candidate(candidate) @@ -110,9 +118,7 @@ class JingleTransportSocks5(JingleTransport): def make_candidate(self, candidate): - import logging - log = logging.getLogger() - log.info('candidate dict, %s' % candidate) + log.info('candidate dict, %s', candidate) attrs = { 'cid': candidate['candidate_id'], 'host': candidate['host'], @@ -124,8 +130,8 @@ class JingleTransportSocks5(JingleTransport): return nbxmpp.Node('candidate', attrs=attrs) - def make_transport(self, candidates=None, add_candidates = True): - if add_candidates: + def make_transport(self, candidates=None, add_candidates=True): + if add_candidates: self._add_local_ips_as_candidates() self._add_additional_candidates() self._add_proxy_candidates() @@ -174,7 +180,7 @@ class JingleTransportSocks5(JingleTransport): def _add_local_ips_as_candidates(self): if not gajim.config.get_per('accounts', self.connection.name, - 'ft_send_local_ips'): + 'ft_send_local_ips'): return if not self.connection: return @@ -186,30 +192,34 @@ class JingleTransportSocks5(JingleTransport): hosts = set() local_ip_cand = [] - c = {'host': self.connection.peerhost[0], - 'candidate_id': self.connection.connection.getAnID(), - 'port': port, - 'type': 'direct', - 'jid': self.ourjid, - 'priority': priority} + candidate = { + 'host': self.connection.peerhost[0], + 'candidate_id': self.connection.connection.getAnID(), + 'port': port, + 'type': 'direct', + 'jid': self.ourjid, + 'priority': priority + } hosts.add(self.connection.peerhost[0]) - local_ip_cand.append(c) + local_ip_cand.append(candidate) try: for addrinfo in socket.getaddrinfo(socket.gethostname(), None): addr = addrinfo[4][0] if not addr in hosts and not addr.startswith('127.') and \ addr != '::1': - c = {'host': addr, - 'candidate_id': self.connection.connection.getAnID(), - 'port': port, - 'type': 'direct', - 'jid': self.ourjid, - 'priority': priority, - 'initiator': self.file_props.sender, - 'target': self.file_props.receiver} + candidate = { + 'host': addr, + 'candidate_id': self.connection.connection.getAnID(), + 'port': port, + 'type': 'direct', + 'jid': self.ourjid, + 'priority': priority, + 'initiator': self.file_props.sender, + 'target': self.file_props.receiver + } hosts.add(addr) - local_ip_cand.append(c) + local_ip_cand.append(candidate) except socket.gaierror: pass # ignore address-related errors for getaddrinfo @@ -226,16 +236,18 @@ class JingleTransportSocks5(JingleTransport): if ft_add_hosts: hosts = [e.strip() for e in ft_add_hosts.split(',')] - for h in hosts: - c = {'host': h, - 'candidate_id': self.connection.connection.getAnID(), - 'port': port, - 'type': 'direct', - 'jid': self.ourjid, - 'priority': priority, - 'initiator': self.file_props.sender, - 'target': self.file_props.receiver} - additional_ip_cand.append(c) + for host in hosts: + candidate = { + 'host': host, + 'candidate_id': self.connection.connection.getAnID(), + 'port': port, + 'type': 'direct', + 'jid': self.ourjid, + 'priority': priority, + 'initiator': self.file_props.sender, + 'target': self.file_props.receiver + } + additional_ip_cand.append(candidate) self._add_candidates(additional_ip_cand) @@ -252,21 +264,23 @@ class JingleTransportSocks5(JingleTransport): self.file_props.proxyhosts = proxyhosts for proxyhost in proxyhosts: - c = {'host': proxyhost['host'], - 'candidate_id': self.connection.connection.getAnID(), - 'port': int(proxyhost['port']), - 'type': 'proxy', - 'jid': proxyhost['jid'], - 'priority': priority, - 'initiator': self.file_props.sender, - 'target': self.file_props.receiver} - proxy_cand.append(c) + candidate = { + 'host': proxyhost['host'], + 'candidate_id': self.connection.connection.getAnID(), + 'port': int(proxyhost['port']), + 'type': 'proxy', + 'jid': proxyhost['jid'], + 'priority': priority, + 'initiator': self.file_props.sender, + 'target': self.file_props.receiver + } + proxy_cand.append(candidate) self._add_candidates(proxy_cand) def get_content(self): sesn = self.connection.get_jingle_session(self.ourjid, - self.file_props.sid) + self.file_props.sid) for content in sesn.contents.values(): if content.transport == self: return content @@ -277,7 +291,7 @@ class JingleTransportSocks5(JingleTransport): if not self.connection: return sesn = self.connection.get_jingle_session(self.ourjid, - self.file_props.sid) + self.file_props.sid) if sesn is None: return @@ -294,8 +308,8 @@ class JingleTransportSocks5(JingleTransport): content = nbxmpp.Node('content') content.setAttr('creator', 'initiator') - c = self.get_content() - content.setAttr('name', c.name) + content_object = self.get_content() + content.setAttr('name', content_object.name) transport = nbxmpp.Node('transport') transport.setNamespace(nbxmpp.NS_JINGLE_BYTESTREAM) transport.setAttr('sid', proxy['sid']) @@ -307,7 +321,7 @@ class JingleTransportSocks5(JingleTransport): else: for host in self.candidates: if host['host'] == proxy['host'] and host['jid'] == proxy['jid'] \ - and host['port'] == proxy['port']: + and host['port'] == proxy['port']: cid = host['candidate_id'] break if cid is None: @@ -345,7 +359,7 @@ class JingleTransportIBB(JingleTransport): try: from gi.repository import Farstream -except Exception: +except ImportError: pass class JingleTransportICEUDP(JingleTransport): @@ -353,11 +367,13 @@ class JingleTransportICEUDP(JingleTransport): JingleTransport.__init__(self, TransportType.ICEUDP) def make_candidate(self, candidate): - types = {Farstream.CandidateType.HOST: 'host', + types = { + Farstream.CandidateType.HOST: 'host', Farstream.CandidateType.SRFLX: 'srflx', Farstream.CandidateType.PRFLX: 'prflx', Farstream.CandidateType.RELAY: 'relay', - Farstream.CandidateType.MULTICAST: 'multicast'} + Farstream.CandidateType.MULTICAST: 'multicast' + } attrs = { 'component': candidate.component_id, 'foundation': '1', # hack @@ -402,23 +418,26 @@ class JingleTransportICEUDP(JingleTransport): # jingle proto = Farstream.NetworkProtocol.TCP priority = int(candidate['priority']) - types = {'host': Farstream.CandidateType.HOST, + types = { + 'host': Farstream.CandidateType.HOST, 'srflx': Farstream.CandidateType.SRFLX, 'prflx': Farstream.CandidateType.PRFLX, 'relay': Farstream.CandidateType.RELAY, - 'multicast': Farstream.CandidateType.MULTICAST} + 'multicast': Farstream.CandidateType.MULTICAST + } if 'type' in candidate and candidate['type'] in types: type_ = types[candidate['type']] else: - log.warning('Unknown type %s' % candidate['type']) + log.warning('Unknown type %s', candidate['type']) type_ = Farstream.CandidateType.HOST username = str(transport['ufrag']) password = str(transport['pwd']) ttl = 0 cand = Farstream.Candidate.new_full(foundation, component_id, ip, - port, base_ip, base_port, proto, priority, type_, username, - password, ttl) + port, base_ip, base_port, + proto, priority, type_, + username, password, ttl) candidates.append(cand) self.remote_candidates.extend(candidates) diff --git a/src/common/jingle_xtls.py b/src/common/jingle_xtls.py index abc2c8170..10a60d815 100644 --- a/src/common/jingle_xtls.py +++ b/src/common/jingle_xtls.py @@ -16,13 +16,15 @@ ## along with Gajim. If not, see . ## -import os -import nbxmpp - import logging +import os + +import nbxmpp from common import gajim + log = logging.getLogger('gajim.c.jingle_xtls') + PYOPENSSL_PRESENT = False # key-exchange id -> [callback, args], accept that session once key-exchange completes @@ -53,7 +55,7 @@ DH_PARAMS = 'dh_params.pem' DEFAULT_DH_PARAMS = 'dh4096.pem' def default_callback(connection, certificate, error_num, depth, return_code): - log.info("certificate: %s" % certificate) + log.info("certificate: %s", certificate) return return_code def load_cert_file(cert_path, cert_store=None): @@ -65,8 +67,8 @@ def load_cert_file(cert_path, cert_store=None): try: f = open(cert_path) except IOError as e: - log.warning('Unable to open certificate file %s: %s' % (cert_path, - str(e))) + log.warning('Unable to open certificate file %s: %s', cert_path, + str(e)) return None lines = f.readlines() i = 0 @@ -84,11 +86,11 @@ def load_cert_file(cert_path, cert_store=None): f.close() return x509cert except OpenSSL.crypto.Error as exception_obj: - log.warning('Unable to load a certificate from file %s: %s' %\ - (cert_path, exception_obj.args[0][0][2])) + log.warning('Unable to load a certificate from file %s: %s', + cert_path, exception_obj.args[0][0][2]) except: log.warning('Unknown error while loading certificate from file ' - '%s' % cert_path) + '%s', cert_path) begin = -1 i += 1 f.close() @@ -105,7 +107,7 @@ def get_context(fingerprint, verify_cb=None, remote_jid=None): if fingerprint == 'server': # for testing purposes only ctx.set_verify(SSL.VERIFY_NONE|SSL.VERIFY_FAIL_IF_NO_PEER_CERT, - verify_cb or default_callback) + verify_cb or default_callback) elif fingerprint == 'client': ctx.set_verify(SSL.VERIFY_PEER, verify_cb or default_callback) @@ -121,23 +123,23 @@ def get_context(fingerprint, verify_cb=None, remote_jid=None): ctx.load_tmp_dh(dh_params_name.encode('utf-8')) except FileNotFoundError as err: default_dh_params_name = os.path.join(gajim.DATA_DIR, - 'other', DEFAULT_DH_PARAMS) + 'other', DEFAULT_DH_PARAMS) try: with open(default_dh_params_name, "r") as default_dh_params_file: ctx.load_tmp_dh(default_dh_params_name.encode('utf-8')) except FileNotFoundError as err: - log.error('Unable to load default DH parameter file: %s , %s' - % (default_dh_params_name, err)) + log.error('Unable to load default DH parameter file: %s, %s', + default_dh_params_name, err) raise if remote_jid: store = ctx.get_cert_store() path = os.path.join(os.path.expanduser(gajim.MY_PEER_CERTS_PATH), - remote_jid) + '.cert' + remote_jid) + '.cert' if os.path.exists(path): load_cert_file(path, cert_store=store) - log.debug('certificate file ' + path + ' loaded fingerprint ' + \ - fingerprint) + log.debug('certificate file %s loaded fingerprint %s', + path, fingerprint) return ctx def read_cert(certpath): @@ -212,16 +214,16 @@ def send_cert_request(con, to_jid): # the following code is partly due to pyopenssl examples -def createKeyPair(type, bits): +def createKeyPair(type_, bits): """ Create a public/private key pair. - Arguments: type - Key type, must be one of TYPE_RSA and TYPE_DSA + Arguments: type_ - Key type, must be one of TYPE_RSA and TYPE_DSA bits - Number of bits to use in the key Returns: The public/private key pair in a PKey object """ pkey = crypto.PKey() - pkey.generate_key(type, bits) + pkey.generate_key(type_, bits) return pkey def createCertRequest(pkey, digest="sha256", **name): @@ -244,7 +246,7 @@ def createCertRequest(pkey, digest="sha256", **name): req = crypto.X509Req() subj = req.get_subject() - for (key,value) in name.items(): + for (key, value) in name.items(): setattr(subj, key, value) req.set_pubkey(pkey) From eb51184a95a2cf3229eac1557ccb1a2c149e0e7c Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Wed, 8 Feb 2017 04:37:21 +0000 Subject: [PATCH 15/16] Fix a few things in common.connection_handlers_events. --- src/common/connection_handlers_events.py | 90 ++++++++++++------------ 1 file changed, 44 insertions(+), 46 deletions(-) diff --git a/src/common/connection_handlers_events.py b/src/common/connection_handlers_events.py index c8287020f..d0e6bfc9e 100644 --- a/src/common/connection_handlers_events.py +++ b/src/common/connection_handlers_events.py @@ -18,34 +18,33 @@ ## along with Gajim. If not, see . ## +from calendar import timegm import datetime +import hashlib +import hmac +import logging import sys import os from time import time as time_time -from calendar import timegm -import hmac -import hashlib +import nbxmpp +from nbxmpp.protocol import NS_CHATSTATES from common import atom from common import nec from common import helpers from common import gajim from common import i18n -import nbxmpp from common import dataforms from common import exceptions -from common.zeroconf import zeroconf from common.zeroconf.zeroconf import Constant from common.logger import LOG_DB_PATH from common.pep import SUPPORTED_PERSONAL_USER_EVENTS -from nbxmpp.protocol import NS_CHATSTATES from common.jingle_transport import JingleTransportSocks5 from common.file_props import FilesProp if gajim.HAVE_PYOPENSSL: import OpenSSL.crypto -import logging log = logging.getLogger('gajim.c.connection_handlers_events') CONDITION_TO_CODE = { @@ -73,7 +72,7 @@ CONDITION_TO_CODE = { class HelperEvent: def get_jid_resource(self, check_fake_jid=False): if check_fake_jid and hasattr(self, 'id_') and \ - self.id_ in self.conn.groupchat_jids: + self.id_ in self.conn.groupchat_jids: self.fjid = self.conn.groupchat_jids[self.id_] del self.conn.groupchat_jids[self.id_] else: @@ -85,7 +84,7 @@ class HelperEvent: def get_gc_control(self): self.gc_control = gajim.interface.msg_win_mgr.get_gc_control(self.jid, - self.conn.name) + self.conn.name) # If gc_control is missing - it may be minimized. Try to get it # from there. If it's not there - then it's missing anyway and @@ -248,7 +247,7 @@ class TimeResultReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): except ValueError: try: t = datetime.datetime.strptime(utc_time, - '%Y-%m-%dT%H:%M:%S.%f') + '%Y-%m-%dT%H:%M:%S.%f') except ValueError as e: log.info('Wrong time format: %s' % str(e)) return @@ -281,8 +280,7 @@ class GMailQueryReceivedEvent(nec.NetworkIncomingEvent): gmail_messages = mb.getTags('mail-thread-info') for gmessage in gmail_messages: unread_senders = [] - for sender in gmessage.getTag('senders').getTags( - 'sender'): + for sender in gmessage.getTag('senders').getTags('sender'): if sender.getAttr('unread') != '1': continue if sender.getAttr('name'): @@ -310,8 +308,7 @@ class GMailQueryReceivedEvent(nec.NetworkIncomingEvent): self.conn.gmail_last_time = int(mb.getAttr('result-time')) self.jid = gajim.get_jid_from_account(self.name) - log.debug(('You have %s new gmail e-mails on %s.') % (self.newmsgs, - self.jid)) + log.debug('You have %s new gmail e-mails on %s.', self.newmsgs, self.jid) return True class RosterItemExchangeEvent(nec.NetworkIncomingEvent, HelperEvent): @@ -392,15 +389,15 @@ class RosterReceivedEvent(nec.NetworkIncomingEvent): j = helpers.parse_jid(jid) except Exception: print(_('JID %s is not RFC compliant. It will not be added ' - 'to your roster. Use roster management tools such as ' - 'http://jru.jabberstudio.org/ to remove it') % jid, - file=sys.stderr) + 'to your roster. Use roster management tools such as ' + 'http://jru.jabberstudio.org/ to remove it') % jid, + file=sys.stderr) else: infos = raw_roster[jid] if jid != our_jid and (not infos['subscription'] or \ - infos['subscription'] == 'none') and (not infos['ask'] or \ - infos['ask'] == 'none') and not infos['name'] and \ - not infos['groups']: + infos['subscription'] == 'none') and (not infos['ask'] or \ + infos['ask'] == 'none') and not infos['name'] and \ + not infos['groups']: # remove this useless item, it won't be shown in roster # anyway self.conn.connection.getRoster().delItem(jid) @@ -778,7 +775,8 @@ PresenceHelperEvent): sig_msg = sig_tag.getData() self.keyID = self.conn.gpg.verify(self.status, sig_msg) self.keyID = helpers.prepare_and_validate_gpg_keyID(self.conn.name, - self.jid, self.keyID) + self.jid, + self.keyID) def _generate_prio(self): self.prio = self.stanza.getPriority() @@ -845,7 +843,7 @@ PresenceHelperEvent): # Error presences may not include sent stanza, so we don't detect # it's a muc presence. So detect it by ID h = hmac.new(self.conn.secret_hmac, self.jid.encode('utf-8'), - hashlib.md5).hexdigest()[:6] + hashlib.md5).hexdigest()[:6] if self.id_.split('_')[-1] == h: self.is_gc = True self.status = self.stanza.getStatus() or '' @@ -857,8 +855,10 @@ PresenceHelperEvent): self.errmsg = self.stanza.getErrorMsg() if self.is_gc: - gajim.nec.push_incoming_event(GcPresenceReceivedEvent(None, - conn=self.conn, stanza=self.stanza, presence_obj=self)) + gajim.nec.push_incoming_event( + GcPresenceReceivedEvent( + None, conn=self.conn, stanza=self.stanza, + presence_obj=self)) return if self.ptype == 'subscribe': @@ -878,11 +878,10 @@ PresenceHelperEvent): if not self.ptype or self.ptype == 'unavailable': our_jid = gajim.get_jid_from_account(self.conn.name) - if self.jid == our_jid and self.resource == \ - self.conn.server_resource: + if self.jid == our_jid and self.resource == self.conn.server_resource: # We got our own presence gajim.nec.push_incoming_event(OurShowEvent(None, conn=self.conn, - show=self.show)) + show=self.show)) elif self.jid in jid_list or self.jid == our_jid: return True @@ -948,18 +947,16 @@ class GcPresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): # we know real jid, save it in db st += ' (%s)' % jid try: - gajim.logger.write('gcstatus', self.fjid, st, - self.show) + gajim.logger.write('gcstatus', self.fjid, st, self.show) except exceptions.PysqliteOperationalError as e: - self.conn.dispatch('DB_ERROR', (_('Disk Write Error'), - str(e))) + self.conn.dispatch('DB_ERROR', (_('Disk Write Error'), str(e))) except exceptions.DatabaseMalformed: pritext = _('Database Error') sectext = _('The database file (%s) cannot be read. ' - 'Try to repair it (see ' - 'http://trac.gajim.org/wiki/DatabaseBackup) or ' - 'remove it (all history will be lost).') % \ - LOG_DB_PATH + 'Try to repair it (see ' + 'http://trac.gajim.org/wiki/DatabaseBackup) or ' + 'remove it (all history will be lost).') % \ + LOG_DB_PATH self.conn.dispatch('DB_ERROR', (pritext, sectext)) if self.avatar_sha == '': # contact has no avatar @@ -1261,10 +1258,11 @@ class MessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): self.session = self.conn.get_latest_session(self.fjid) if not self.session: self.session = self.conn.make_new_session(self.fjid, - self.thread_id, type_='pm') + self.thread_id, + type_='pm') else: self.session = self.conn.get_or_create_session(self.fjid, - self.thread_id) + self.thread_id) if self.thread_id and not self.session.received_thread_id: self.session.received_thread_id = True @@ -1273,10 +1271,10 @@ class MessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): # check if the message is a XEP-0020 feature negotiation request if not self.forwarded and self.stanza.getTag('feature', - namespace=nbxmpp.NS_FEATURE): + namespace=nbxmpp.NS_FEATURE): if gajim.HAVE_PYCRYPTO: feature = self.stanza.getTag(name='feature', - namespace=nbxmpp.NS_FEATURE) + namespace=nbxmpp.NS_FEATURE) form = nbxmpp.DataForm(node=feature.getTag('x')) if not form: return @@ -1296,9 +1294,9 @@ class MessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): return if not self.forwarded and self.stanza.getTag('init', - namespace=nbxmpp.NS_ESESSION_INIT): + namespace=nbxmpp.NS_ESESSION_INIT): init = self.stanza.getTag(name='init', - namespace=nbxmpp.NS_ESESSION_INIT) + namespace=nbxmpp.NS_ESESSION_INIT) form = nbxmpp.DataForm(node=init.getTag('x')) self.session.handle_negotiation(form) @@ -1310,7 +1308,7 @@ class MessageReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): self.encrypted = False xep_200_encrypted = self.stanza.getTag('c', - namespace=nbxmpp.NS_STANZA_CRYPTO) + namespace=nbxmpp.NS_STANZA_CRYPTO) if xep_200_encrypted: if self.forwarded: # Ignore E2E forwarded encrypted messages @@ -1329,7 +1327,7 @@ class ZeroconfMessageReceivedEvent(MessageReceivedEvent): if self.fjid is None: for key in self.conn.connection.zeroconf.contacts: if self.ip == self.conn.connection.zeroconf.contacts[key][ - Constant.ADDRESS]: + Constant.ADDRESS]: self.fjid = key break @@ -1337,7 +1335,7 @@ class ZeroconfMessageReceivedEvent(MessageReceivedEvent): def generate(self): self.base_event = nec.NetworkIncomingEvent(None, conn=self.conn, - stanza=self.stanza) + stanza=self.stanza) return super(ZeroconfMessageReceivedEvent, self).generate() class GcInvitationReceivedEvent(nec.NetworkIncomingEvent): @@ -1351,8 +1349,8 @@ class GcInvitationReceivedEvent(nec.NetworkIncomingEvent): try: self.room_jid = helpers.parse_jid(invite_tag.getAttr('jid')) except helpers.InvalidFormat: - log.warning('Invalid JID: %s, ignoring it' % invite_tag.getAttr( - 'jid')) + log.warning('Invalid JID: %s, ignoring it', invite_tag.getAttr( + 'jid')) return self.jid_from = self.msg_obj.fjid self.reason = invite_tag.getAttr('reason') From a4387e848955e7083b66961851974d74b415e52f Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Wed, 8 Feb 2017 12:07:12 +0000 Subject: [PATCH 16/16] =?UTF-8?q?Use=20=E2=80=9C=E2=80=A6=20is=20not=20?= =?UTF-8?q?=E2=80=A6=E2=80=9D=20everywhere=20instead=20of=20=E2=80=9Cnot?= =?UTF-8?q?=20=E2=80=A6=20is=20=E2=80=A6=E2=80=9D.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/jingle_session.py | 2 +- src/common/socks5.py | 2 +- src/plugins/gui.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/common/jingle_session.py b/src/common/jingle_session.py index 63a6be14f..678cb32f6 100644 --- a/src/common/jingle_session.py +++ b/src/common/jingle_session.py @@ -527,7 +527,7 @@ class JingleSession: # Check if there's already a session with this user: if contents[0][0] != 'file': for session in self.connection.iter_jingle_sessions(self.peerjid): - if not session is self: + if session is not self: reason = nbxmpp.Node('reason') alternative_session = reason.setTag('alternative-session') alternative_session.setTagData('sid', session.sid) diff --git a/src/common/socks5.py b/src/common/socks5.py index a823023b2..1273e6486 100644 --- a/src/common/socks5.py +++ b/src/common/socks5.py @@ -485,7 +485,7 @@ class Socks5(object): for ai in self.ais: try: self._sock = socket.socket(*ai[:3]) - if not self.fingerprint is None: + if self.fingerprint is not None: if self.file_props.type_ == 's': remote_jid = gajim.get_jid_without_resource( self.file_props.receiver) diff --git a/src/plugins/gui.py b/src/plugins/gui.py index 46c48d1fc..3aac9be25 100644 --- a/src/plugins/gui.py +++ b/src/plugins/gui.py @@ -159,7 +159,7 @@ class PluginsWindow(object): self.uninstall_plugin_button.set_property('sensitive', gajim.PLUGINS_DIRS[1] in plugin.__path__) self.configure_plugin_button.set_property( - 'sensitive', not plugin.config_dialog is None) + 'sensitive', plugin.config_dialog is not None) def _clear_installed_plugin_info(self): self.plugin_name_label.set_text('')