mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	Add annotations to avatar.py, db.py, logging_util.py, unminify.py.
Also, fixed a a small type annotation in users.py because email must be a string because emails don't support UTF-8 at this time (according a comment in gravatar_hash in avatar.py).
This commit is contained in:
		@@ -3,8 +3,13 @@ from django.conf import settings
 | 
			
		||||
 | 
			
		||||
import hashlib
 | 
			
		||||
from zerver.lib.utils import make_safe_digest
 | 
			
		||||
if False:
 | 
			
		||||
    from zerver.models import UserProfile
 | 
			
		||||
 | 
			
		||||
from six import text_type
 | 
			
		||||
 | 
			
		||||
def gravatar_hash(email):
 | 
			
		||||
    # type: (str) -> str
 | 
			
		||||
    """Compute the Gravatar hash for an email address."""
 | 
			
		||||
    # Non-ASCII characters aren't permitted by the currently active e-mail
 | 
			
		||||
    # RFCs. However, the IETF has published https://tools.ietf.org/html/rfc4952,
 | 
			
		||||
@@ -14,6 +19,7 @@ def gravatar_hash(email):
 | 
			
		||||
    return make_safe_digest(email.lower(), hashlib.md5)
 | 
			
		||||
 | 
			
		||||
def user_avatar_hash(email):
 | 
			
		||||
    # type: (str) -> str
 | 
			
		||||
    # Salting the user_key may be overkill, but it prevents us from
 | 
			
		||||
    # basically mimicking Gravatar's hashing scheme, which could lead
 | 
			
		||||
    # to some abuse scenarios like folks using us as a free Gravatar
 | 
			
		||||
@@ -22,12 +28,14 @@ def user_avatar_hash(email):
 | 
			
		||||
    return make_safe_digest(user_key, hashlib.sha1)
 | 
			
		||||
 | 
			
		||||
def avatar_url(user_profile):
 | 
			
		||||
    # type: (UserProfile) -> text_type
 | 
			
		||||
    return get_avatar_url(
 | 
			
		||||
            user_profile.avatar_source,
 | 
			
		||||
            user_profile.email
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
def get_avatar_url(avatar_source, email):
 | 
			
		||||
    # type: (str, str) -> str
 | 
			
		||||
    if avatar_source == 'U':
 | 
			
		||||
        hash_key = user_avatar_hash(email)
 | 
			
		||||
        if settings.LOCAL_UPLOADS_DIR is not None:
 | 
			
		||||
 
 | 
			
		||||
@@ -3,9 +3,16 @@ from __future__ import absolute_import
 | 
			
		||||
import time
 | 
			
		||||
from psycopg2.extensions import cursor, connection
 | 
			
		||||
 | 
			
		||||
from typing import Callable, Optional, Iterable, Any, Dict, Union, TypeVar, \
 | 
			
		||||
    Mapping, Sequence
 | 
			
		||||
from six import text_type
 | 
			
		||||
 | 
			
		||||
CursorObj = TypeVar('CursorObj', bound=cursor)
 | 
			
		||||
 | 
			
		||||
# Similar to the tracking done in Django's CursorDebugWrapper, but done at the
 | 
			
		||||
# psycopg2 cursor level so it works with SQLAlchemy.
 | 
			
		||||
def wrapper_execute(self, action, sql, params=()):
 | 
			
		||||
    # type: (CursorObj, Callable[[text_type, Optional[Union[Iterable[Any], Dict[text_type, Any]]]], CursorObj], text_type, Union[Iterable[Any], Dict[text_type, Any]]) -> CursorObj
 | 
			
		||||
    start = time.time()
 | 
			
		||||
    try:
 | 
			
		||||
        return action(sql, params)
 | 
			
		||||
@@ -20,25 +27,30 @@ class TimeTrackingCursor(cursor):
 | 
			
		||||
    """A psycopg2 cursor class that tracks the time spent executing queries."""
 | 
			
		||||
 | 
			
		||||
    def execute(self, query, vars=None):
 | 
			
		||||
        # type: (text_type, Optional[Union[Iterable[Any], Dict[text_type, Any]]]) -> TimeTrackingCursor
 | 
			
		||||
        return wrapper_execute(self, super(TimeTrackingCursor, self).execute, query, vars)
 | 
			
		||||
 | 
			
		||||
    def executemany(self, query, vars):
 | 
			
		||||
        # type: (text_type, Iterable[Any]) -> TimeTrackingCursor
 | 
			
		||||
        return wrapper_execute(self, super(TimeTrackingCursor, self).executemany, query, vars)
 | 
			
		||||
 | 
			
		||||
class TimeTrackingConnection(connection):
 | 
			
		||||
    """A psycopg2 connection class that uses TimeTrackingCursors."""
 | 
			
		||||
 | 
			
		||||
    def __init__(self, *args, **kwargs):
 | 
			
		||||
        # type: (Sequence[Any], Mapping[text_type, Any]) -> None
 | 
			
		||||
        self.queries = [] # type: List[Dict[str, str]]
 | 
			
		||||
        super(TimeTrackingConnection, self).__init__(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    def cursor(self, name=None):
 | 
			
		||||
        # type: (Optional[text_type]) -> TimeTrackingCursor
 | 
			
		||||
        if name is None:
 | 
			
		||||
            return super(TimeTrackingConnection, self).cursor(cursor_factory=TimeTrackingCursor)
 | 
			
		||||
        else:
 | 
			
		||||
            return super(TimeTrackingConnection, self).cursor(name, cursor_factory=TimeTrackingCursor)
 | 
			
		||||
 | 
			
		||||
def reset_queries():
 | 
			
		||||
    # type: () -> None
 | 
			
		||||
    from django.db import connections
 | 
			
		||||
    for conn in connections.all():
 | 
			
		||||
        if conn.connection is not None:
 | 
			
		||||
 
 | 
			
		||||
@@ -9,6 +9,7 @@ class _RateLimitFilter(object):
 | 
			
		||||
    last_error = datetime.min
 | 
			
		||||
 | 
			
		||||
    def filter(self, record):
 | 
			
		||||
        # type: (logging.LogRecord) -> bool
 | 
			
		||||
        from django.conf import settings
 | 
			
		||||
        from django.core.cache import cache
 | 
			
		||||
 | 
			
		||||
@@ -44,9 +45,11 @@ class EmailLimiter(_RateLimitFilter):
 | 
			
		||||
 | 
			
		||||
class ReturnTrue(logging.Filter):
 | 
			
		||||
    def filter(self, record):
 | 
			
		||||
        # type: (logging.LogRecord) -> bool
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
class RequireReallyDeployed(logging.Filter):
 | 
			
		||||
    def filter(self, record):
 | 
			
		||||
        # type: (logging.LogRecord) -> bool
 | 
			
		||||
        from django.conf import settings
 | 
			
		||||
        return settings.PRODUCTION
 | 
			
		||||
 
 | 
			
		||||
@@ -4,16 +4,21 @@ import re
 | 
			
		||||
import os.path
 | 
			
		||||
import sourcemap
 | 
			
		||||
from six.moves import map
 | 
			
		||||
from six import text_type
 | 
			
		||||
 | 
			
		||||
from typing import Dict
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class SourceMap(object):
 | 
			
		||||
    '''Map (line, column) pairs from generated to source file.'''
 | 
			
		||||
 | 
			
		||||
    def __init__(self, sourcemap_dir):
 | 
			
		||||
        # type: (text_type) -> None
 | 
			
		||||
        self._dir = sourcemap_dir
 | 
			
		||||
        self._indices = {} # type: Dict[str, sourcemap.SourceMapDecoder]
 | 
			
		||||
        self._indices = {} # type: Dict[text_type, sourcemap.SourceMapDecoder]
 | 
			
		||||
 | 
			
		||||
    def _index_for(self, minified_src):
 | 
			
		||||
        # type: (text_type) -> sourcemap.SourceMapDecoder
 | 
			
		||||
        '''Return the source map index for minified_src, loading it if not
 | 
			
		||||
           already loaded.'''
 | 
			
		||||
        if minified_src not in self._indices:
 | 
			
		||||
@@ -23,7 +28,8 @@ class SourceMap(object):
 | 
			
		||||
        return self._indices[minified_src]
 | 
			
		||||
 | 
			
		||||
    def annotate_stacktrace(self, stacktrace):
 | 
			
		||||
        out = ''
 | 
			
		||||
        # type: (text_type) -> text_type
 | 
			
		||||
        out = '' # type: text_type
 | 
			
		||||
        for ln in stacktrace.splitlines():
 | 
			
		||||
            out += ln + '\n'
 | 
			
		||||
            match = re.search(r'/static/min/(.+)(\.[0-9a-f]+)\.js:(\d+):(\d+)', ln)
 | 
			
		||||
 
 | 
			
		||||
@@ -85,7 +85,7 @@ def update_user_backend(request, user_profile, email,
 | 
			
		||||
    return json_success({})
 | 
			
		||||
 | 
			
		||||
def avatar(request, email):
 | 
			
		||||
    # type: (HttpRequest, text_type) -> HttpResponse
 | 
			
		||||
    # type: (HttpRequest, str) -> HttpResponse
 | 
			
		||||
    try:
 | 
			
		||||
        user_profile = get_user_profile_by_email(email)
 | 
			
		||||
        avatar_source = user_profile.avatar_source
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user