Philipp Hörist pushed to branch master at gajim / gajim
Commits:
-
1ac4fd7a
by André Apitzsch at 2021-02-13T18:09:40+01:00
-
b243c3c0
by André Apitzsch at 2021-02-13T18:09:41+01:00
7 changed files:
- gajim/common/helpers.py
- + gajim/common/regex.py
- gajim/conversation_textview.py
- gajim/gtk/message_input.py
- gajim/gui_interface.py
- + test/no_gui/test_regex.py
- test/unit/test_gui_interface.py
Changes:
| ... | ... | @@ -80,6 +80,8 @@ |
| 80 | 80 |
from gajim.common.const import URIAction
|
| 81 | 81 |
from gajim.common.const import GIO_TLS_ERRORS
|
| 82 | 82 |
from gajim.common.const import SHOW_LIST
|
| 83 |
+from gajim.common.regex import INVALID_XML_CHARS_REGEX
|
|
| 84 |
+from gajim.common.regex import STH_AT_STH_DOT_STH_REGEX
|
|
| 83 | 85 |
from gajim.common.structs import URI
|
| 84 | 86 |
|
| 85 | 87 |
|
| ... | ... | @@ -632,7 +634,7 @@ def get_auth_sha(sid, initiator, target): |
| 632 | 634 |
|
| 633 | 635 |
def remove_invalid_xml_chars(string_):
|
| 634 | 636 |
if string_:
|
| 635 |
- string_ = re.sub(app.interface.invalid_XML_chars_re, '', string_)
|
|
| 637 |
+ string_ = re.sub(INVALID_XML_CHARS_REGEX, '', string_)
|
|
| 636 | 638 |
return string_
|
| 637 | 639 |
|
| 638 | 640 |
def get_random_string(count=16):
|
| ... | ... | @@ -1067,7 +1069,7 @@ def parse_uri(uri): |
| 1067 | 1069 |
uri = uri[4:]
|
| 1068 | 1070 |
return URI(type=URIType.TEL, data=uri)
|
| 1069 | 1071 |
|
| 1070 |
- if app.interface.sth_at_sth_dot_sth_re.match(uri):
|
|
| 1072 |
+ if STH_AT_STH_DOT_STH_REGEX.match(uri):
|
|
| 1071 | 1073 |
return URI(type=URIType.AT, data=uri)
|
| 1072 | 1074 |
|
| 1073 | 1075 |
if uri.startswith('geo:'):
|
| 1 |
+import re
|
|
| 2 |
+ |
|
| 3 |
+def _get_link_pattern():
|
|
| 4 |
+ # regexp meta characters are: . ^ $ * + ? { } [ ] \ | ( )
|
|
| 5 |
+ # one escapes the metachars with \
|
|
| 6 |
+ # \S matches anything but ' ' '\t' '\n' '\r' '\f' and '\v'
|
|
| 7 |
+ # \s matches any whitespace character
|
|
| 8 |
+ # \w any alphanumeric character
|
|
| 9 |
+ # \W any non-alphanumeric character
|
|
| 10 |
+ # \b means word boundary. This is a zero-width assertion that
|
|
| 11 |
+ # matches only at the beginning or end of a word.
|
|
| 12 |
+ # ^ matches at the beginning of lines
|
|
| 13 |
+ #
|
|
| 14 |
+ # * means 0 or more times
|
|
| 15 |
+ # + means 1 or more times
|
|
| 16 |
+ # ? means 0 or 1 time
|
|
| 17 |
+ # | means or
|
|
| 18 |
+ # [^*] anything but '*' (inside [] you don't have to escape metachars)
|
|
| 19 |
+ # [^\s*] anything but whitespaces and '*'
|
|
| 20 |
+ # (?<!\S) is a one char lookbehind assertion and asks for any leading
|
|
| 21 |
+ # whitespace
|
|
| 22 |
+ # and matches beginning of lines so we have correct formatting detection
|
|
| 23 |
+ # even if the text is just '*foo*'
|
|
| 24 |
+ # (?!\S) is the same thing but it's a lookahead assertion
|
|
| 25 |
+ # \S*[^\s\W] --> in the matching string don't match ? or ) etc.. if at
|
|
| 26 |
+ # the end
|
|
| 27 |
+ # so http://be) will match http://be and http://be)be) will match
|
|
| 28 |
+ # http://be)be
|
|
| 29 |
+ |
|
| 30 |
+ legacy_prefixes = r"((?<=\()(www|ftp)\.([A-Za-z0-9\.\-_~:/\?#\[\]@!\$"\
|
|
| 31 |
+ r"&'\(\)\*\+,;=]|%[A-Fa-f0-9]{2})+(?=\)))"\
|
|
| 32 |
+ r"|((www|ftp)\.([A-Za-z0-9\.\-_~:/\?#\[\]@!\$&'\(\)\*\+,;=]"\
|
|
| 33 |
+ r"|%[A-Fa-f0-9]{2})+"\
|
|
| 34 |
+ r"\.([A-Za-z0-9\.\-_~:/\?#\[\]@!\$&'\(\)\*\+,;=]|%[A-Fa-f0-9]{2})+)"
|
|
| 35 |
+ # NOTE: it's ok to catch www.gr such stuff exist!
|
|
| 36 |
+ |
|
| 37 |
+ # FIXME: recognize xmpp: and treat it specially
|
|
| 38 |
+ links = r"((?<=\()[A-Za-z][A-Za-z0-9\+\.\-]*:"\
|
|
| 39 |
+ r"([\w\.\-_~:/\?#\[\]@!\$&'\(\)\*\+,;=]|%[A-Fa-f0-9]{2})+"\
|
|
| 40 |
+ r"(?=\)))|(\w[\w\+\.\-]*:([^<>\s]|%[A-Fa-f0-9]{2})+)"
|
|
| 41 |
+ |
|
| 42 |
+ # 2nd one: at_least_one_char@at_least_one_char.at_least_one_char
|
|
| 43 |
+ mail = r'\bmailto:\S*[^\s\W]|' r'\b\S+@\S+\.\S*[^\s\W]'
|
|
| 44 |
+ |
|
| 45 |
+ link_pattern = links + '|' + mail + '|' + legacy_prefixes
|
|
| 46 |
+ return link_pattern
|
|
| 47 |
+ |
|
| 48 |
+def _get_basic_pattern():
|
|
| 49 |
+ basic_pattern = _get_link_pattern()
|
|
| 50 |
+ # detects eg. *b* *bold* *bold bold* test *bold* *bold*! (*bold*)
|
|
| 51 |
+ # doesn't detect (it's a feature :P) * bold* *bold * * bold * test*bold*
|
|
| 52 |
+ formatting = r'|(?<!\w)' r'\*[^\s*]' r'([^*]*[^\s*])?' r'\*(?!\w)|'\
|
|
| 53 |
+ r'(?<!\S)' r'~[^\s~]' r'([^~]*[^\s~])?' r'~(?!\S)|'\
|
|
| 54 |
+ r'(?<!\w)' r'_[^\s_]' r'([^_]*[^\s_])?' r'_(?!\w)'
|
|
| 55 |
+ return basic_pattern + formatting
|
|
| 56 |
+ |
|
| 57 |
+def _get_emot_and_basic_pattern(use_ascii_formatting=True):
|
|
| 58 |
+ from gajim.gui.emoji_data import emoji_data
|
|
| 59 |
+ # because emoticons match later (in the string) they need to be after
|
|
| 60 |
+ # basic matches that may occur earlier
|
|
| 61 |
+ emoticons = emoji_data.get_regex()
|
|
| 62 |
+ |
|
| 63 |
+ if use_ascii_formatting:
|
|
| 64 |
+ pattern = _get_basic_pattern()
|
|
| 65 |
+ else:
|
|
| 66 |
+ pattern = _get_link_pattern()
|
|
| 67 |
+ |
|
| 68 |
+ return '%s|%s' % (pattern, emoticons)
|
|
| 69 |
+ |
|
| 70 |
+LINK_REGEX = re.compile(_get_link_pattern(), re.I | re.U)
|
|
| 71 |
+ |
|
| 72 |
+# link pattern + ASCII formatting
|
|
| 73 |
+BASIC_REGEX = re.compile(_get_basic_pattern(), re.IGNORECASE)
|
|
| 74 |
+ |
|
| 75 |
+# emoticons + link pattern
|
|
| 76 |
+EMOT_AND_LINK_REGEX = re.compile(_get_emot_and_basic_pattern(False),
|
|
| 77 |
+ re.IGNORECASE)
|
|
| 78 |
+ |
|
| 79 |
+# emoticons + link pattern + ASCII formatting
|
|
| 80 |
+EMOT_AND_BASIC_REGEX = re.compile(_get_emot_and_basic_pattern(True),
|
|
| 81 |
+ re.IGNORECASE)
|
|
| 82 |
+ |
|
| 83 |
+INVALID_XML_CHARS_REGEX = re.compile(
|
|
| 84 |
+ '[\x00-\x08]|[\x0b-\x0c]|[\x0e-\x1f]|[\ud800-\udfff]|[\ufffe-\uffff]')
|
|
| 85 |
+ |
|
| 86 |
+# at least one character in 3 parts (before @, after @, after .)
|
|
| 87 |
+STH_AT_STH_DOT_STH_REGEX = re.compile(
|
|
| 88 |
+ r'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$')
|
| ... | ... | @@ -44,6 +44,11 @@ |
| 44 | 44 |
from gajim.common.const import Trust
|
| 45 | 45 |
from gajim.common.const import URI_SCHEMES
|
| 46 | 46 |
from gajim.common.helpers import to_user_string
|
| 47 |
+from gajim.common.regex import STH_AT_STH_DOT_STH_REGEX
|
|
| 48 |
+from gajim.common.regex import BASIC_REGEX
|
|
| 49 |
+from gajim.common.regex import LINK_REGEX
|
|
| 50 |
+from gajim.common.regex import EMOT_AND_BASIC_REGEX
|
|
| 51 |
+from gajim.common.regex import EMOT_AND_LINK_REGEX
|
|
| 47 | 52 |
|
| 48 | 53 |
from gajim.gui import util
|
| 49 | 54 |
from gajim.gui.util import get_cursor
|
| ... | ... | @@ -584,9 +589,17 @@ def detect_and_print_special_text(self, otext, other_tags, graphics=True, |
| 584 | 589 |
# basic: links + mail + formatting is always checked (we like that)
|
| 585 | 590 |
if app.settings.get('emoticons_theme') and graphics:
|
| 586 | 591 |
# search for emoticons & urls
|
| 587 |
- iterator = app.interface.emot_and_basic_re.finditer(otext)
|
|
| 588 |
- else: # search for just urls + mail + formatting
|
|
| 589 |
- iterator = app.interface.basic_pattern_re.finditer(otext)
|
|
| 592 |
+ if app.settings.get('ascii_formatting'):
|
|
| 593 |
+ regex = EMOT_AND_BASIC_REGEX
|
|
| 594 |
+ else:
|
|
| 595 |
+ regex = EMOT_AND_LINK_REGEX
|
|
| 596 |
+ else:
|
|
| 597 |
+ if app.settings.get('ascii_formatting'):
|
|
| 598 |
+ # search for just urls + mail + formatting
|
|
| 599 |
+ regex = BASIC_REGEX
|
|
| 600 |
+ else: # search for just urls + mail
|
|
| 601 |
+ regex = LINK_REGEX
|
|
| 602 |
+ iterator = regex.finditer(otext)
|
|
| 590 | 603 |
if iter_:
|
| 591 | 604 |
end_iter = iter_
|
| 592 | 605 |
else:
|
| ... | ... | @@ -693,7 +706,7 @@ def print_special_text(self, special_text, other_tags, graphics=True, |
| 693 | 706 |
tags.append('mail')
|
| 694 | 707 |
elif special_text.startswith('xmpp:') and not is_xhtml_link:
|
| 695 | 708 |
tags.append('xmpp')
|
| 696 |
- elif app.interface.sth_at_sth_dot_sth_re.match(special_text) and\
|
|
| 709 |
+ elif STH_AT_STH_DOT_STH_REGEX.match(special_text) and \
|
|
| 697 | 710 |
not is_xhtml_link:
|
| 698 | 711 |
# it's a JID or mail
|
| 699 | 712 |
tags.append('sth_at_sth')
|
| ... | ... | @@ -28,6 +28,7 @@ |
| 28 | 28 |
from gajim.common import app
|
| 29 | 29 |
from gajim.common.i18n import _
|
| 30 | 30 |
from gajim.common.const import StyleAttr
|
| 31 |
+from gajim.common.regex import LINK_REGEX
|
|
| 31 | 32 |
|
| 32 | 33 |
from .util import scroll_to_end
|
| 33 | 34 |
|
| ... | ... | @@ -207,7 +208,7 @@ def make_clickable_urls(self, text): |
| 207 | 208 |
index = 0
|
| 208 | 209 |
|
| 209 | 210 |
new_text = ''
|
| 210 |
- iterator = app.interface.link_pattern_re.finditer(text)
|
|
| 211 |
+ iterator = LINK_REGEX.finditer(text)
|
|
| 211 | 212 |
for match in iterator:
|
| 212 | 213 |
start, end = match.span()
|
| 213 | 214 |
url = text[start:end]
|
| ... | ... | @@ -33,7 +33,6 @@ |
| 33 | 33 |
|
| 34 | 34 |
import os
|
| 35 | 35 |
import sys
|
| 36 |
-import re
|
|
| 37 | 36 |
import time
|
| 38 | 37 |
import json
|
| 39 | 38 |
import logging
|
| ... | ... | @@ -101,7 +100,6 @@ |
| 101 | 100 |
from gajim.gui.dialogs import InputDialog
|
| 102 | 101 |
from gajim.gui.dialogs import PassphraseDialog
|
| 103 | 102 |
from gajim.gui.filechoosers import FileChooserDialog
|
| 104 |
-from gajim.gui.emoji_data import emoji_data
|
|
| 105 | 103 |
from gajim.gui.filetransfer import FileTransfersWindow
|
| 106 | 104 |
from gajim.gui.filetransfer_progress import FileTransferProgress
|
| 107 | 105 |
from gajim.gui.roster_item_exchange import RosterItemExchangeWindow
|
| ... | ... | @@ -1296,112 +1294,6 @@ def handle_event(self, account, fjid, type_): |
| 1296 | 1294 |
if isinstance(ctrl, ChatControlBase):
|
| 1297 | 1295 |
ctrl.scroll_to_end()
|
| 1298 | 1296 |
|
| 1299 |
-################################################################################
|
|
| 1300 |
-### Methods dealing with emoticons
|
|
| 1301 |
-################################################################################
|
|
| 1302 |
- |
|
| 1303 |
- @property
|
|
| 1304 |
- def basic_pattern_re(self):
|
|
| 1305 |
- if not self._basic_pattern_re:
|
|
| 1306 |
- self._basic_pattern_re = re.compile(self.basic_pattern,
|
|
| 1307 |
- re.IGNORECASE)
|
|
| 1308 |
- return self._basic_pattern_re
|
|
| 1309 |
- |
|
| 1310 |
- @property
|
|
| 1311 |
- def emot_and_basic_re(self):
|
|
| 1312 |
- if not self._emot_and_basic_re:
|
|
| 1313 |
- self._emot_and_basic_re = re.compile(
|
|
| 1314 |
- self.emot_and_basic, re.IGNORECASE)
|
|
| 1315 |
- return self._emot_and_basic_re
|
|
| 1316 |
- |
|
| 1317 |
- @property
|
|
| 1318 |
- def sth_at_sth_dot_sth_re(self):
|
|
| 1319 |
- if not self._sth_at_sth_dot_sth_re:
|
|
| 1320 |
- self._sth_at_sth_dot_sth_re = re.compile(self.sth_at_sth_dot_sth)
|
|
| 1321 |
- return self._sth_at_sth_dot_sth_re
|
|
| 1322 |
- |
|
| 1323 |
- @property
|
|
| 1324 |
- def invalid_XML_chars_re(self):
|
|
| 1325 |
- if not self._invalid_XML_chars_re:
|
|
| 1326 |
- self._invalid_XML_chars_re = re.compile(self.invalid_XML_chars)
|
|
| 1327 |
- return self._invalid_XML_chars_re
|
|
| 1328 |
- |
|
| 1329 |
- def make_regexps(self):
|
|
| 1330 |
- # regexp meta characters are: . ^ $ * + ? { } [ ] \ | ( )
|
|
| 1331 |
- # one escapes the metachars with \
|
|
| 1332 |
- # \S matches anything but ' ' '\t' '\n' '\r' '\f' and '\v'
|
|
| 1333 |
- # \s matches any whitespace character
|
|
| 1334 |
- # \w any alphanumeric character
|
|
| 1335 |
- # \W any non-alphanumeric character
|
|
| 1336 |
- # \b means word boundary. This is a zero-width assertion that
|
|
| 1337 |
- # matches only at the beginning or end of a word.
|
|
| 1338 |
- # ^ matches at the beginning of lines
|
|
| 1339 |
- #
|
|
| 1340 |
- # * means 0 or more times
|
|
| 1341 |
- # + means 1 or more times
|
|
| 1342 |
- # ? means 0 or 1 time
|
|
| 1343 |
- # | means or
|
|
| 1344 |
- # [^*] anything but '*' (inside [] you don't have to escape metachars)
|
|
| 1345 |
- # [^\s*] anything but whitespaces and '*'
|
|
| 1346 |
- # (?<!\S) is a one char lookbehind assertion and asks for any leading
|
|
| 1347 |
- # whitespace
|
|
| 1348 |
- # and matches beginning of lines so we have correct formatting detection
|
|
| 1349 |
- # even if the text is just '*foo*'
|
|
| 1350 |
- # (?!\S) is the same thing but it's a lookahead assertion
|
|
| 1351 |
- # \S*[^\s\W] --> in the matching string don't match ? or ) etc.. if at
|
|
| 1352 |
- # the end
|
|
| 1353 |
- # so http://be) will match http://be and http://be)be) will match
|
|
| 1354 |
- # http://be)be
|
|
| 1355 |
- |
|
| 1356 |
- self._basic_pattern_re = None
|
|
| 1357 |
- self._emot_and_basic_re = None
|
|
| 1358 |
- self._sth_at_sth_dot_sth_re = None
|
|
| 1359 |
- self._invalid_XML_chars_re = None
|
|
| 1360 |
- |
|
| 1361 |
- legacy_prefixes = r"((?<=\()(www|ftp)\.([A-Za-z0-9\.\-_~:/\?#\[\]@!\$"\
|
|
| 1362 |
- r"&'\(\)\*\+,;=]|%[A-Fa-f0-9]{2})+(?=\)))"\
|
|
| 1363 |
- r"|((www|ftp)\.([A-Za-z0-9\.\-_~:/\?#\[\]@!\$&'\(\)\*\+,;=]"\
|
|
| 1364 |
- r"|%[A-Fa-f0-9]{2})+"\
|
|
| 1365 |
- r"\.([A-Za-z0-9\.\-_~:/\?#\[\]@!\$&'\(\)\*\+,;=]|%[A-Fa-f0-9]{2})+)"
|
|
| 1366 |
- # NOTE: it's ok to catch www.gr such stuff exist!
|
|
| 1367 |
- |
|
| 1368 |
- # FIXME: recognize xmpp: and treat it specially
|
|
| 1369 |
- links = r"((?<=\()[A-Za-z][A-Za-z0-9\+\.\-]*:"\
|
|
| 1370 |
- r"([\w\.\-_~:/\?#\[\]@!\$&'\(\)\*\+,;=]|%[A-Fa-f0-9]{2})+"\
|
|
| 1371 |
- r"(?=\)))|(\w[\w\+\.\-]*:([^<>\s]|%[A-Fa-f0-9]{2})+)"
|
|
| 1372 |
- |
|
| 1373 |
- # 2nd one: at_least_one_char@at_least_one_char.at_least_one_char
|
|
| 1374 |
- mail = r'\bmailto:\S*[^\s\W]|' r'\b\S+@\S+\.\S*[^\s\W]'
|
|
| 1375 |
- |
|
| 1376 |
- # detects eg. *b* *bold* *bold bold* test *bold* *bold*! (*bold*)
|
|
| 1377 |
- # doesn't detect (it's a feature :P) * bold* *bold * * bold * test*bold*
|
|
| 1378 |
- formatting = r'|(?<!\w)' r'\*[^\s*]' r'([^*]*[^\s*])?' r'\*(?!\w)|'\
|
|
| 1379 |
- r'(?<!\S)' r'~[^\s~]' r'([^~]*[^\s~])?' r'~(?!\S)|'\
|
|
| 1380 |
- r'(?<!\w)' r'_[^\s_]' r'([^_]*[^\s_])?' r'_(?!\w)'
|
|
| 1381 |
- |
|
| 1382 |
- basic_pattern = links + '|' + mail + '|' + legacy_prefixes
|
|
| 1383 |
- |
|
| 1384 |
- link_pattern = basic_pattern
|
|
| 1385 |
- self.link_pattern_re = re.compile(link_pattern, re.I | re.U)
|
|
| 1386 |
- |
|
| 1387 |
- if app.settings.get('ascii_formatting'):
|
|
| 1388 |
- basic_pattern += formatting
|
|
| 1389 |
- self.basic_pattern = basic_pattern
|
|
| 1390 |
- |
|
| 1391 |
- # because emoticons match later (in the string) they need to be after
|
|
| 1392 |
- # basic matches that may occur earlier
|
|
| 1393 |
- emoticons = emoji_data.get_regex()
|
|
| 1394 |
- |
|
| 1395 |
- self.emot_and_basic = '%s|%s' % (basic_pattern, emoticons)
|
|
| 1396 |
- |
|
| 1397 |
- # at least one character in 3 parts (before @, after @, after .)
|
|
| 1398 |
- self.sth_at_sth_dot_sth = r'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$'
|
|
| 1399 |
- |
|
| 1400 |
- # Invalid XML chars
|
|
| 1401 |
- self.invalid_XML_chars = '[\x00-\x08]|[\x0b-\x0c]|[\x0e-\x1f]|'\
|
|
| 1402 |
- '[\ud800-\udfff]|[\ufffe-\uffff]'
|
|
| 1403 |
- |
|
| 1404 |
- |
|
| 1405 | 1297 |
################################################################################
|
| 1406 | 1298 |
### Methods for opening new messages controls
|
| 1407 | 1299 |
################################################################################
|
| ... | ... | @@ -2114,15 +2006,6 @@ def __init__(self): |
| 2114 | 2006 |
|
| 2115 | 2007 |
self.handlers = {}
|
| 2116 | 2008 |
self.roster = None
|
| 2117 |
- self._invalid_XML_chars_re = None
|
|
| 2118 |
- self._basic_pattern_re = None
|
|
| 2119 |
- self._emot_and_basic_re = None
|
|
| 2120 |
- self._sth_at_sth_dot_sth_re = None
|
|
| 2121 |
- self.link_pattern_re = None
|
|
| 2122 |
- self.invalid_XML_chars = None
|
|
| 2123 |
- self.basic_pattern = None
|
|
| 2124 |
- self.emot_and_basic = None
|
|
| 2125 |
- self.sth_at_sth_dot_sth = None
|
|
| 2126 | 2009 |
|
| 2127 | 2010 |
self.avatar_storage = AvatarStorage()
|
| 2128 | 2011 |
|
| ... | ... | @@ -2199,8 +2082,6 @@ def __init__(self): |
| 2199 | 2082 |
from gajim.gui.emoji_chooser import emoji_chooser
|
| 2200 | 2083 |
emoji_chooser.load()
|
| 2201 | 2084 |
|
| 2202 |
- self.make_regexps()
|
|
| 2203 |
- |
|
| 2204 | 2085 |
self.last_ftwindow_update = 0
|
| 2205 | 2086 |
|
| 2206 | 2087 |
self._network_monitor = Gio.NetworkMonitor.get_default()
|
| 1 |
+import unittest
|
|
| 2 |
+ |
|
| 3 |
+from gajim import gui
|
|
| 4 |
+gui.init('gtk')
|
|
| 5 |
+import gajim.common.regex as regex
|
|
| 6 |
+ |
|
| 7 |
+class Test(unittest.TestCase):
|
|
| 8 |
+ def test_links_regexp_entire(self):
|
|
| 9 |
+ def assert_matches_all(str_):
|
|
| 10 |
+ m = regex.BASIC_REGEX.match(str_)
|
|
| 11 |
+ |
|
| 12 |
+ # the match should equal the string
|
|
| 13 |
+ str_span = (0, len(str_))
|
|
| 14 |
+ self.assertEqual(m.span(), str_span)
|
|
| 15 |
+ |
|
| 16 |
+ # these entire strings should be parsed as links
|
|
| 17 |
+ assert_matches_all('http://google.com/')
|
|
| 18 |
+ assert_matches_all('http://google.com')
|
|
| 19 |
+ assert_matches_all('http://www.google.ca/search?q=xmpp')
|
|
| 20 |
+ |
|
| 21 |
+ assert_matches_all('http://tools.ietf.org/html/draft-saintandre-rfc3920bis-05#section-12.3')
|
|
| 22 |
+ |
|
| 23 |
+ assert_matches_all('http://en.wikipedia.org/wiki/Protocol_(computing)')
|
|
| 24 |
+ assert_matches_all(
|
|
| 25 |
+ 'http://en.wikipedia.org/wiki/Protocol_%28computing%29')
|
|
| 26 |
+ |
|
| 27 |
+ assert_matches_all('mailto:test@example.org')
|
|
| 28 |
+ |
|
| 29 |
+ assert_matches_all('xmpp:example-node@example.com')
|
|
| 30 |
+ assert_matches_all('xmpp:example-node@example.com/some-resource')
|
|
| 31 |
+ assert_matches_all('xmpp:example-node@example.com?message')
|
|
| 32 |
+ assert_matches_all('xmpp://guest@example.com/support@example.com?message')
|
|
| 33 |
+ |
|
| 34 |
+ |
|
| 35 |
+if __name__ == "__main__":
|
|
| 36 |
+ unittest.main()
|
| ... | ... | @@ -24,33 +24,6 @@ def close_app(): |
| 24 | 24 |
GLib.idle_add(close_app)
|
| 25 | 25 |
app.app.run()
|
| 26 | 26 |
|
| 27 |
- def test_links_regexp_entire(self):
|
|
| 28 |
- sut = Interface()
|
|
| 29 |
- def assert_matches_all(str_):
|
|
| 30 |
- m = sut.basic_pattern_re.match(str_)
|
|
| 31 |
- |
|
| 32 |
- # the match should equal the string
|
|
| 33 |
- str_span = (0, len(str_))
|
|
| 34 |
- self.assertEqual(m.span(), str_span)
|
|
| 35 |
- |
|
| 36 |
- # these entire strings should be parsed as links
|
|
| 37 |
- assert_matches_all('http://google.com/')
|
|
| 38 |
- assert_matches_all('http://google.com')
|
|
| 39 |
- assert_matches_all('http://www.google.ca/search?q=xmpp')
|
|
| 40 |
- |
|
| 41 |
- assert_matches_all('http://tools.ietf.org/html/draft-saintandre-rfc3920bis-05#section-12.3')
|
|
| 42 |
- |
|
| 43 |
- assert_matches_all('http://en.wikipedia.org/wiki/Protocol_(computing)')
|
|
| 44 |
- assert_matches_all(
|
|
| 45 |
- 'http://en.wikipedia.org/wiki/Protocol_%28computing%29')
|
|
| 46 |
- |
|
| 47 |
- assert_matches_all('mailto:test@example.org')
|
|
| 48 |
- |
|
| 49 |
- assert_matches_all('xmpp:example-node@example.com')
|
|
| 50 |
- assert_matches_all('xmpp:example-node@example.com/some-resource')
|
|
| 51 |
- assert_matches_all('xmpp:example-node@example.com?message')
|
|
| 52 |
- assert_matches_all('xmpp://guest@example.com/support@example.com?message')
|
|
| 53 |
- |
|
| 54 | 27 |
|
| 55 | 28 |
if __name__ == "__main__":
|
| 56 | 29 |
unittest.main()
|