Add zerver/lib/str_utils.py.

str_utils.py has functions for converting strings from one type to
another.  It also has a TypeVar called NonBinaryStr, which is like AnyStr
except that it doesn't allow bytes.
This commit is contained in:
Eklavya Sharma 2016-06-09 12:07:53 +05:30
parent ddd44189a9
commit 6d29da8cee
2 changed files with 44 additions and 4 deletions

View File

@ -67,6 +67,7 @@ from zerver.lib.narrow import check_supported_events_narrow_filter
from zerver.lib.request import JsonableError from zerver.lib.request import JsonableError
from zerver.lib.session_user import get_session_user from zerver.lib.session_user import get_session_user
from zerver.lib.upload import claim_attachment, delete_message_image from zerver.lib.upload import claim_attachment, delete_message_image
from zerver.lib.str_utils import NonBinaryStr
import DNS import DNS
import ujson import ujson
@ -80,7 +81,6 @@ import logging
import itertools import itertools
from collections import defaultdict from collections import defaultdict
NON_BINARY_STR = TypeVar('NON_BINARY_STR', str, text_type)
# This will be used to type annotate parameters in a function if the function # This will be used to type annotate parameters in a function if the function
# works on both str and unicode in python 2 but in python 3 it only works on str. # works on both str and unicode in python 2 but in python 3 it only works on str.
SizedTextIterable = Union[Sequence[text_type], AbstractSet[text_type]] SizedTextIterable = Union[Sequence[text_type], AbstractSet[text_type]]
@ -521,15 +521,15 @@ def do_change_user_email(user_profile, new_email):
'new_email': new_email}) 'new_email': new_email})
def compute_irc_user_fullname(email): def compute_irc_user_fullname(email):
# type: (NON_BINARY_STR) -> NON_BINARY_STR # type: (NonBinaryStr) -> NonBinaryStr
return email.split("@")[0] + " (IRC)" return email.split("@")[0] + " (IRC)"
def compute_jabber_user_fullname(email): def compute_jabber_user_fullname(email):
# type: (NON_BINARY_STR) -> NON_BINARY_STR # type: (NonBinaryStr) -> NonBinaryStr
return email.split("@")[0] + " (XMPP)" return email.split("@")[0] + " (XMPP)"
def compute_mit_user_fullname(email): def compute_mit_user_fullname(email):
# type: (NON_BINARY_STR) -> NON_BINARY_STR # type: (NonBinaryStr) -> NonBinaryStr
try: try:
# Input is either e.g. username@mit.edu or user|CROSSREALM.INVALID@mit.edu # Input is either e.g. username@mit.edu or user|CROSSREALM.INVALID@mit.edu
match_user = re.match(r'^([a-zA-Z0-9_.-]+)(\|.+)?@mit\.edu$', email.lower()) match_user = re.match(r'^([a-zA-Z0-9_.-]+)(\|.+)?@mit\.edu$', email.lower())

40
zerver/lib/str_utils.py Normal file
View File

@ -0,0 +1,40 @@
import six
from six import text_type, binary_type
from typing import Any, Mapping, Union, TypeVar
NonBinaryStr = TypeVar('NonBinaryStr', str, text_type)
# This is used to represent text or native strings
def force_text(s):
# type: (Union[text_type, binary_type]) -> text_type
if isinstance(s, text_type):
return s
elif isinstance(s, binary_type):
return s.decode('utf-8')
else:
raise ValueError("force_text expects a string type")
def force_bytes(s):
# type: (Union[text_type, binary_type]) -> binary_type
if isinstance(s, binary_type):
return s
elif isinstance(s, text_type):
return s.encode('utf-8')
else:
raise ValueError("force_bytes expects a string type")
def force_str(s):
# type: (Union[text_type, binary_type]) -> str
if isinstance(s, str):
return s
elif isinstance(s, text_type):
return s.encode('utf-8')
elif isinstance(s, binary_type):
return s.decode('utf-8')
else:
raise ValueError("force_str expects a string type")
def dict_with_str_keys(dct):
# type: (Mapping[NonBinaryStr, Any]) -> Dict[str, Any]
"""applies force_str on the keys of a dict (non-recursively)"""
return {force_str(key): value for key, value in six.iteritems(dct)}