Philipp Hörist pushed to branch master at gajim / gajim

Commits:

1 changed file:

Changes:

  • gajim/common/helpers.py
    ... ... @@ -54,7 +54,6 @@
    54 54
     import string
    
    55 55
     import webbrowser
    
    56 56
     from string import Template
    
    57
    -import urllib
    
    58 57
     from datetime import datetime
    
    59 58
     from datetime import timedelta
    
    60 59
     from urllib.parse import unquote
    
    ... ... @@ -129,6 +128,7 @@ def parse_jid(jidstring: str) -> str:
    129 128
         except Exception as error:
    
    130 129
             raise InvalidFormat(error)
    
    131 130
     
    
    131
    +
    
    132 132
     def idn_to_ascii(host: str) -> str:
    
    133 133
         """
    
    134 134
         Convert IDN (Internationalized Domain Names) to ACE (ASCII-compatible
    
    ... ... @@ -144,6 +144,7 @@ def idn_to_ascii(host: str) -> str:
    144 144
                 converted_labels.append('')
    
    145 145
         return ".".join(converted_labels)
    
    146 146
     
    
    147
    +
    
    147 148
     def ascii_to_idn(host: str) -> str:
    
    148 149
         """
    
    149 150
         Convert ACE (ASCII-compatible encoding) to IDN (Internationalized Domain
    
    ... ... @@ -156,17 +157,6 @@ def ascii_to_idn(host: str) -> str:
    156 157
             converted_labels.append(idna.ToUnicode(label))
    
    157 158
         return ".".join(converted_labels)
    
    158 159
     
    
    159
    -def puny_encode_url(url: str) -> Optional[str]:
    
    160
    -    _url = url
    
    161
    -    if '//' not in _url:
    
    162
    -        _url = '//' + _url
    
    163
    -    try:
    
    164
    -        o = urllib.parse.urlparse(_url)
    
    165
    -        p_loc = idn_to_ascii(o.hostname)
    
    166
    -    except Exception:
    
    167
    -        log.debug('urlparse failed: %s', url)
    
    168
    -        return None
    
    169
    -    return url.replace(o.hostname, p_loc)
    
    170 160
     
    
    171 161
     def parse_resource(resource: str) -> Optional[str]:
    
    172 162
         """
    
    ... ... @@ -180,16 +170,13 @@ def parse_resource(resource: str) -> Optional[str]:
    180 170
         except UnicodeError:
    
    181 171
             raise InvalidFormat('Invalid character in resource.')
    
    182 172
     
    
    183
    -def windowsify(word: str) -> str:
    
    184
    -    if os.name == 'nt':
    
    185
    -        return word.capitalize()
    
    186
    -    return word
    
    187 173
     
    
    188 174
     def get_uf_show(show: str, use_mnemonic: bool = False) -> str:
    
    189 175
         if use_mnemonic:
    
    190 176
             return SHOW_STRING_MNEMONIC[show]
    
    191 177
         return SHOW_STRING[show]
    
    192 178
     
    
    179
    +
    
    193 180
     def get_uf_sub(sub: str) -> str:
    
    194 181
         if sub == 'none':
    
    195 182
             uf_sub = Q_('?Subscription we already have:None')
    
    ... ... @@ -204,6 +191,7 @@ def get_uf_sub(sub: str) -> str:
    204 191
     
    
    205 192
         return uf_sub
    
    206 193
     
    
    194
    +
    
    207 195
     def get_uf_ask(ask: Union[str, None]) -> str:
    
    208 196
         if ask is None:
    
    209 197
             uf_ask = Q_('?Ask (for Subscription):None')
    
    ... ... @@ -214,6 +202,7 @@ def get_uf_ask(ask: Union[str, None]) -> str:
    214 202
     
    
    215 203
         return uf_ask
    
    216 204
     
    
    205
    +
    
    217 206
     def get_uf_role(role: Union[Role, str], plural: bool = False) -> str:
    
    218 207
         ''' plural determines if you get Moderators or Moderator'''
    
    219 208
         if not isinstance(role, str):
    
    ... ... @@ -235,6 +224,7 @@ def get_uf_role(role: Union[Role, str], plural: bool = False) -> str:
    235 224
             return _('Visitor')
    
    236 225
         return ''
    
    237 226
     
    
    227
    +
    
    238 228
     def get_uf_affiliation(affiliation: Union[Affiliation, str],
    
    239 229
                            plural: bool = False
    
    240 230
                            ) -> str:
    
    ... ... @@ -258,6 +248,7 @@ def get_uf_affiliation(affiliation: Union[Affiliation, str],
    258 248
             return _('Member')
    
    259 249
         return ''
    
    260 250
     
    
    251
    +
    
    261 252
     def get_uf_relative_time(timestamp: float) -> str:
    
    262 253
         date_time = datetime.fromtimestamp(timestamp)
    
    263 254
         now = datetime.now()
    
    ... ... @@ -282,9 +273,6 @@ def get_uf_relative_time(timestamp: float) -> str:
    282 273
                             minutes)
    
    283 274
         return _('Just now')
    
    284 275
     
    
    285
    -def get_sorted_keys(adict):
    
    286
    -    keys = sorted(adict.keys())
    
    287
    -    return keys
    
    288 276
     
    
    289 277
     def to_one_line(msg: str) -> str:
    
    290 278
         msg = msg.replace('\\', '\\\\')
    
    ... ... @@ -296,6 +284,7 @@ def to_one_line(msg: str) -> str:
    296 284
         # 'test\\ntest\\\\ntest'
    
    297 285
         return msg
    
    298 286
     
    
    287
    +
    
    299 288
     def from_one_line(msg: str) -> str:
    
    300 289
         # (?<!\\) is a lookbehind assertion which asks anything but '\'
    
    301 290
         # to match the regexp that follows it
    
    ... ... @@ -311,6 +300,7 @@ def from_one_line(msg: str) -> str:
    311 300
         # 'test\ntest\\ntest'
    
    312 301
         return msg
    
    313 302
     
    
    303
    +
    
    314 304
     def get_uf_chatstate(chatstate: str) -> str:
    
    315 305
         """
    
    316 306
         Remove chatstate jargon and returns user friendly messages
    
    ... ... @@ -322,12 +312,13 @@ def get_uf_chatstate(chatstate: str) -> str:
    322 312
         if chatstate == 'composing':
    
    323 313
             return _('is composing a message…')
    
    324 314
         if chatstate == 'paused':
    
    325
    -        #paused means he or she was composing but has stopped for a while
    
    315
    +        # paused means he or she was composing but has stopped for a while
    
    326 316
             return _('paused composing a message')
    
    327 317
         if chatstate == 'gone':
    
    328 318
             return _('has closed the chat window or tab')
    
    329 319
         return ''
    
    330 320
     
    
    321
    +
    
    331 322
     def exec_command(command: str,
    
    332 323
                      use_shell: bool = False,
    
    333 324
                      posix: bool = True
    
    ... ... @@ -344,6 +335,7 @@ def exec_command(command: str,
    344 335
             process = subprocess.Popen(args)
    
    345 336
             app.thread_interface(process.wait)
    
    346 337
     
    
    338
    +
    
    347 339
     def build_command(executable: str, parameter: str) -> str:
    
    348 340
         # we add to the parameter (can hold path with spaces)
    
    349 341
         # "" so we have good parsing from shell
    
    ... ... @@ -351,8 +343,9 @@ def build_command(executable: str, parameter: str) -> str:
    351 343
         command = f'{executable} "{parameter}"'
    
    352 344
         return command
    
    353 345
     
    
    346
    +
    
    354 347
     def get_file_path_from_dnd_dropped_uri(uri: str) -> str:
    
    355
    -    path = urllib.parse.unquote(uri)  # escape special chars
    
    348
    +    path = unquote(uri)  # escape special chars
    
    356 349
         path = path.strip('\r\n\x00')  # remove \r\n and NULL
    
    357 350
         # get the path to file
    
    358 351
         if re.match('^file:///[a-zA-Z]:/', path):  # windows
    
    ... ... @@ -363,6 +356,7 @@ def get_file_path_from_dnd_dropped_uri(uri: str) -> str:
    363 356
             path = path[5:]  # 5 is len('file:')
    
    364 357
         return path
    
    365 358
     
    
    359
    +
    
    366 360
     def sanitize_filename(filename: str) -> str:
    
    367 361
         """
    
    368 362
         Make sure the filename we will write does contain only acceptable and latin
    
    ... ... @@ -383,6 +377,7 @@ def sanitize_filename(filename: str) -> str:
    383 377
     
    
    384 378
         return filename
    
    385 379
     
    
    380
    +
    
    386 381
     def reduce_chars_newlines(text: str, max_chars: int = 0,
    
    387 382
                               max_lines: int = 0) -> str:
    
    388 383
         """
    
    ... ... @@ -464,7 +459,10 @@ def check_soundfile_path(file_: str,
    464 459
                 return dir_
    
    465 460
         return None
    
    466 461
     
    
    467
    -def strip_soundfile_path(file_, dirs=None, abs_=True):
    
    462
    +
    
    463
    +def strip_soundfile_path(file_: Union[Path, str],
    
    464
    +                         dirs: Optional[list[Path]] = None,
    
    465
    +                         abs_: bool = True):
    
    468 466
         """
    
    469 467
         Remove knowns paths from a sound file
    
    470 468
     
    
    ... ... @@ -494,6 +492,7 @@ def strip_soundfile_path(file_, dirs=None, abs_=True):
    494 492
                 return name
    
    495 493
         return file_
    
    496 494
     
    
    495
    +
    
    497 496
     def play_sound_file(str_path_to_soundfile: str, loop: bool = False) -> None:
    
    498 497
         path_to_soundfile = check_soundfile_path(str_path_to_soundfile)
    
    499 498
         if path_to_soundfile is None:
    
    ... ... @@ -502,6 +501,7 @@ def play_sound_file(str_path_to_soundfile: str, loop: bool = False) -> None:
    502 501
         from gajim.common import sound
    
    503 502
         sound.play(path_to_soundfile, loop)
    
    504 503
     
    
    504
    +
    
    505 505
     def get_client_status(account: str) -> str:
    
    506 506
         client = app.get_client(account)
    
    507 507
         if client.state.is_disconnected:
    
    ... ... @@ -514,6 +514,7 @@ def get_client_status(account: str) -> str:
    514 514
     
    
    515 515
         return client.status
    
    516 516
     
    
    517
    +
    
    517 518
     def get_global_show() -> str:
    
    518 519
         maxi = 0
    
    519 520
         for account in app.connections:
    
    ... ... @@ -526,6 +527,7 @@ def get_global_show() -> str:
    526 527
                 maxi = index
    
    527 528
         return SHOW_LIST[maxi]
    
    528 529
     
    
    530
    +
    
    529 531
     def get_global_status_message() -> str:
    
    530 532
         maxi = 0
    
    531 533
         status_message = ''
    
    ... ... @@ -539,6 +541,7 @@ def get_global_status_message() -> str:
    539 541
                 status_message = con.status_message
    
    540 542
         return status_message
    
    541 543
     
    
    544
    +
    
    542 545
     def statuses_unified() -> bool:
    
    543 546
         """
    
    544 547
         Test if all statuses are the same
    
    ... ... @@ -566,6 +569,7 @@ def get_full_jid_from_iq(iq_obj: Iq) -> Optional[str]:
    566 569
             return None
    
    567 570
         return parse_jid(str(iq_obj.getFrom()))
    
    568 571
     
    
    572
    +
    
    569 573
     def get_jid_from_iq(iq_obj: Iq) -> Optional[str]:
    
    570 574
         """
    
    571 575
         Return the jid (without resource) from an iq
    
    ... ... @@ -575,6 +579,7 @@ def get_jid_from_iq(iq_obj: Iq) -> Optional[str]:
    575 579
             return None
    
    576 580
         return app.get_jid_without_resource(jid)
    
    577 581
     
    
    582
    +
    
    578 583
     def get_auth_sha(sid: str, initiator: str, target: str) -> str:
    
    579 584
         """
    
    580 585
         Return sha of sid + initiator + target used for proxy auth
    
    ... ... @@ -582,11 +587,13 @@ def get_auth_sha(sid: str, initiator: str, target: str) -> str:
    582 587
         return hashlib.sha1(
    
    583 588
             (f'{sid}{initiator}{target}').encode('utf-8')).hexdigest()
    
    584 589
     
    
    590
    +
    
    585 591
     def remove_invalid_xml_chars(string_: str) -> str:
    
    586 592
         if string_:
    
    587 593
             string_ = re.sub(INVALID_XML_CHARS_REGEX, '', string_)
    
    588 594
         return string_
    
    589 595
     
    
    596
    +
    
    590 597
     def get_random_string(count: int = 16) -> str:
    
    591 598
         """
    
    592 599
         Create random string of count length
    
    ... ... @@ -661,7 +668,7 @@ def allow_sound_notification(account: str, sound_event: str) -> bool:
    661 668
         return False
    
    662 669
     
    
    663 670
     
    
    664
    -def get_optional_features(account: str) -> list[Namespace]:
    
    671
    +def get_optional_features(account: str) -> list[str]:
    
    665 672
         features: list[str] = []
    
    666 673
     
    
    667 674
         if app.settings.get_account_setting(account, 'request_user_data'):
    
    ... ... @@ -684,10 +691,12 @@ def get_optional_features(account: str) -> list[Namespace]:
    684 691
         app.plugin_manager.extension_point('update_caps', account, features)
    
    685 692
         return features
    
    686 693
     
    
    694
    +
    
    687 695
     def jid_is_blocked(account: str, jid: str) -> bool:
    
    688 696
         con = app.connections[account]
    
    689 697
         return jid in con.get_module('Blocking').blocked
    
    690 698
     
    
    699
    +
    
    691 700
     def get_subscription_request_msg(account: Optional[str] = None) -> str:
    
    692 701
         message = _('I would like to add you to my contact list.')
    
    693 702
         if account is None:
    
    ... ... @@ -701,8 +710,11 @@ def get_subscription_request_msg(account: Optional[str] = None) -> str:
    701 710
         message = _('Hello, I am $name. %s') % message
    
    702 711
         return Template(message).safe_substitute({'name': app.nicks[account]})
    
    703 712
     
    
    704
    -def get_retraction_text(account: str, moderator_jid: str,
    
    713
    +
    
    714
    +def get_retraction_text(account: str,
    
    715
    +                        moderator_jid: str,
    
    705 716
                             reason: Optional[str]) -> str:
    
    717
    +
    
    706 718
         client = app.get_client(account)
    
    707 719
         contact = client.get_module('Contacts').get_contact(
    
    708 720
             moderator_jid, groupchat=True)
    
    ... ... @@ -711,12 +723,14 @@ def get_retraction_text(account: str, moderator_jid: str,
    711 723
             text += ' ' + _('Reason: %s') % reason
    
    712 724
         return text
    
    713 725
     
    
    726
    +
    
    714 727
     def get_global_proxy() -> Optional[ProxyData]:
    
    715 728
         proxy_name = app.settings.get('global_proxy')
    
    716 729
         if not proxy_name:
    
    717 730
             return None
    
    718 731
         return get_proxy(proxy_name)
    
    719 732
     
    
    733
    +
    
    720 734
     def get_account_proxy(account: str, fallback=True) -> Optional[ProxyData]:
    
    721 735
         proxy_name = app.settings.get_account_setting(account, 'proxy')
    
    722 736
         if proxy_name:
    
    ... ... @@ -726,6 +740,7 @@ def get_account_proxy(account: str, fallback=True) -> Optional[ProxyData]:
    726 740
             return get_global_proxy()
    
    727 741
         return None
    
    728 742
     
    
    743
    +
    
    729 744
     def get_proxy(proxy_name: str) -> Optional[ProxyData]:
    
    730 745
         try:
    
    731 746
             settings = app.settings.get_proxy_settings(proxy_name)
    
    ... ... @@ -741,11 +756,13 @@ def get_proxy(proxy_name: str) -> Optional[ProxyData]:
    741 756
                          username=username,
    
    742 757
                          password=password)
    
    743 758
     
    
    759
    +
    
    744 760
     def version_condition(current_version: str, required_version: str) -> bool:
    
    745 761
         if V(current_version) < V(required_version):
    
    746 762
             return False
    
    747 763
         return True
    
    748 764
     
    
    765
    +
    
    749 766
     def get_available_emoticon_themes() -> list[str]:
    
    750 767
         files: list[Path] = []
    
    751 768
         for folder in configpaths.get('EMOTICONS').iterdir():
    
    ... ... @@ -761,6 +778,7 @@ def get_available_emoticon_themes() -> list[str]:
    761 778
         emoticons_themes += [file.stem for file in files if file.suffix == '.png']
    
    762 779
         return sorted(emoticons_themes)
    
    763 780
     
    
    781
    +
    
    764 782
     def call_counter(func):
    
    765 783
         def helper(self, restart=False):
    
    766 784
             if restart:
    
    ... ... @@ -769,6 +787,7 @@ def helper(self, restart=False):
    769 787
             return func(self)
    
    770 788
         return helper
    
    771 789
     
    
    790
    +
    
    772 791
     def load_json(path: Path,
    
    773 792
                   key: Optional[str] = None,
    
    774 793
                   default: Optional[Any] = None) -> Any: