mirror of https://github.com/zulip/zulip.git
mypy: Convert more zerver/lib files to typing.Text.
This commit touches files in zerver/lib/bugdown/ and zerver/lib/webhooks.
This commit is contained in:
parent
c51d2c3d8f
commit
690d72d35f
|
@ -1,7 +1,7 @@
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
# Zulip's main markdown implementation. See docs/markdown.md for
|
# Zulip's main markdown implementation. See docs/markdown.md for
|
||||||
# detailed documentation on our markdown syntax.
|
# detailed documentation on our markdown syntax.
|
||||||
from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, TypeVar, Union
|
from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, TypeVar, Union, Text
|
||||||
from typing.re import Match
|
from typing.re import Match
|
||||||
|
|
||||||
import markdown
|
import markdown
|
||||||
|
@ -61,14 +61,14 @@ class BugdownRenderingException(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def unescape(s):
|
def unescape(s):
|
||||||
# type: (text_type) -> (text_type)
|
# type: (Text) -> (Text)
|
||||||
if six.PY2:
|
if six.PY2:
|
||||||
return html_parser.HTMLParser().unescape(s)
|
return html_parser.HTMLParser().unescape(s)
|
||||||
else:
|
else:
|
||||||
return html.unescape(s)
|
return html.unescape(s)
|
||||||
|
|
||||||
def list_of_tlds():
|
def list_of_tlds():
|
||||||
# type: () -> List[text_type]
|
# type: () -> List[Text]
|
||||||
# HACK we manually blacklist .py
|
# HACK we manually blacklist .py
|
||||||
blacklist = [u'PY\n', ]
|
blacklist = [u'PY\n', ]
|
||||||
|
|
||||||
|
@ -101,7 +101,7 @@ def walk_tree(root, processor, stop_after_first=False):
|
||||||
# height is not actually used
|
# height is not actually used
|
||||||
def add_a(root, url, link, height="", title=None, desc=None,
|
def add_a(root, url, link, height="", title=None, desc=None,
|
||||||
class_attr="message_inline_image", data_id=None):
|
class_attr="message_inline_image", data_id=None):
|
||||||
# type: (Element, text_type, text_type, text_type, Optional[text_type], Optional[text_type], text_type, Optional[text_type]) -> None
|
# type: (Element, Text, Text, Text, Optional[Text], Optional[Text], Text, Optional[Text]) -> None
|
||||||
title = title if title is not None else url_filename(link)
|
title = title if title is not None else url_filename(link)
|
||||||
title = title if title else ""
|
title = title if title else ""
|
||||||
desc = desc if desc is not None else ""
|
desc = desc if desc is not None else ""
|
||||||
|
@ -126,7 +126,7 @@ def add_a(root, url, link, height="", title=None, desc=None,
|
||||||
|
|
||||||
@cache_with_key(lambda tweet_id: tweet_id, cache_name="database", with_statsd_key="tweet_data")
|
@cache_with_key(lambda tweet_id: tweet_id, cache_name="database", with_statsd_key="tweet_data")
|
||||||
def fetch_tweet_data(tweet_id):
|
def fetch_tweet_data(tweet_id):
|
||||||
# type: (text_type) -> Optional[Dict[text_type, Any]]
|
# type: (Text) -> Optional[Dict[Text, Any]]
|
||||||
if settings.TEST_SUITE:
|
if settings.TEST_SUITE:
|
||||||
from . import testing_mocks
|
from . import testing_mocks
|
||||||
res = testing_mocks.twitter(tweet_id)
|
res = testing_mocks.twitter(tweet_id)
|
||||||
|
@ -186,7 +186,7 @@ META_START_RE = re.compile(u'^meta[ >]')
|
||||||
META_END_RE = re.compile(u'^/meta[ >]')
|
META_END_RE = re.compile(u'^/meta[ >]')
|
||||||
|
|
||||||
def fetch_open_graph_image(url):
|
def fetch_open_graph_image(url):
|
||||||
# type: (text_type) -> Optional[Dict[str, Any]]
|
# type: (Text) -> Optional[Dict[str, Any]]
|
||||||
in_head = False
|
in_head = False
|
||||||
# HTML will auto close meta tags, when we start the next tag add a closing tag if it has not been closed yet.
|
# HTML will auto close meta tags, when we start the next tag add a closing tag if it has not been closed yet.
|
||||||
last_closed = True
|
last_closed = True
|
||||||
|
@ -252,7 +252,7 @@ def fetch_open_graph_image(url):
|
||||||
return {'image': image, 'title': title, 'desc': desc}
|
return {'image': image, 'title': title, 'desc': desc}
|
||||||
|
|
||||||
def get_tweet_id(url):
|
def get_tweet_id(url):
|
||||||
# type: (text_type) -> Optional[text_type]
|
# type: (Text) -> Optional[Text]
|
||||||
parsed_url = urllib.parse.urlparse(url)
|
parsed_url = urllib.parse.urlparse(url)
|
||||||
if not (parsed_url.netloc == 'twitter.com' or parsed_url.netloc.endswith('.twitter.com')):
|
if not (parsed_url.netloc == 'twitter.com' or parsed_url.netloc.endswith('.twitter.com')):
|
||||||
return None
|
return None
|
||||||
|
@ -289,7 +289,7 @@ class InlineInterestingLinkProcessor(markdown.treeprocessors.Treeprocessor):
|
||||||
markdown.treeprocessors.Treeprocessor.__init__(self, md)
|
markdown.treeprocessors.Treeprocessor.__init__(self, md)
|
||||||
|
|
||||||
def is_image(self, url):
|
def is_image(self, url):
|
||||||
# type: (text_type) -> bool
|
# type: (Text) -> bool
|
||||||
if not settings.INLINE_IMAGE_PREVIEW:
|
if not settings.INLINE_IMAGE_PREVIEW:
|
||||||
return False
|
return False
|
||||||
parsed_url = urllib.parse.urlparse(url)
|
parsed_url = urllib.parse.urlparse(url)
|
||||||
|
@ -300,7 +300,7 @@ class InlineInterestingLinkProcessor(markdown.treeprocessors.Treeprocessor):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def dropbox_image(self, url):
|
def dropbox_image(self, url):
|
||||||
# type: (text_type) -> Optional[Dict]
|
# type: (Text) -> Optional[Dict]
|
||||||
# TODO: specify details of returned Dict
|
# TODO: specify details of returned Dict
|
||||||
parsed_url = urllib.parse.urlparse(url)
|
parsed_url = urllib.parse.urlparse(url)
|
||||||
if (parsed_url.netloc == 'dropbox.com' or parsed_url.netloc.endswith('.dropbox.com')):
|
if (parsed_url.netloc == 'dropbox.com' or parsed_url.netloc.endswith('.dropbox.com')):
|
||||||
|
@ -346,7 +346,7 @@ class InlineInterestingLinkProcessor(markdown.treeprocessors.Treeprocessor):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def youtube_id(self, url):
|
def youtube_id(self, url):
|
||||||
# type: (text_type) -> Optional[text_type]
|
# type: (Text) -> Optional[Text]
|
||||||
if not settings.INLINE_IMAGE_PREVIEW:
|
if not settings.INLINE_IMAGE_PREVIEW:
|
||||||
return None
|
return None
|
||||||
# Youtube video id extraction regular expression from http://pastebin.com/KyKAFv1s
|
# Youtube video id extraction regular expression from http://pastebin.com/KyKAFv1s
|
||||||
|
@ -360,14 +360,14 @@ class InlineInterestingLinkProcessor(markdown.treeprocessors.Treeprocessor):
|
||||||
return match.group(2)
|
return match.group(2)
|
||||||
|
|
||||||
def youtube_image(self, url):
|
def youtube_image(self, url):
|
||||||
# type: (text_type) -> Optional[text_type]
|
# type: (Text) -> Optional[Text]
|
||||||
yt_id = self.youtube_id(url)
|
yt_id = self.youtube_id(url)
|
||||||
|
|
||||||
if yt_id is not None:
|
if yt_id is not None:
|
||||||
return "https://i.ytimg.com/vi/%s/default.jpg" % (yt_id,)
|
return "https://i.ytimg.com/vi/%s/default.jpg" % (yt_id,)
|
||||||
|
|
||||||
def twitter_text(self, text, urls, user_mentions, media):
|
def twitter_text(self, text, urls, user_mentions, media):
|
||||||
# type: (text_type, List[Dict[text_type, text_type]], List[Dict[text_type, Any]], List[Dict[text_type, Any]]) -> Element
|
# type: (Text, List[Dict[Text, Text]], List[Dict[Text, Any]], List[Dict[Text, Any]]) -> Element
|
||||||
"""
|
"""
|
||||||
Use data from the twitter API to turn links, mentions and media into A
|
Use data from the twitter API to turn links, mentions and media into A
|
||||||
tags.
|
tags.
|
||||||
|
@ -388,7 +388,7 @@ class InlineInterestingLinkProcessor(markdown.treeprocessors.Treeprocessor):
|
||||||
Finally we add any remaining text to the last node.
|
Finally we add any remaining text to the last node.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
to_linkify = [] # type: List[Dict[text_type, Any]]
|
to_linkify = [] # type: List[Dict[Text, Any]]
|
||||||
# Build dicts for URLs
|
# Build dicts for URLs
|
||||||
for url_data in urls:
|
for url_data in urls:
|
||||||
short_url = url_data["url"]
|
short_url = url_data["url"]
|
||||||
|
@ -427,7 +427,7 @@ class InlineInterestingLinkProcessor(markdown.treeprocessors.Treeprocessor):
|
||||||
p = current_node = markdown.util.etree.Element('p')
|
p = current_node = markdown.util.etree.Element('p')
|
||||||
|
|
||||||
def set_text(text):
|
def set_text(text):
|
||||||
# type: (text_type) -> None
|
# type: (Text) -> None
|
||||||
"""
|
"""
|
||||||
Helper to set the text or the tail of the current_node
|
Helper to set the text or the tail of the current_node
|
||||||
"""
|
"""
|
||||||
|
@ -453,7 +453,7 @@ class InlineInterestingLinkProcessor(markdown.treeprocessors.Treeprocessor):
|
||||||
return p
|
return p
|
||||||
|
|
||||||
def twitter_link(self, url):
|
def twitter_link(self, url):
|
||||||
# type: (text_type) -> Optional[Element]
|
# type: (Text) -> Optional[Element]
|
||||||
tweet_id = get_tweet_id(url)
|
tweet_id = get_tweet_id(url)
|
||||||
|
|
||||||
if tweet_id is None:
|
if tweet_id is None:
|
||||||
|
@ -463,7 +463,7 @@ class InlineInterestingLinkProcessor(markdown.treeprocessors.Treeprocessor):
|
||||||
res = fetch_tweet_data(tweet_id)
|
res = fetch_tweet_data(tweet_id)
|
||||||
if res is None:
|
if res is None:
|
||||||
return None
|
return None
|
||||||
user = res['user'] # type: Dict[text_type, Any]
|
user = res['user'] # type: Dict[Text, Any]
|
||||||
tweet = markdown.util.etree.Element("div")
|
tweet = markdown.util.etree.Element("div")
|
||||||
tweet.set("class", "twitter-tweet")
|
tweet.set("class", "twitter-tweet")
|
||||||
img_a = markdown.util.etree.SubElement(tweet, 'a')
|
img_a = markdown.util.etree.SubElement(tweet, 'a')
|
||||||
|
@ -482,7 +482,7 @@ class InlineInterestingLinkProcessor(markdown.treeprocessors.Treeprocessor):
|
||||||
text = unescape(res['text'])
|
text = unescape(res['text'])
|
||||||
urls = res.get('urls', [])
|
urls = res.get('urls', [])
|
||||||
user_mentions = res.get('user_mentions', [])
|
user_mentions = res.get('user_mentions', [])
|
||||||
media = res.get('media', []) # type: List[Dict[text_type, Any]]
|
media = res.get('media', []) # type: List[Dict[Text, Any]]
|
||||||
p = self.twitter_text(text, urls, user_mentions, media)
|
p = self.twitter_text(text, urls, user_mentions, media)
|
||||||
tweet.append(p)
|
tweet.append(p)
|
||||||
|
|
||||||
|
@ -523,7 +523,7 @@ class InlineInterestingLinkProcessor(markdown.treeprocessors.Treeprocessor):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_url_data(self, e):
|
def get_url_data(self, e):
|
||||||
# type: (Element) -> Optional[Tuple[text_type, text_type]]
|
# type: (Element) -> Optional[Tuple[Text, Text]]
|
||||||
if e.tag == "a":
|
if e.tag == "a":
|
||||||
if e.text is not None:
|
if e.text is not None:
|
||||||
return (e.get("href"), force_text(e.text))
|
return (e.get("href"), force_text(e.text))
|
||||||
|
@ -579,7 +579,7 @@ class InlineInterestingLinkProcessor(markdown.treeprocessors.Treeprocessor):
|
||||||
|
|
||||||
class Avatar(markdown.inlinepatterns.Pattern):
|
class Avatar(markdown.inlinepatterns.Pattern):
|
||||||
def handleMatch(self, match):
|
def handleMatch(self, match):
|
||||||
# type: (Match[text_type]) -> Optional[Element]
|
# type: (Match[Text]) -> Optional[Element]
|
||||||
img = markdown.util.etree.Element('img')
|
img = markdown.util.etree.Element('img')
|
||||||
email_address = match.group('email')
|
email_address = match.group('email')
|
||||||
img.set('class', 'message_body_gravatar')
|
img.set('class', 'message_body_gravatar')
|
||||||
|
@ -597,7 +597,7 @@ unicode_emoji_list = [os.path.splitext(os.path.basename(fn))[0] for fn in glob.g
|
||||||
|
|
||||||
|
|
||||||
def make_emoji(emoji_name, src, display_string):
|
def make_emoji(emoji_name, src, display_string):
|
||||||
# type: (text_type, text_type, text_type) -> Element
|
# type: (Text, Text, Text) -> Element
|
||||||
elt = markdown.util.etree.Element('img')
|
elt = markdown.util.etree.Element('img')
|
||||||
elt.set('src', src)
|
elt.set('src', src)
|
||||||
elt.set('class', 'emoji')
|
elt.set('class', 'emoji')
|
||||||
|
@ -607,7 +607,7 @@ def make_emoji(emoji_name, src, display_string):
|
||||||
|
|
||||||
class UnicodeEmoji(markdown.inlinepatterns.Pattern):
|
class UnicodeEmoji(markdown.inlinepatterns.Pattern):
|
||||||
def handleMatch(self, match):
|
def handleMatch(self, match):
|
||||||
# type: (Match[text_type]) -> Optional[Element]
|
# type: (Match[Text]) -> Optional[Element]
|
||||||
orig_syntax = match.group('syntax')
|
orig_syntax = match.group('syntax')
|
||||||
name = hex(ord(orig_syntax))[2:]
|
name = hex(ord(orig_syntax))[2:]
|
||||||
if name in unicode_emoji_list:
|
if name in unicode_emoji_list:
|
||||||
|
@ -618,11 +618,11 @@ class UnicodeEmoji(markdown.inlinepatterns.Pattern):
|
||||||
|
|
||||||
class Emoji(markdown.inlinepatterns.Pattern):
|
class Emoji(markdown.inlinepatterns.Pattern):
|
||||||
def handleMatch(self, match):
|
def handleMatch(self, match):
|
||||||
# type: (Match[text_type]) -> Optional[Element]
|
# type: (Match[Text]) -> Optional[Element]
|
||||||
orig_syntax = match.group("syntax")
|
orig_syntax = match.group("syntax")
|
||||||
name = orig_syntax[1:-1]
|
name = orig_syntax[1:-1]
|
||||||
|
|
||||||
realm_emoji = {} # type: Dict[text_type, Dict[str, text_type]]
|
realm_emoji = {} # type: Dict[Text, Dict[str, Text]]
|
||||||
if db_data is not None:
|
if db_data is not None:
|
||||||
realm_emoji = db_data['emoji']
|
realm_emoji = db_data['emoji']
|
||||||
|
|
||||||
|
@ -638,7 +638,7 @@ class StreamSubscribeButton(markdown.inlinepatterns.Pattern):
|
||||||
# This markdown extension has required javascript in
|
# This markdown extension has required javascript in
|
||||||
# static/js/custom_markdown.js
|
# static/js/custom_markdown.js
|
||||||
def handleMatch(self, match):
|
def handleMatch(self, match):
|
||||||
# type: (Match[text_type]) -> Element
|
# type: (Match[Text]) -> Element
|
||||||
stream_name = match.group('stream_name')
|
stream_name = match.group('stream_name')
|
||||||
stream_name = stream_name.replace('\\)', ')').replace('\\\\', '\\')
|
stream_name = stream_name.replace('\\)', ')').replace('\\\\', '\\')
|
||||||
|
|
||||||
|
@ -661,7 +661,7 @@ class ModalLink(markdown.inlinepatterns.Pattern):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def handleMatch(self, match):
|
def handleMatch(self, match):
|
||||||
# type: (Match[text_type]) -> Element
|
# type: (Match[Text]) -> Element
|
||||||
relative_url = match.group('relative_url')
|
relative_url = match.group('relative_url')
|
||||||
text = match.group('text')
|
text = match.group('text')
|
||||||
|
|
||||||
|
@ -675,7 +675,7 @@ class ModalLink(markdown.inlinepatterns.Pattern):
|
||||||
|
|
||||||
upload_title_re = re.compile(u"^(https?://[^/]*)?(/user_uploads/\\d+)(/[^/]*)?/[^/]*/(?P<filename>[^/]*)$")
|
upload_title_re = re.compile(u"^(https?://[^/]*)?(/user_uploads/\\d+)(/[^/]*)?/[^/]*/(?P<filename>[^/]*)$")
|
||||||
def url_filename(url):
|
def url_filename(url):
|
||||||
# type: (text_type) -> text_type
|
# type: (Text) -> Text
|
||||||
"""Extract the filename if a URL is an uploaded file, or return the original URL"""
|
"""Extract the filename if a URL is an uploaded file, or return the original URL"""
|
||||||
match = upload_title_re.match(url)
|
match = upload_title_re.match(url)
|
||||||
if match:
|
if match:
|
||||||
|
@ -692,7 +692,7 @@ def fixup_link(link, target_blank=True):
|
||||||
|
|
||||||
|
|
||||||
def sanitize_url(url):
|
def sanitize_url(url):
|
||||||
# type: (text_type) -> text_type
|
# type: (Text) -> Text
|
||||||
"""
|
"""
|
||||||
Sanitize a url against xss attacks.
|
Sanitize a url against xss attacks.
|
||||||
See the docstring on markdown.inlinepatterns.LinkPattern.sanitize_url.
|
See the docstring on markdown.inlinepatterns.LinkPattern.sanitize_url.
|
||||||
|
@ -747,7 +747,7 @@ def sanitize_url(url):
|
||||||
return urllib.parse.urlunparse((scheme, netloc, path, params, query, fragment))
|
return urllib.parse.urlunparse((scheme, netloc, path, params, query, fragment))
|
||||||
|
|
||||||
def url_to_a(url, text = None):
|
def url_to_a(url, text = None):
|
||||||
# type: (text_type, Optional[text_type]) -> Union[Element, text_type]
|
# type: (Text, Optional[Text]) -> Union[Element, Text]
|
||||||
a = markdown.util.etree.Element('a')
|
a = markdown.util.etree.Element('a')
|
||||||
|
|
||||||
href = sanitize_url(url)
|
href = sanitize_url(url)
|
||||||
|
@ -764,7 +764,7 @@ def url_to_a(url, text = None):
|
||||||
|
|
||||||
class VerbosePattern(markdown.inlinepatterns.Pattern):
|
class VerbosePattern(markdown.inlinepatterns.Pattern):
|
||||||
def __init__(self, pattern):
|
def __init__(self, pattern):
|
||||||
# type: (text_type) -> None
|
# type: (Text) -> None
|
||||||
markdown.inlinepatterns.Pattern.__init__(self, ' ')
|
markdown.inlinepatterns.Pattern.__init__(self, ' ')
|
||||||
|
|
||||||
# HACK: we just had python-markdown compile an empty regex.
|
# HACK: we just had python-markdown compile an empty regex.
|
||||||
|
@ -776,7 +776,7 @@ class VerbosePattern(markdown.inlinepatterns.Pattern):
|
||||||
|
|
||||||
class AutoLink(VerbosePattern):
|
class AutoLink(VerbosePattern):
|
||||||
def handleMatch(self, match):
|
def handleMatch(self, match):
|
||||||
# type: (Match[text_type]) -> ElementStringNone
|
# type: (Match[Text]) -> ElementStringNone
|
||||||
url = match.group('url')
|
url = match.group('url')
|
||||||
return url_to_a(url)
|
return url_to_a(url)
|
||||||
|
|
||||||
|
@ -801,7 +801,7 @@ class BugdownUListPreprocessor(markdown.preprocessors.Preprocessor):
|
||||||
HANGING_ULIST_RE = re.compile(u'^.+\\n([ ]{0,3}[*][ ]+.*)', re.MULTILINE)
|
HANGING_ULIST_RE = re.compile(u'^.+\\n([ ]{0,3}[*][ ]+.*)', re.MULTILINE)
|
||||||
|
|
||||||
def run(self, lines):
|
def run(self, lines):
|
||||||
# type: (List[text_type]) -> List[text_type]
|
# type: (List[Text]) -> List[Text]
|
||||||
""" Insert a newline between a paragraph and ulist if missing """
|
""" Insert a newline between a paragraph and ulist if missing """
|
||||||
inserts = 0
|
inserts = 0
|
||||||
fence = None
|
fence = None
|
||||||
|
@ -829,7 +829,7 @@ class LinkPattern(markdown.inlinepatterns.Pattern):
|
||||||
""" Return a link element from the given match. """
|
""" Return a link element from the given match. """
|
||||||
|
|
||||||
def handleMatch(self, m):
|
def handleMatch(self, m):
|
||||||
# type: (Match[text_type]) -> Optional[Element]
|
# type: (Match[Text]) -> Optional[Element]
|
||||||
href = m.group(9)
|
href = m.group(9)
|
||||||
if not href:
|
if not href:
|
||||||
return None
|
return None
|
||||||
|
@ -847,7 +847,7 @@ class LinkPattern(markdown.inlinepatterns.Pattern):
|
||||||
return el
|
return el
|
||||||
|
|
||||||
def prepare_realm_pattern(source):
|
def prepare_realm_pattern(source):
|
||||||
# type: (text_type) -> text_type
|
# type: (Text) -> Text
|
||||||
""" Augment a realm filter so it only matches after start-of-string,
|
""" Augment a realm filter so it only matches after start-of-string,
|
||||||
whitespace, or opening delimiters, won't match if there are word
|
whitespace, or opening delimiters, won't match if there are word
|
||||||
characters directly after, and saves what was matched as "name". """
|
characters directly after, and saves what was matched as "name". """
|
||||||
|
@ -859,19 +859,19 @@ class RealmFilterPattern(markdown.inlinepatterns.Pattern):
|
||||||
""" Applied a given realm filter to the input """
|
""" Applied a given realm filter to the input """
|
||||||
|
|
||||||
def __init__(self, source_pattern, format_string, markdown_instance=None):
|
def __init__(self, source_pattern, format_string, markdown_instance=None):
|
||||||
# type: (text_type, text_type, Optional[markdown.Markdown]) -> None
|
# type: (Text, Text, Optional[markdown.Markdown]) -> None
|
||||||
self.pattern = prepare_realm_pattern(source_pattern)
|
self.pattern = prepare_realm_pattern(source_pattern)
|
||||||
self.format_string = format_string
|
self.format_string = format_string
|
||||||
markdown.inlinepatterns.Pattern.__init__(self, self.pattern, markdown_instance)
|
markdown.inlinepatterns.Pattern.__init__(self, self.pattern, markdown_instance)
|
||||||
|
|
||||||
def handleMatch(self, m):
|
def handleMatch(self, m):
|
||||||
# type: (Match[text_type]) -> Union[Element, text_type]
|
# type: (Match[Text]) -> Union[Element, Text]
|
||||||
return url_to_a(self.format_string % m.groupdict(),
|
return url_to_a(self.format_string % m.groupdict(),
|
||||||
m.group("name"))
|
m.group("name"))
|
||||||
|
|
||||||
class UserMentionPattern(markdown.inlinepatterns.Pattern):
|
class UserMentionPattern(markdown.inlinepatterns.Pattern):
|
||||||
def find_user_for_mention(self, name):
|
def find_user_for_mention(self, name):
|
||||||
# type: (text_type) -> Tuple[bool, Dict[str, Any]]
|
# type: (Text) -> Tuple[bool, Dict[str, Any]]
|
||||||
if db_data is None:
|
if db_data is None:
|
||||||
return (False, None)
|
return (False, None)
|
||||||
|
|
||||||
|
@ -885,7 +885,7 @@ class UserMentionPattern(markdown.inlinepatterns.Pattern):
|
||||||
return (False, user)
|
return (False, user)
|
||||||
|
|
||||||
def handleMatch(self, m):
|
def handleMatch(self, m):
|
||||||
# type: (Match[text_type]) -> Optional[Element]
|
# type: (Match[Text]) -> Optional[Element]
|
||||||
name = m.group(2) or m.group(3)
|
name = m.group(2) or m.group(3)
|
||||||
|
|
||||||
if current_message:
|
if current_message:
|
||||||
|
@ -911,14 +911,14 @@ class UserMentionPattern(markdown.inlinepatterns.Pattern):
|
||||||
|
|
||||||
class StreamPattern(VerbosePattern):
|
class StreamPattern(VerbosePattern):
|
||||||
def find_stream_by_name(self, name):
|
def find_stream_by_name(self, name):
|
||||||
# type: (Match[text_type]) -> Dict[str, Any]
|
# type: (Match[Text]) -> Dict[str, Any]
|
||||||
if db_data is None:
|
if db_data is None:
|
||||||
return None
|
return None
|
||||||
stream = db_data['stream_names'].get(name)
|
stream = db_data['stream_names'].get(name)
|
||||||
return stream
|
return stream
|
||||||
|
|
||||||
def handleMatch(self, m):
|
def handleMatch(self, m):
|
||||||
# type: (Match[text_type]) -> Optional[Element]
|
# type: (Match[Text]) -> Optional[Element]
|
||||||
name = m.group('stream_name')
|
name = m.group('stream_name')
|
||||||
|
|
||||||
if current_message:
|
if current_message:
|
||||||
|
@ -940,7 +940,7 @@ class StreamPattern(VerbosePattern):
|
||||||
|
|
||||||
class AlertWordsNotificationProcessor(markdown.preprocessors.Preprocessor):
|
class AlertWordsNotificationProcessor(markdown.preprocessors.Preprocessor):
|
||||||
def run(self, lines):
|
def run(self, lines):
|
||||||
# type: (Iterable[text_type]) -> Iterable[text_type]
|
# type: (Iterable[Text]) -> Iterable[Text]
|
||||||
if current_message and db_data is not None:
|
if current_message and db_data is not None:
|
||||||
# We check for custom alert words here, the set of which are
|
# We check for custom alert words here, the set of which are
|
||||||
# dependent on which users may see this message.
|
# dependent on which users may see this message.
|
||||||
|
@ -972,7 +972,7 @@ class AlertWordsNotificationProcessor(markdown.preprocessors.Preprocessor):
|
||||||
# might be worth sending a version of this change upstream.
|
# might be worth sending a version of this change upstream.
|
||||||
class AtomicLinkPattern(LinkPattern):
|
class AtomicLinkPattern(LinkPattern):
|
||||||
def handleMatch(self, m):
|
def handleMatch(self, m):
|
||||||
# type: (Match[text_type]) -> Optional[Element]
|
# type: (Match[Text]) -> Optional[Element]
|
||||||
ret = LinkPattern.handleMatch(self, m)
|
ret = LinkPattern.handleMatch(self, m)
|
||||||
if ret is None:
|
if ret is None:
|
||||||
return None
|
return None
|
||||||
|
@ -982,7 +982,7 @@ class AtomicLinkPattern(LinkPattern):
|
||||||
|
|
||||||
class Bugdown(markdown.Extension):
|
class Bugdown(markdown.Extension):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
# type: (*Any, **Union[bool, None, text_type]) -> None
|
# type: (*Any, **Union[bool, None, Text]) -> None
|
||||||
# define default configs
|
# define default configs
|
||||||
self.config = {
|
self.config = {
|
||||||
"realm_filters": [kwargs['realm_filters'], "Realm-specific filters for domain"],
|
"realm_filters": [kwargs['realm_filters'], "Realm-specific filters for domain"],
|
||||||
|
@ -1140,7 +1140,7 @@ class Bugdown(markdown.Extension):
|
||||||
del md.parser.blockprocessors[k]
|
del md.parser.blockprocessors[k]
|
||||||
|
|
||||||
md_engines = {}
|
md_engines = {}
|
||||||
realm_filter_data = {} # type: Dict[text_type, List[Tuple[text_type, text_type, int]]]
|
realm_filter_data = {} # type: Dict[Text, List[Tuple[Text, Text, int]]]
|
||||||
|
|
||||||
class EscapeHtml(markdown.Extension):
|
class EscapeHtml(markdown.Extension):
|
||||||
def extendMarkdown(self, md, md_globals):
|
def extendMarkdown(self, md, md_globals):
|
||||||
|
@ -1149,7 +1149,7 @@ class EscapeHtml(markdown.Extension):
|
||||||
del md.inlinePatterns['html']
|
del md.inlinePatterns['html']
|
||||||
|
|
||||||
def make_md_engine(key, opts):
|
def make_md_engine(key, opts):
|
||||||
# type: (text_type, Dict[str, Any]) -> None
|
# type: (Text, Dict[str, Any]) -> None
|
||||||
md_engines[key] = markdown.Markdown(
|
md_engines[key] = markdown.Markdown(
|
||||||
output_format = 'html',
|
output_format = 'html',
|
||||||
extensions = [
|
extensions = [
|
||||||
|
@ -1165,9 +1165,9 @@ def make_md_engine(key, opts):
|
||||||
realm=opts["realm"][0])])
|
realm=opts["realm"][0])])
|
||||||
|
|
||||||
def subject_links(domain, subject):
|
def subject_links(domain, subject):
|
||||||
# type: (text_type, text_type) -> List[text_type]
|
# type: (Text, Text) -> List[Text]
|
||||||
from zerver.models import get_realm, RealmFilter, realm_filters_for_domain
|
from zerver.models import get_realm, RealmFilter, realm_filters_for_domain
|
||||||
matches = [] # type: List[text_type]
|
matches = [] # type: List[Text]
|
||||||
|
|
||||||
realm_filters = realm_filters_for_domain(domain)
|
realm_filters = realm_filters_for_domain(domain)
|
||||||
|
|
||||||
|
@ -1178,7 +1178,7 @@ def subject_links(domain, subject):
|
||||||
return matches
|
return matches
|
||||||
|
|
||||||
def make_realm_filters(domain, filters):
|
def make_realm_filters(domain, filters):
|
||||||
# type: (text_type, List[Tuple[text_type, text_type, int]]) -> None
|
# type: (Text, List[Tuple[Text, Text, int]]) -> None
|
||||||
global md_engines, realm_filter_data
|
global md_engines, realm_filter_data
|
||||||
if domain in md_engines:
|
if domain in md_engines:
|
||||||
del md_engines[domain]
|
del md_engines[domain]
|
||||||
|
@ -1190,7 +1190,7 @@ def make_realm_filters(domain, filters):
|
||||||
"realm": [domain, "Realm name"]})
|
"realm": [domain, "Realm name"]})
|
||||||
|
|
||||||
def maybe_update_realm_filters(domain):
|
def maybe_update_realm_filters(domain):
|
||||||
# type: (Optional[text_type]) -> None
|
# type: (Optional[Text]) -> None
|
||||||
from zerver.models import realm_filters_for_domain, all_realm_filters
|
from zerver.models import realm_filters_for_domain, all_realm_filters
|
||||||
|
|
||||||
# If domain is None, load all filters
|
# If domain is None, load all filters
|
||||||
|
@ -1215,7 +1215,7 @@ def maybe_update_realm_filters(domain):
|
||||||
# codes, which can do surprisingly nasty things.
|
# codes, which can do surprisingly nasty things.
|
||||||
_privacy_re = re.compile(u'\\w', flags=re.UNICODE)
|
_privacy_re = re.compile(u'\\w', flags=re.UNICODE)
|
||||||
def _sanitize_for_log(content):
|
def _sanitize_for_log(content):
|
||||||
# type: (text_type) -> text_type
|
# type: (Text) -> Text
|
||||||
return repr(_privacy_re.sub('x', content))
|
return repr(_privacy_re.sub('x', content))
|
||||||
|
|
||||||
|
|
||||||
|
@ -1226,7 +1226,7 @@ current_message = None # type: Optional[Message]
|
||||||
# We avoid doing DB queries in our markdown thread to avoid the overhead of
|
# We avoid doing DB queries in our markdown thread to avoid the overhead of
|
||||||
# opening a new DB connection. These connections tend to live longer than the
|
# opening a new DB connection. These connections tend to live longer than the
|
||||||
# threads themselves, as well.
|
# threads themselves, as well.
|
||||||
db_data = None # type: Dict[text_type, Any]
|
db_data = None # type: Dict[Text, Any]
|
||||||
|
|
||||||
def log_bugdown_error(msg):
|
def log_bugdown_error(msg):
|
||||||
# type: (str) -> None
|
# type: (str) -> None
|
||||||
|
@ -1237,7 +1237,7 @@ def log_bugdown_error(msg):
|
||||||
logging.getLogger('').error(msg)
|
logging.getLogger('').error(msg)
|
||||||
|
|
||||||
def do_convert(content, realm_domain=None, message=None, possible_words=None):
|
def do_convert(content, realm_domain=None, message=None, possible_words=None):
|
||||||
# type: (text_type, Optional[text_type], Optional[Message], Optional[Set[text_type]]) -> Optional[text_type]
|
# type: (Text, Optional[Text], Optional[Message], Optional[Set[Text]]) -> Optional[Text]
|
||||||
"""Convert Markdown to HTML, with Zulip-specific settings and hacks."""
|
"""Convert Markdown to HTML, with Zulip-specific settings and hacks."""
|
||||||
from zerver.models import get_active_user_dicts_in_realm, get_active_streams, UserProfile
|
from zerver.models import get_active_user_dicts_in_realm, get_active_streams, UserProfile
|
||||||
|
|
||||||
|
@ -1264,7 +1264,7 @@ def do_convert(content, realm_domain=None, message=None, possible_words=None):
|
||||||
realm_streams = get_active_streams(message.get_realm()).values('id', 'name')
|
realm_streams = get_active_streams(message.get_realm()).values('id', 'name')
|
||||||
|
|
||||||
if possible_words is None:
|
if possible_words is None:
|
||||||
possible_words = set() # Set[text_type]
|
possible_words = set() # Set[Text]
|
||||||
|
|
||||||
db_data = {'possible_words': possible_words,
|
db_data = {'possible_words': possible_words,
|
||||||
'full_names': dict((user['full_name'].lower(), user) for user in realm_users),
|
'full_names': dict((user['full_name'].lower(), user) for user in realm_users),
|
||||||
|
@ -1323,7 +1323,7 @@ def bugdown_stats_finish():
|
||||||
bugdown_total_time += (time.time() - bugdown_time_start)
|
bugdown_total_time += (time.time() - bugdown_time_start)
|
||||||
|
|
||||||
def convert(content, realm_domain=None, message=None, possible_words=None):
|
def convert(content, realm_domain=None, message=None, possible_words=None):
|
||||||
# type: (text_type, Optional[text_type], Optional[Message], Optional[Set[text_type]]) -> Optional[text_type]
|
# type: (Text, Optional[Text], Optional[Message], Optional[Set[Text]]) -> Optional[Text]
|
||||||
bugdown_stats_start()
|
bugdown_stats_start()
|
||||||
ret = do_convert(content, realm_domain, message, possible_words)
|
ret = do_convert(content, realm_domain, message, possible_words)
|
||||||
bugdown_stats_finish()
|
bugdown_stats_finish()
|
||||||
|
|
|
@ -64,8 +64,7 @@ Dependencies:
|
||||||
import re
|
import re
|
||||||
import markdown
|
import markdown
|
||||||
from markdown.extensions.codehilite import CodeHilite, CodeHiliteExtension
|
from markdown.extensions.codehilite import CodeHilite, CodeHiliteExtension
|
||||||
from six import text_type
|
from typing import Any, Dict, Iterable, List, MutableSequence, Optional, Tuple, Union, Text
|
||||||
from typing import Any, Dict, Iterable, List, MutableSequence, Optional, Tuple, Union
|
|
||||||
|
|
||||||
# Global vars
|
# Global vars
|
||||||
FENCE_RE = re.compile(u"""
|
FENCE_RE = re.compile(u"""
|
||||||
|
@ -118,14 +117,14 @@ class FencedBlockPreprocessor(markdown.preprocessors.Preprocessor):
|
||||||
self.codehilite_conf = {} # type: Dict[str, List[Any]]
|
self.codehilite_conf = {} # type: Dict[str, List[Any]]
|
||||||
|
|
||||||
def run(self, lines):
|
def run(self, lines):
|
||||||
# type: (Iterable[text_type]) -> List[text_type]
|
# type: (Iterable[Text]) -> List[Text]
|
||||||
""" Match and store Fenced Code Blocks in the HtmlStash. """
|
""" Match and store Fenced Code Blocks in the HtmlStash. """
|
||||||
|
|
||||||
output = [] # type: List[text_type]
|
output = [] # type: List[Text]
|
||||||
|
|
||||||
class BaseHandler(object):
|
class BaseHandler(object):
|
||||||
def handle_line(self, line):
|
def handle_line(self, line):
|
||||||
# type: (text_type) -> None
|
# type: (Text) -> None
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def done(self):
|
def done(self):
|
||||||
|
@ -144,7 +143,7 @@ class FencedBlockPreprocessor(markdown.preprocessors.Preprocessor):
|
||||||
handlers.pop()
|
handlers.pop()
|
||||||
|
|
||||||
def check_for_new_fence(output, line):
|
def check_for_new_fence(output, line):
|
||||||
# type: (MutableSequence[text_type], text_type) -> None
|
# type: (MutableSequence[Text], Text) -> None
|
||||||
m = FENCE_RE.match(line)
|
m = FENCE_RE.match(line)
|
||||||
if m:
|
if m:
|
||||||
fence = m.group('fence')
|
fence = m.group('fence')
|
||||||
|
@ -156,11 +155,11 @@ class FencedBlockPreprocessor(markdown.preprocessors.Preprocessor):
|
||||||
|
|
||||||
class OuterHandler(BaseHandler):
|
class OuterHandler(BaseHandler):
|
||||||
def __init__(self, output):
|
def __init__(self, output):
|
||||||
# type: (MutableSequence[text_type]) -> None
|
# type: (MutableSequence[Text]) -> None
|
||||||
self.output = output
|
self.output = output
|
||||||
|
|
||||||
def handle_line(self, line):
|
def handle_line(self, line):
|
||||||
# type: (text_type) -> None
|
# type: (Text) -> None
|
||||||
check_for_new_fence(self.output, line)
|
check_for_new_fence(self.output, line)
|
||||||
|
|
||||||
def done(self):
|
def done(self):
|
||||||
|
@ -168,7 +167,7 @@ class FencedBlockPreprocessor(markdown.preprocessors.Preprocessor):
|
||||||
pop()
|
pop()
|
||||||
|
|
||||||
def generic_handler(output, fence, lang):
|
def generic_handler(output, fence, lang):
|
||||||
# type: (MutableSequence[text_type], text_type, text_type) -> BaseHandler
|
# type: (MutableSequence[Text], Text, Text) -> BaseHandler
|
||||||
if lang in ('quote', 'quoted'):
|
if lang in ('quote', 'quoted'):
|
||||||
return QuoteHandler(output, fence)
|
return QuoteHandler(output, fence)
|
||||||
else:
|
else:
|
||||||
|
@ -176,13 +175,13 @@ class FencedBlockPreprocessor(markdown.preprocessors.Preprocessor):
|
||||||
|
|
||||||
class QuoteHandler(BaseHandler):
|
class QuoteHandler(BaseHandler):
|
||||||
def __init__(self, output, fence):
|
def __init__(self, output, fence):
|
||||||
# type: (MutableSequence[text_type], text_type) -> None
|
# type: (MutableSequence[Text], Text) -> None
|
||||||
self.output = output
|
self.output = output
|
||||||
self.fence = fence
|
self.fence = fence
|
||||||
self.lines = [] # type: List[text_type]
|
self.lines = [] # type: List[Text]
|
||||||
|
|
||||||
def handle_line(self, line):
|
def handle_line(self, line):
|
||||||
# type: (text_type) -> None
|
# type: (Text) -> None
|
||||||
if line.rstrip() == self.fence:
|
if line.rstrip() == self.fence:
|
||||||
self.done()
|
self.done()
|
||||||
else:
|
else:
|
||||||
|
@ -200,14 +199,14 @@ class FencedBlockPreprocessor(markdown.preprocessors.Preprocessor):
|
||||||
|
|
||||||
class CodeHandler(BaseHandler):
|
class CodeHandler(BaseHandler):
|
||||||
def __init__(self, output, fence, lang):
|
def __init__(self, output, fence, lang):
|
||||||
# type: (MutableSequence[text_type], text_type, text_type) -> None
|
# type: (MutableSequence[Text], Text, Text) -> None
|
||||||
self.output = output
|
self.output = output
|
||||||
self.fence = fence
|
self.fence = fence
|
||||||
self.lang = lang
|
self.lang = lang
|
||||||
self.lines = [] # type: List[text_type]
|
self.lines = [] # type: List[Text]
|
||||||
|
|
||||||
def handle_line(self, line):
|
def handle_line(self, line):
|
||||||
# type: (text_type) -> None
|
# type: (Text) -> None
|
||||||
if line.rstrip() == self.fence:
|
if line.rstrip() == self.fence:
|
||||||
self.done()
|
self.done()
|
||||||
else:
|
else:
|
||||||
|
@ -241,7 +240,7 @@ class FencedBlockPreprocessor(markdown.preprocessors.Preprocessor):
|
||||||
return output
|
return output
|
||||||
|
|
||||||
def format_code(self, lang, text):
|
def format_code(self, lang, text):
|
||||||
# type: (text_type, text_type) -> text_type
|
# type: (Text, Text) -> Text
|
||||||
if lang:
|
if lang:
|
||||||
langclass = LANG_TAG % (lang,)
|
langclass = LANG_TAG % (lang,)
|
||||||
else:
|
else:
|
||||||
|
@ -275,7 +274,7 @@ class FencedBlockPreprocessor(markdown.preprocessors.Preprocessor):
|
||||||
return code
|
return code
|
||||||
|
|
||||||
def format_quote(self, text):
|
def format_quote(self, text):
|
||||||
# type: (text_type) -> text_type
|
# type: (Text) -> Text
|
||||||
paragraphs = text.split("\n\n")
|
paragraphs = text.split("\n\n")
|
||||||
quoted_paragraphs = []
|
quoted_paragraphs = []
|
||||||
for paragraph in paragraphs:
|
for paragraph in paragraphs:
|
||||||
|
@ -284,11 +283,11 @@ class FencedBlockPreprocessor(markdown.preprocessors.Preprocessor):
|
||||||
return "\n\n".join(quoted_paragraphs)
|
return "\n\n".join(quoted_paragraphs)
|
||||||
|
|
||||||
def placeholder(self, code):
|
def placeholder(self, code):
|
||||||
# type: (text_type) -> text_type
|
# type: (Text) -> Text
|
||||||
return self.markdown.htmlStash.store(code, safe=True)
|
return self.markdown.htmlStash.store(code, safe=True)
|
||||||
|
|
||||||
def _escape(self, txt):
|
def _escape(self, txt):
|
||||||
# type: (text_type) -> text_type
|
# type: (Text) -> Text
|
||||||
""" basic html escaping """
|
""" basic html escaping """
|
||||||
txt = txt.replace('&', '&')
|
txt = txt.replace('&', '&')
|
||||||
txt = txt.replace('<', '<')
|
txt = txt.replace('<', '<')
|
||||||
|
@ -298,7 +297,7 @@ class FencedBlockPreprocessor(markdown.preprocessors.Preprocessor):
|
||||||
|
|
||||||
|
|
||||||
def makeExtension(*args, **kwargs):
|
def makeExtension(*args, **kwargs):
|
||||||
# type: (*Any, **Union[bool, None, text_type]) -> FencedCodeExtension
|
# type: (*Any, **Union[bool, None, Text]) -> FencedCodeExtension
|
||||||
return FencedCodeExtension(*args, **kwargs)
|
return FencedCodeExtension(*args, **kwargs)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from six import text_type
|
from typing import Any, Dict, Optional, Text
|
||||||
from typing import Any, Dict, Optional
|
|
||||||
import ujson
|
import ujson
|
||||||
|
|
||||||
|
|
||||||
|
@ -183,7 +182,7 @@ MEDIA_TWEET = """{
|
||||||
|
|
||||||
|
|
||||||
def twitter(tweet_id):
|
def twitter(tweet_id):
|
||||||
# type: (text_type) -> Optional[Dict[text_type, Any]]
|
# type: (Text) -> Optional[Dict[Text, Any]]
|
||||||
if tweet_id in ["112652479837110273", "287977969287315456", "287977969287315457"]:
|
if tweet_id in ["112652479837110273", "287977969287315456", "287977969287315457"]:
|
||||||
return ujson.loads(NORMAL_TWEET)
|
return ujson.loads(NORMAL_TWEET)
|
||||||
elif tweet_id == "287977969287315458":
|
elif tweet_id == "287977969287315458":
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
from six import text_type
|
from typing import Optional, Any, Text
|
||||||
from typing import Optional, Any
|
|
||||||
|
|
||||||
SUBJECT_WITH_BRANCH_TEMPLATE = u'{repo} / {branch}'
|
SUBJECT_WITH_BRANCH_TEMPLATE = u'{repo} / {branch}'
|
||||||
SUBJECT_WITH_PR_OR_ISSUE_INFO_TEMPLATE = u'{repo} / {type} #{id} {title}'
|
SUBJECT_WITH_PR_OR_ISSUE_INFO_TEMPLATE = u'{repo} / {type} #{id} {title}'
|
||||||
|
@ -33,7 +32,7 @@ TAG_WITH_URL_TEMPLATE = u"[{tag_name}]({tag_url})"
|
||||||
TAG_WITHOUT_URL_TEMPLATE = u"{tag_name}"
|
TAG_WITHOUT_URL_TEMPLATE = u"{tag_name}"
|
||||||
|
|
||||||
def get_push_commits_event_message(user_name, compare_url, branch_name, commits_data, is_truncated=False):
|
def get_push_commits_event_message(user_name, compare_url, branch_name, commits_data, is_truncated=False):
|
||||||
# type: (text_type, Optional[text_type], text_type, List[Dict[str, Any]], Optional[bool]) -> text_type
|
# type: (Text, Optional[Text], Text, List[Dict[str, Any]], Optional[bool]) -> Text
|
||||||
if compare_url:
|
if compare_url:
|
||||||
pushed_text_message = PUSH_PUSHED_TEXT_WITH_URL.format(compare_url=compare_url)
|
pushed_text_message = PUSH_PUSHED_TEXT_WITH_URL.format(compare_url=compare_url)
|
||||||
else:
|
else:
|
||||||
|
@ -47,7 +46,7 @@ def get_push_commits_event_message(user_name, compare_url, branch_name, commits_
|
||||||
).rstrip()
|
).rstrip()
|
||||||
|
|
||||||
def get_force_push_commits_event_message(user_name, url, branch_name, head):
|
def get_force_push_commits_event_message(user_name, url, branch_name, head):
|
||||||
# type: (text_type, text_type, text_type, text_type) -> text_type
|
# type: (Text, Text, Text, Text) -> Text
|
||||||
return FORCE_PUSH_COMMITS_MESSAGE_TEMPLATE.format(
|
return FORCE_PUSH_COMMITS_MESSAGE_TEMPLATE.format(
|
||||||
user_name=user_name,
|
user_name=user_name,
|
||||||
url=url,
|
url=url,
|
||||||
|
@ -56,7 +55,7 @@ def get_force_push_commits_event_message(user_name, url, branch_name, head):
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_remove_branch_event_message(user_name, branch_name):
|
def get_remove_branch_event_message(user_name, branch_name):
|
||||||
# type: (text_type, text_type) -> text_type
|
# type: (Text, Text) -> Text
|
||||||
return REMOVE_BRANCH_MESSAGE_TEMPLATE.format(
|
return REMOVE_BRANCH_MESSAGE_TEMPLATE.format(
|
||||||
user_name=user_name,
|
user_name=user_name,
|
||||||
branch_name=branch_name,
|
branch_name=branch_name,
|
||||||
|
@ -67,7 +66,7 @@ def get_pull_request_event_message(
|
||||||
target_branch=None, base_branch=None,
|
target_branch=None, base_branch=None,
|
||||||
message=None, assignee=None, type='PR'
|
message=None, assignee=None, type='PR'
|
||||||
):
|
):
|
||||||
# type: (text_type, text_type, text_type, Optional[int], Optional[text_type], Optional[text_type], Optional[text_type], Optional[text_type], Optional[text_type]) -> text_type
|
# type: (Text, Text, Text, Optional[int], Optional[Text], Optional[Text], Optional[Text], Optional[Text], Optional[Text]) -> Text
|
||||||
main_message = PULL_REQUEST_OR_ISSUE_MESSAGE_TEMPLATE.format(
|
main_message = PULL_REQUEST_OR_ISSUE_MESSAGE_TEMPLATE.format(
|
||||||
user_name=user_name,
|
user_name=user_name,
|
||||||
action=action,
|
action=action,
|
||||||
|
@ -88,7 +87,7 @@ def get_pull_request_event_message(
|
||||||
return main_message.rstrip()
|
return main_message.rstrip()
|
||||||
|
|
||||||
def get_issue_event_message(user_name, action, url, number=None, message=None, assignee=None):
|
def get_issue_event_message(user_name, action, url, number=None, message=None, assignee=None):
|
||||||
# type: (text_type, text_type, text_type, Optional[int], Optional[text_type], Optional[text_type]) -> text_type
|
# type: (Text, Text, Text, Optional[int], Optional[Text], Optional[Text]) -> Text
|
||||||
return get_pull_request_event_message(
|
return get_pull_request_event_message(
|
||||||
user_name,
|
user_name,
|
||||||
action,
|
action,
|
||||||
|
@ -100,7 +99,7 @@ def get_issue_event_message(user_name, action, url, number=None, message=None, a
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_push_tag_event_message(user_name, tag_name, tag_url=None, action='pushed'):
|
def get_push_tag_event_message(user_name, tag_name, tag_url=None, action='pushed'):
|
||||||
# type: (text_type, text_type, Optional[text_type], Optional[text_type]) -> text_type
|
# type: (Text, Text, Optional[Text], Optional[Text]) -> Text
|
||||||
if tag_url:
|
if tag_url:
|
||||||
tag_part = TAG_WITH_URL_TEMPLATE.format(tag_name=tag_name, tag_url=tag_url)
|
tag_part = TAG_WITH_URL_TEMPLATE.format(tag_name=tag_name, tag_url=tag_url)
|
||||||
else:
|
else:
|
||||||
|
@ -112,7 +111,7 @@ def get_push_tag_event_message(user_name, tag_name, tag_url=None, action='pushed
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_commits_comment_action_message(user_name, action, commit_url, sha, message=None):
|
def get_commits_comment_action_message(user_name, action, commit_url, sha, message=None):
|
||||||
# type: (text_type, text_type, text_type, text_type, Optional[text_type]) -> text_type
|
# type: (Text, Text, Text, Text, Optional[Text]) -> Text
|
||||||
content = COMMITS_COMMENT_MESSAGE_TEMPLATE.format(
|
content = COMMITS_COMMENT_MESSAGE_TEMPLATE.format(
|
||||||
user_name=user_name,
|
user_name=user_name,
|
||||||
action=action,
|
action=action,
|
||||||
|
@ -126,7 +125,7 @@ def get_commits_comment_action_message(user_name, action, commit_url, sha, messa
|
||||||
return content
|
return content
|
||||||
|
|
||||||
def get_commits_content(commits_data, is_truncated=False):
|
def get_commits_content(commits_data, is_truncated=False):
|
||||||
# type: (List[Dict[str, Any]], Optional[bool]) -> text_type
|
# type: (List[Dict[str, Any]], Optional[bool]) -> Text
|
||||||
commits_content = u''
|
commits_content = u''
|
||||||
for commit in commits_data[:COMMITS_LIMIT]:
|
for commit in commits_data[:COMMITS_LIMIT]:
|
||||||
commits_content += COMMIT_ROW_TEMPLATE.format(
|
commits_content += COMMIT_ROW_TEMPLATE.format(
|
||||||
|
@ -146,5 +145,5 @@ def get_commits_content(commits_data, is_truncated=False):
|
||||||
return commits_content.rstrip()
|
return commits_content.rstrip()
|
||||||
|
|
||||||
def get_short_sha(sha):
|
def get_short_sha(sha):
|
||||||
# type: (text_type) -> text_type
|
# type: (Text) -> Text
|
||||||
return sha[:7]
|
return sha[:7]
|
||||||
|
|
Loading…
Reference in New Issue