mirror of
https://github.com/zulip/zulip.git
synced 2025-11-02 04:53:36 +00:00
Annotate most Zulip management commands.
This commit is contained in:
@@ -2,6 +2,7 @@ from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
from typing import Any
|
||||
|
||||
from zerver.models import UserPresence, UserActivity
|
||||
from zerver.lib.utils import statsd, statsd_key
|
||||
@@ -15,6 +16,7 @@ class Command(BaseCommand):
|
||||
Run as a cron job that runs every 10 minutes."""
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **Any) -> None
|
||||
# Get list of all active users in the last 1 week
|
||||
cutoff = datetime.now() - timedelta(minutes=30, hours=168)
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import datetime
|
||||
import pytz
|
||||
|
||||
from optparse import make_option
|
||||
from typing import Any
|
||||
from django.core.management.base import BaseCommand
|
||||
from zerver.lib.statistics import activity_averages_during_day
|
||||
|
||||
@@ -16,6 +17,7 @@ class Command(BaseCommand):
|
||||
help="Day to query in format 2013-12-05. Default is yesterday"),)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **Any) -> None
|
||||
if options["date"] is None:
|
||||
date = datetime.datetime.now() - datetime.timedelta(days=1)
|
||||
else:
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any
|
||||
|
||||
from optparse import make_option
|
||||
from django.core.management.base import BaseCommand
|
||||
from zerver.models import Recipient, Message
|
||||
@@ -10,6 +12,7 @@ import time
|
||||
import logging
|
||||
|
||||
def compute_stats(log_level):
|
||||
# type: (int) -> None
|
||||
logger = logging.getLogger()
|
||||
logger.setLevel(log_level)
|
||||
|
||||
@@ -76,6 +79,7 @@ class Command(BaseCommand):
|
||||
help = "Compute statistics on MIT Zephyr usage."
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **Any) -> None
|
||||
level = logging.INFO
|
||||
if options["verbose"]:
|
||||
level = logging.DEBUG
|
||||
|
||||
@@ -2,6 +2,8 @@ from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any, Dict
|
||||
|
||||
from zerver.lib.statistics import seconds_usage_between
|
||||
|
||||
from optparse import make_option
|
||||
@@ -11,6 +13,7 @@ import datetime
|
||||
from django.utils.timezone import utc
|
||||
|
||||
def analyze_activity(options):
|
||||
# type: (Dict[str, Any]) -> None
|
||||
day_start = datetime.datetime.strptime(options["date"], "%Y-%m-%d").replace(tzinfo=utc)
|
||||
day_end = day_start + datetime.timedelta(days=options["duration"])
|
||||
|
||||
@@ -56,4 +59,5 @@ is shown for all realms"""
|
||||
)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **Any) -> None
|
||||
analyze_activity(options)
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.db.models import Count
|
||||
from django.db.models import Count, QuerySet
|
||||
|
||||
from zerver.models import UserActivity, UserProfile, Realm, \
|
||||
get_realm, get_user_profile_by_email
|
||||
@@ -19,10 +22,12 @@ python manage.py client_activity zulip.com
|
||||
python manage.py client_activity jesstess@zulip.com"""
|
||||
|
||||
def add_arguments(self, parser):
|
||||
# type: (ArgumentParser) -> None
|
||||
parser.add_argument('arg', metavar='<arg>', type=str, nargs='?', default=None,
|
||||
help="realm or user to estimate client activity for")
|
||||
|
||||
def compute_activity(self, user_activity_objects):
|
||||
# type: (QuerySet) -> None
|
||||
# Report data from the past week.
|
||||
#
|
||||
# This is a rough report of client activity because we inconsistently
|
||||
@@ -54,6 +59,7 @@ python manage.py client_activity jesstess@zulip.com"""
|
||||
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **str) -> None
|
||||
if options['arg'] is None:
|
||||
# Report global activity.
|
||||
self.compute_activity(UserActivity.objects.all())
|
||||
|
||||
@@ -2,6 +2,9 @@ from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any
|
||||
|
||||
from argparse import ArgumentParser
|
||||
import datetime
|
||||
import pytz
|
||||
|
||||
@@ -19,10 +22,12 @@ class Command(BaseCommand):
|
||||
help = "Generate statistics on realm activity."
|
||||
|
||||
def add_arguments(self, parser):
|
||||
# type: (ArgumentParser) -> None
|
||||
parser.add_argument('realms', metavar='<realm>', type=str, nargs='*',
|
||||
help="realm to generate statistics for")
|
||||
|
||||
def active_users(self, realm):
|
||||
# type: (Realm) -> List[UserProfile]
|
||||
# Has been active (on the website, for now) in the last 7 days.
|
||||
activity_cutoff = datetime.datetime.now(tz=pytz.utc) - datetime.timedelta(days=7)
|
||||
return [activity.user_profile for activity in \
|
||||
@@ -33,36 +38,44 @@ class Command(BaseCommand):
|
||||
client__name="website")]
|
||||
|
||||
def messages_sent_by(self, user, days_ago):
|
||||
# type: (UserProfile, int) -> int
|
||||
sent_time_cutoff = datetime.datetime.now(tz=pytz.utc) - datetime.timedelta(days=days_ago)
|
||||
return human_messages.filter(sender=user, pub_date__gt=sent_time_cutoff).count()
|
||||
|
||||
def total_messages(self, realm, days_ago):
|
||||
# type: (Realm, int) -> int
|
||||
sent_time_cutoff = datetime.datetime.now(tz=pytz.utc) - datetime.timedelta(days=days_ago)
|
||||
return Message.objects.filter(sender__realm=realm, pub_date__gt=sent_time_cutoff).count()
|
||||
|
||||
def human_messages(self, realm, days_ago):
|
||||
# type: (Realm, int) -> int
|
||||
sent_time_cutoff = datetime.datetime.now(tz=pytz.utc) - datetime.timedelta(days=days_ago)
|
||||
return human_messages.filter(sender__realm=realm, pub_date__gt=sent_time_cutoff).count()
|
||||
|
||||
def api_messages(self, realm, days_ago):
|
||||
# type: (Realm, int) -> int
|
||||
return (self.total_messages(realm, days_ago) - self.human_messages(realm, days_ago))
|
||||
|
||||
def stream_messages(self, realm, days_ago):
|
||||
# type: (Realm, int) -> int
|
||||
sent_time_cutoff = datetime.datetime.now(tz=pytz.utc) - datetime.timedelta(days=days_ago)
|
||||
return human_messages.filter(sender__realm=realm, pub_date__gt=sent_time_cutoff,
|
||||
recipient__type=Recipient.STREAM).count()
|
||||
|
||||
def private_messages(self, realm, days_ago):
|
||||
# type: (Realm, int) -> int
|
||||
sent_time_cutoff = datetime.datetime.now(tz=pytz.utc) - datetime.timedelta(days=days_ago)
|
||||
return human_messages.filter(sender__realm=realm, pub_date__gt=sent_time_cutoff).exclude(
|
||||
recipient__type=Recipient.STREAM).exclude(recipient__type=Recipient.HUDDLE).count()
|
||||
|
||||
def group_private_messages(self, realm, days_ago):
|
||||
# type: (Realm, int) -> int
|
||||
sent_time_cutoff = datetime.datetime.now(tz=pytz.utc) - datetime.timedelta(days=days_ago)
|
||||
return human_messages.filter(sender__realm=realm, pub_date__gt=sent_time_cutoff).exclude(
|
||||
recipient__type=Recipient.STREAM).exclude(recipient__type=Recipient.PERSONAL).count()
|
||||
|
||||
def report_percentage(self, numerator, denominator, text):
|
||||
# type: (float, float, str) -> None
|
||||
if not denominator:
|
||||
fraction = 0.0
|
||||
else:
|
||||
@@ -70,6 +83,7 @@ class Command(BaseCommand):
|
||||
print("%.2f%% of" % (fraction * 100,), text)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **Any) -> None
|
||||
if options['realms']:
|
||||
try:
|
||||
realms = [get_realm(domain) for domain in options['realms']]
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.db.models import Q
|
||||
from zerver.models import Realm, Stream, Message, Subscription, Recipient, get_realm
|
||||
@@ -9,10 +12,12 @@ class Command(BaseCommand):
|
||||
help = "Generate statistics on the streams for a realm."
|
||||
|
||||
def add_arguments(self, parser):
|
||||
# type: (ArgumentParser) -> None
|
||||
parser.add_argument('realms', metavar='<realm>', type=str, nargs='*',
|
||||
help="realm to generate statistics for")
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **str) -> None
|
||||
if options['realms']:
|
||||
try:
|
||||
realms = [get_realm(domain) for domain in options['realms']]
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from argparse import ArgumentParser
|
||||
import datetime
|
||||
import pytz
|
||||
from typing import Any
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
from zerver.models import UserProfile, Realm, Stream, Message, get_realm
|
||||
@@ -12,15 +14,18 @@ class Command(BaseCommand):
|
||||
help = "Generate statistics on user activity."
|
||||
|
||||
def add_arguments(self, parser):
|
||||
# type: (ArgumentParser) -> None
|
||||
parser.add_argument('realms', metavar='<realm>', type=str, nargs='*',
|
||||
help="realm to generate statistics for")
|
||||
|
||||
def messages_sent_by(self, user, week):
|
||||
# type: (UserProfile, int) -> int
|
||||
start = datetime.datetime.now(tz=pytz.utc) - datetime.timedelta(days=(week + 1)*7)
|
||||
end = datetime.datetime.now(tz=pytz.utc) - datetime.timedelta(days=week*7)
|
||||
return Message.objects.filter(sender=user, pub_date__gt=start, pub_date__lte=end).count()
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **Any) -> None
|
||||
if options['realms']:
|
||||
try:
|
||||
realms = [get_realm(domain) for domain in options['realms']]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
__revision__ = '$Id: cleanupconfirmation.py 5 2008-11-18 09:10:12Z jarek.zgoda $'
|
||||
|
||||
from typing import Any
|
||||
|
||||
from django.core.management.base import NoArgsCommand
|
||||
|
||||
@@ -14,4 +15,5 @@ class Command(NoArgsCommand):
|
||||
help = 'Delete expired confirmations from database'
|
||||
|
||||
def handle_noargs(self, **options):
|
||||
# type: (**Any) -> None
|
||||
Confirmation.objects.delete_expired_confirmations()
|
||||
|
||||
@@ -3,6 +3,8 @@ from __future__ import print_function
|
||||
|
||||
from optparse import make_option
|
||||
|
||||
from typing import Any
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from zerver.lib.actions import create_stream_if_needed, do_add_subscription
|
||||
@@ -32,6 +34,7 @@ class Command(BaseCommand):
|
||||
)
|
||||
|
||||
def handle(self, **options):
|
||||
# type: (**Any) -> None
|
||||
if options["domain"] is None or options["streams"] is None or \
|
||||
(options["users"] is None and options["all_users"] is None):
|
||||
self.print_help("python manage.py", "add_users_to_streams")
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from zerver.lib.actions import do_update_message_flags
|
||||
@@ -10,10 +13,12 @@ class Command(BaseCommand):
|
||||
help = """Bankrupt one or many users."""
|
||||
|
||||
def add_arguments(self, parser):
|
||||
# type: (ArgumentParser) -> None
|
||||
parser.add_argument('emails', metavar='<email>', type=str, nargs='+',
|
||||
help='email address to bankrupt')
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **str) -> None
|
||||
for email in options['emails']:
|
||||
try:
|
||||
user_profile = get_user_profile_by_email(email)
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from zerver.lib.actions import do_change_full_name
|
||||
@@ -10,10 +13,12 @@ class Command(BaseCommand):
|
||||
help = """Change the names for many users."""
|
||||
|
||||
def add_arguments(self, parser):
|
||||
# type: (ArgumentParser) -> None
|
||||
parser.add_argument('data_file', metavar='<data file>', type=str,
|
||||
help="file containing rows of the form <email>,<desired name>")
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **str) -> None
|
||||
data_file = options['data_file']
|
||||
with open(data_file, "r") as f:
|
||||
for line in f:
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
from typing import Any
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from django.core.management.base import BaseCommand
|
||||
from zerver.lib.actions import do_change_user_email
|
||||
from zerver.models import UserProfile, get_user_profile_by_email
|
||||
|
||||
@@ -10,12 +12,14 @@ class Command(BaseCommand):
|
||||
help = """Change the email address for a user."""
|
||||
|
||||
def add_arguments(self, parser):
|
||||
# type: (ArgumentParser) -> None
|
||||
parser.add_argument('old_email', metavar='<old email>', type=str,
|
||||
help='email address to change')
|
||||
parser.add_argument('new_email', metavar='<new email>', type=str,
|
||||
help='new email address')
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **str) -> None
|
||||
old_email = options['old_email']
|
||||
new_email = options['new_email']
|
||||
try:
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from typing import Any
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
from zerver.lib.push_notifications import check_apns_feedback
|
||||
|
||||
@@ -10,4 +12,5 @@ class Command(BaseCommand):
|
||||
Usage: ./manage.py check_apns_tokens"""
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **Any) -> None
|
||||
check_apns_feedback()
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any, Callable, Optional
|
||||
|
||||
from zerver.models import get_user_profile_by_id
|
||||
from zerver.lib.rate_limiter import client, max_api_calls, max_api_window
|
||||
|
||||
@@ -24,6 +26,7 @@ class Command(BaseCommand):
|
||||
)
|
||||
|
||||
def _check_within_range(self, key, count_func, trim_func=None):
|
||||
# type: ignore # should be (str, Callable[[], int], Optional[Callable[[str, int], None]]) -> None
|
||||
user_id = int(key.split(':')[1])
|
||||
try:
|
||||
user = get_user_profile_by_id(user_id)
|
||||
@@ -44,6 +47,7 @@ than max_api_calls! (trying to trim) %s %s" % (key, count))
|
||||
trim_func(key, max_calls)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **Any) -> None
|
||||
if not settings.RATE_LIMITING:
|
||||
print("This machine is not using redis or rate limiting, aborting")
|
||||
exit(1)
|
||||
|
||||
@@ -2,6 +2,7 @@ from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from optparse import make_option
|
||||
from typing import Any
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.conf import settings
|
||||
@@ -11,7 +12,8 @@ class Command(BaseCommand):
|
||||
help = """Checks your Zulip Voyager Django configuration for issues."""
|
||||
|
||||
option_list = BaseCommand.option_list + ()
|
||||
def handle(self, **options):
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **Any) -> None
|
||||
for (setting_name, default) in settings.REQUIRED_SETTINGS:
|
||||
try:
|
||||
if settings.__getattr__(setting_name) != default:
|
||||
|
||||
@@ -2,6 +2,8 @@ from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
from optparse import make_option
|
||||
|
||||
from typing import Any
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.management.base import BaseCommand
|
||||
from zerver.lib.actions import do_create_realm, set_default_streams
|
||||
@@ -40,6 +42,7 @@ Usage: python manage.py create_realm --domain=foo.com --name='Foo, Inc.'"""
|
||||
)
|
||||
|
||||
def validate_domain(self, domain):
|
||||
# type: (str) -> None
|
||||
# Domains can't contain whitespace if they are to be used in memcached
|
||||
# keys. Seems safer to leave that as the default case regardless of
|
||||
# which backing store we use.
|
||||
@@ -56,6 +59,7 @@ Usage: python manage.py create_realm --domain=foo.com --name='Foo, Inc.'"""
|
||||
raise ValueError("Cannot create a new realm that is already an alias for an existing realm")
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **Any) -> None
|
||||
if options["domain"] is None or options["name"] is None:
|
||||
print("\033[1;31mPlease provide both a domain and name.\033[0m\n", file=sys.stderr)
|
||||
self.print_help("python manage.py", "create_realm")
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from zerver.lib.actions import do_create_stream
|
||||
from zerver.models import Realm, get_realm
|
||||
|
||||
from argparse import ArgumentParser
|
||||
import sys
|
||||
|
||||
class Command(BaseCommand):
|
||||
@@ -15,12 +18,14 @@ This should be used for TESTING only, unless you understand the limitations of
|
||||
the command."""
|
||||
|
||||
def add_arguments(self, parser):
|
||||
# type: (ArgumentParser) -> None
|
||||
parser.add_argument('domain', metavar='<domain>', type=str,
|
||||
help='domain in which to create the stream')
|
||||
parser.add_argument('stream_name', metavar='<stream name>', type=str,
|
||||
help='name of stream to create')
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **str) -> None
|
||||
domain = options['domain']
|
||||
stream_name = options['stream_name']
|
||||
encoding = sys.getfilesystemencoding()
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any
|
||||
|
||||
import sys
|
||||
import argparse
|
||||
|
||||
@@ -25,6 +27,7 @@ Omit both <email> and <full name> for interactive user creation.
|
||||
"""
|
||||
|
||||
def add_arguments(self, parser):
|
||||
# type: (argparse.ArgumentParser) -> None
|
||||
parser.add_argument('--this-user-has-accepted-the-tos',
|
||||
dest='tos',
|
||||
action="store_true",
|
||||
@@ -40,6 +43,7 @@ Omit both <email> and <full name> for interactive user creation.
|
||||
help='full name of new user')
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **Any) -> None
|
||||
if not options["tos"]:
|
||||
raise CommandError("""You must confirm that this user has accepted the
|
||||
Terms of Service by passing --this-user-has-accepted-the-tos.""")
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from argparse import ArgumentParser
|
||||
import sys
|
||||
|
||||
from zerver.lib.actions import do_deactivate_realm
|
||||
@@ -12,10 +15,12 @@ class Command(BaseCommand):
|
||||
help = """Script to deactivate a realm."""
|
||||
|
||||
def add_arguments(self, parser):
|
||||
# type: (ArgumentParser) -> None
|
||||
parser.add_argument('domain', metavar='<domain>', type=str,
|
||||
help='domain of realm to deactivate')
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **str) -> None
|
||||
realm = get_realm(options["domain"])
|
||||
if realm is None:
|
||||
print("Could not find realm %s" % (options["domain"],))
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from optparse import make_option
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
@@ -12,6 +15,7 @@ class Command(BaseCommand):
|
||||
help = "Deactivate a user, including forcibly logging them out."
|
||||
|
||||
def add_arguments(self, parser):
|
||||
# type: (ArgumentParser) -> None
|
||||
parser.add_argument('-f', '--for-real',
|
||||
dest='for_real',
|
||||
action='store_true',
|
||||
@@ -21,6 +25,7 @@ class Command(BaseCommand):
|
||||
help='email of user to deactivate')
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **Any) -> None
|
||||
user_profile = get_user_profile_by_email(options['email'])
|
||||
|
||||
print("Deactivating %s (%s) - %s" % (user_profile.full_name,
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from zerver.lib.actions import do_delete_old_unclaimed_attachments
|
||||
@@ -12,6 +15,7 @@ class Command(BaseCommand):
|
||||
One week is taken as the default value."""
|
||||
|
||||
def add_arguments(self, parser):
|
||||
# type: (ArgumentParser) -> None
|
||||
parser.add_argument('-w', '--weeks',
|
||||
dest='delta_weeks',
|
||||
default=1,
|
||||
@@ -24,7 +28,7 @@ class Command(BaseCommand):
|
||||
help="Actually remove the files from the storage.")
|
||||
|
||||
def handle(self, *args, **options):
|
||||
|
||||
# type: (*Any, **Any) -> None
|
||||
delta_weeks = options['delta_weeks']
|
||||
print("Deleting unclaimed attached files older than %s" % (delta_weeks,))
|
||||
print("")
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any
|
||||
|
||||
from optparse import make_option
|
||||
from django.core.management.base import BaseCommand
|
||||
from zerver.models import get_realm, Message, Realm, Stream, Recipient
|
||||
@@ -24,6 +26,7 @@ class Command(BaseCommand):
|
||||
)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **Any) -> None
|
||||
realm = get_realm(options["domain"])
|
||||
streams = Stream.objects.filter(realm=realm, invite_only=False)
|
||||
recipients = Recipient.objects.filter(
|
||||
|
||||
@@ -36,6 +36,9 @@ This script can be used via two mechanisms:
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any
|
||||
|
||||
from argparse import ArgumentParser
|
||||
import email
|
||||
import os
|
||||
from email.header import decode_header
|
||||
@@ -123,9 +126,11 @@ def login_failed(failure):
|
||||
return failure
|
||||
|
||||
def done(_):
|
||||
# type: (Any) -> None
|
||||
reactor.callLater(0, reactor.stop)
|
||||
|
||||
def main():
|
||||
# type: () -> None
|
||||
imap_client = protocol.ClientCreator(reactor, imap4.IMAP4Client)
|
||||
d = imap_client.connectSSL(settings.EMAIL_GATEWAY_IMAP_SERVER, settings.EMAIL_GATEWAY_IMAP_PORT, ssl.ClientContextFactory())
|
||||
d.addCallbacks(connected, login_failed)
|
||||
@@ -135,10 +140,12 @@ class Command(BaseCommand):
|
||||
help = __doc__
|
||||
|
||||
def add_arguments(self, parser):
|
||||
# type: (ArgumentParser) -> None
|
||||
parser.add_argument('recipient', metavar='<recipient>', type=str, nargs='?', default=None,
|
||||
help="original recipient")
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **str) -> None
|
||||
rcpt_to = os.environ.get("ORIGINAL_RECIPIENT", options['recipient'])
|
||||
if rcpt_to is not None:
|
||||
if is_missed_message_address(rcpt_to):
|
||||
|
||||
@@ -3,6 +3,8 @@ import datetime
|
||||
import pytz
|
||||
import logging
|
||||
|
||||
from typing import Any
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
@@ -25,6 +27,7 @@ logger.addHandler(file_handler)
|
||||
|
||||
VALID_DIGEST_DAYS = (1, 2, 3, 4)
|
||||
def inactive_since(user_profile, cutoff):
|
||||
# type: (UserProfile, datetime.datetime) -> bool
|
||||
# Hasn't used the app in the last 24 business-day hours.
|
||||
most_recent_visit = [row.last_visit for row in \
|
||||
UserActivity.objects.filter(
|
||||
@@ -38,6 +41,7 @@ def inactive_since(user_profile, cutoff):
|
||||
return last_visit < cutoff
|
||||
|
||||
def last_business_day():
|
||||
# type: () -> datetime.datetime
|
||||
one_day = datetime.timedelta(hours=23)
|
||||
previous_day = datetime.datetime.now(tz=pytz.utc) - one_day
|
||||
while previous_day.weekday() not in VALID_DIGEST_DAYS:
|
||||
@@ -47,12 +51,14 @@ def last_business_day():
|
||||
# Changes to this should also be reflected in
|
||||
# zerver/worker/queue_processors.py:DigestWorker.consume()
|
||||
def queue_digest_recipient(user_profile, cutoff):
|
||||
# type: (UserProfile, datetime.datetime) -> None
|
||||
# Convert cutoff to epoch seconds for transit.
|
||||
event = {"user_profile_id": user_profile.id,
|
||||
"cutoff": cutoff.strftime('%s')}
|
||||
queue_json_publish("digest_emails", event, lambda event: None)
|
||||
|
||||
def domains_for_this_deployment():
|
||||
# type: () -> List[str]
|
||||
if settings.ZULIP_COM:
|
||||
# Voyager deployments don't have a Deployment entry.
|
||||
# Only send zulip.com digests on staging.
|
||||
@@ -69,6 +75,7 @@ def domains_for_this_deployment():
|
||||
return []
|
||||
|
||||
def should_process_digest(domain, deployment_domains):
|
||||
# type: (str, List[str]) -> bool
|
||||
if settings.VOYAGER:
|
||||
# Voyager. We ship with a zulip.com realm for the feedback bot, but
|
||||
# don't try to send e-mails to it.
|
||||
@@ -85,6 +92,7 @@ class Command(BaseCommand):
|
||||
in a while.
|
||||
"""
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **Any) -> None
|
||||
# To be really conservative while we don't have user timezones or
|
||||
# special-casing for companies with non-standard workweeks, only
|
||||
# try to send mail on Tuesdays, Wednesdays, and Thursdays.
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from django.core.management.base import BaseCommand
|
||||
from zerver.lib.queue import queue_json_publish
|
||||
|
||||
@@ -9,6 +12,7 @@ import ujson
|
||||
|
||||
|
||||
def error(*args):
|
||||
# type: (*Any) -> None
|
||||
raise Exception('We cannot enqueue because settings.USING_RABBITMQ is False.')
|
||||
|
||||
class Command(BaseCommand):
|
||||
@@ -23,12 +27,14 @@ You can use "-" to represent stdin.
|
||||
"""
|
||||
|
||||
def add_arguments(self, parser):
|
||||
# type: (ArgumentParser) -> None
|
||||
parser.add_argument('queue_name', metavar='<queue>', type=str,
|
||||
help="name of worker queue to enqueue to")
|
||||
parser.add_argument('file_name', metavar='<file>', type=str,
|
||||
help="name of file containing JSON lines")
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **str) -> None
|
||||
queue_name = options['queue_name']
|
||||
file_name = options['file_name']
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from typing import Any
|
||||
|
||||
from optparse import make_option
|
||||
from django.core.management.base import BaseCommand
|
||||
from zerver.lib.cache_helpers import fill_remote_cache, cache_fillers
|
||||
@@ -10,8 +12,10 @@ class Command(BaseCommand):
|
||||
help = "Populate the memcached cache of messages."
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **str) -> None
|
||||
if options["cache"] is not None:
|
||||
return fill_remote_cache(options["cache"])
|
||||
fill_remote_cache(options["cache"])
|
||||
return
|
||||
|
||||
for cache in cache_fillers.keys():
|
||||
fill_remote_cache(cache)
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from django.core.management.base import BaseCommand
|
||||
from confirmation.models import Confirmation
|
||||
from zerver.models import UserProfile, PreregistrationUser, \
|
||||
@@ -10,6 +13,7 @@ class Command(BaseCommand):
|
||||
help = "Generate activation links for users and print them to stdout."
|
||||
|
||||
def add_arguments(self, parser):
|
||||
# type: (ArgumentParser) -> None
|
||||
parser.add_argument('--domain',
|
||||
dest='domain',
|
||||
type=str,
|
||||
@@ -23,6 +27,7 @@ class Command(BaseCommand):
|
||||
help='email of user to generate an activation link for')
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **Any) -> None
|
||||
duplicates = False
|
||||
for email in options['emails']:
|
||||
try:
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from typing import Any
|
||||
|
||||
from argparse import ArgumentParser
|
||||
import requests
|
||||
from zerver.models import get_user_profile_by_email, UserProfile
|
||||
from zerver.lib.avatar import gravatar_hash
|
||||
@@ -13,12 +16,14 @@ email addresses are specified, use the Gravatar for the first and upload the ima
|
||||
for both email addresses."""
|
||||
|
||||
def add_arguments(self, parser):
|
||||
# type: (ArgumentParser) -> None
|
||||
parser.add_argument('old_email', metavar='<old email>', type=str,
|
||||
help="user whose Gravatar should be migrated")
|
||||
parser.add_argument('new_email', metavar='<new email>', type=str, nargs='?', default=None,
|
||||
help="user to copy the Gravatar to")
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **str) -> None
|
||||
old_email = options['old_email']
|
||||
|
||||
if options['new_email']:
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from typing import Any, Iterable, Tuple
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from django.contrib.sites.models import Site
|
||||
@@ -14,6 +16,7 @@ from optparse import make_option
|
||||
settings.TORNADO_SERVER = None
|
||||
|
||||
def create_users(name_list, bot_type=None):
|
||||
# type: (Iterable[Tuple[str, str]], int) -> None
|
||||
realms = {}
|
||||
for realm in Realm.objects.all():
|
||||
realms[realm.domain] = realm
|
||||
@@ -35,7 +38,8 @@ class Command(BaseCommand):
|
||||
help='The number of extra users to create'),
|
||||
)
|
||||
|
||||
def handle(self, **options):
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **Any) -> None
|
||||
Realm.objects.create(domain="zulip.com")
|
||||
|
||||
names = [(settings.FEEDBACK_BOT_NAME, settings.FEEDBACK_BOT)]
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
@@ -15,6 +18,7 @@ ONLY perform this on customer request from an authorized person.
|
||||
"""
|
||||
|
||||
def add_arguments(self, parser):
|
||||
# type: (ArgumentParser) -> None
|
||||
parser.add_argument('-f', '--for-real',
|
||||
dest='ack',
|
||||
action="store_true",
|
||||
@@ -34,6 +38,7 @@ ONLY perform this on customer request from an authorized person.
|
||||
help="email of user to knight")
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **Any) -> None
|
||||
email = options['email']
|
||||
try:
|
||||
profile = UserProfile.objects.get(email=email)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from typing import Any
|
||||
from optparse import make_option
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
@@ -24,6 +25,7 @@ class Command(BaseCommand):
|
||||
)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **Any) -> None
|
||||
if options["realm"]:
|
||||
realm = get_realm(options["realm"])
|
||||
delete_realm_user_sessions(realm)
|
||||
|
||||
@@ -30,6 +30,9 @@ http://stackoverflow.com/questions/2090717/getting-translation-strings-for-jinja
|
||||
"""
|
||||
from __future__ import absolute_import
|
||||
|
||||
from typing import Any, Dict, Iterable, Mapping, Set, Tuple
|
||||
|
||||
from argparse import ArgumentParser
|
||||
import os
|
||||
import re
|
||||
import glob
|
||||
@@ -53,6 +56,7 @@ regexes = ['{{#tr .*?}}(.*?){{/tr}}',
|
||||
frontend_compiled_regexes = [re.compile(regex) for regex in regexes]
|
||||
|
||||
def strip_whitespaces(src):
|
||||
# type: (str) -> str
|
||||
src = strip_whitespace_left.sub(r'\1', src)
|
||||
src = strip_whitespace_right.sub(r'\1', src)
|
||||
return src
|
||||
@@ -60,6 +64,7 @@ def strip_whitespaces(src):
|
||||
class Command(makemessages.Command):
|
||||
|
||||
def add_arguments(self, parser):
|
||||
# type: (ArgumentParser) -> None
|
||||
super(Command, self).add_arguments(parser)
|
||||
parser.add_argument('--frontend-source', type=str,
|
||||
default='static/templates',
|
||||
@@ -72,10 +77,12 @@ class Command(makemessages.Command):
|
||||
help='Namespace of the frontend locale file')
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **Any) -> None
|
||||
self.handle_django_locales(*args, **options)
|
||||
self.handle_frontend_locales(*args, **options)
|
||||
|
||||
def handle_frontend_locales(self, *args, **options):
|
||||
# type: (*Any, **Any) -> None
|
||||
self.frontend_source = options.get('frontend_source')
|
||||
self.frontend_output = options.get('frontend_output')
|
||||
self.frontend_namespace = options.get('frontend_namespace')
|
||||
@@ -87,6 +94,7 @@ class Command(makemessages.Command):
|
||||
self.write_translation_strings(translation_strings)
|
||||
|
||||
def handle_django_locales(self, *args, **options):
|
||||
# type: (*Any, **Any) -> None
|
||||
old_endblock_re = trans_real.endblock_re
|
||||
old_block_re = trans_real.block_re
|
||||
old_constant_re = trans_real.constant_re
|
||||
@@ -117,7 +125,8 @@ class Command(makemessages.Command):
|
||||
trans_real.constant_re = old_constant_re
|
||||
|
||||
def extract_strings(self, data):
|
||||
translation_strings = {}
|
||||
# type: (str) -> Dict[str, str]
|
||||
translation_strings = {} # type: Dict[str, str]
|
||||
for regex in frontend_compiled_regexes:
|
||||
for match in regex.findall(data):
|
||||
translation_strings[match] = ""
|
||||
@@ -125,6 +134,7 @@ class Command(makemessages.Command):
|
||||
return translation_strings
|
||||
|
||||
def get_translation_strings(self):
|
||||
# type: () -> Dict[str, str]
|
||||
translation_strings = {} # type: Dict[str, str]
|
||||
dirname = self.get_template_dir()
|
||||
|
||||
@@ -137,13 +147,16 @@ class Command(makemessages.Command):
|
||||
return translation_strings
|
||||
|
||||
def get_template_dir(self):
|
||||
# type: () -> str
|
||||
return self.frontend_source
|
||||
|
||||
|
||||
def get_namespace(self):
|
||||
# type: () -> str
|
||||
return self.frontend_namespace
|
||||
|
||||
def get_locales(self):
|
||||
# type: () -> Iterable[str]
|
||||
locale = self.frontend_locale
|
||||
exclude = self.frontend_exclude
|
||||
process_all = self.frontend_all
|
||||
@@ -159,9 +172,11 @@ class Command(makemessages.Command):
|
||||
return set(locales) - set(exclude)
|
||||
|
||||
def get_base_path(self):
|
||||
# type: () -> str
|
||||
return self.frontend_output
|
||||
|
||||
def get_output_paths(self):
|
||||
# type: () -> Iterable[str]
|
||||
base_path = self.get_base_path()
|
||||
locales = self.get_locales()
|
||||
for path in [os.path.join(base_path, locale) for locale in locales]:
|
||||
@@ -171,17 +186,19 @@ class Command(makemessages.Command):
|
||||
yield os.path.join(path, self.get_namespace())
|
||||
|
||||
def get_new_strings(self, old_strings, translation_strings):
|
||||
# type: (Mapping[str, str], Iterable[str]) -> Dict[str, str]
|
||||
"""
|
||||
Missing strings are removed, new strings are added and already
|
||||
translated strings are not touched.
|
||||
"""
|
||||
new_strings = {}
|
||||
new_strings = {} # Dict[str, str]
|
||||
for k in translation_strings:
|
||||
new_strings[k] = old_strings.get(k, k)
|
||||
|
||||
return new_strings
|
||||
|
||||
def write_translation_strings(self, translation_strings):
|
||||
# type: (Iterable[str]) -> None
|
||||
for locale, output_path in zip(self.get_locales(), self.get_output_paths()):
|
||||
self.stdout.write("[frontend] processing locale {}".format(locale))
|
||||
try:
|
||||
|
||||
@@ -7,6 +7,7 @@ Shows backlog count of ScheduledJobs of type Email
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any
|
||||
from django.conf import settings
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
@@ -25,7 +26,6 @@ Usage: python manage.py print_email_delivery_backlog
|
||||
"""
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **Any) -> None
|
||||
print(len(ScheduledJob.objects.filter(type=ScheduledJob.EMAIL,
|
||||
scheduled_timestamp__lte=datetime.utcnow()-timedelta(minutes=1))))
|
||||
return
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from typing import Any
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.core.management import CommandError
|
||||
from django.conf import settings
|
||||
@@ -11,6 +14,7 @@ import threading
|
||||
|
||||
class Command(BaseCommand):
|
||||
def add_arguments(self, parser):
|
||||
# type: (ArgumentParser) -> None
|
||||
parser.add_argument('--queue_name', metavar='<queue name>', type=str,
|
||||
help="queue to process")
|
||||
parser.add_argument('--worker_num', metavar='<worker number>', type=int, nargs='?', default=0,
|
||||
@@ -20,6 +24,7 @@ class Command(BaseCommand):
|
||||
|
||||
help = "Runs a queue processing worker"
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **Any) -> None
|
||||
logging.basicConfig()
|
||||
logger = logging.getLogger('process_queue')
|
||||
|
||||
@@ -51,10 +56,12 @@ class Command(BaseCommand):
|
||||
|
||||
class Threaded_worker(threading.Thread):
|
||||
def __init__(self, queue_name):
|
||||
# type: (str) -> None
|
||||
threading.Thread.__init__(self)
|
||||
self.worker = get_worker(queue_name)
|
||||
|
||||
def run(self):
|
||||
# type: () -> None
|
||||
self.worker.setup()
|
||||
logging.debug('starting consuming ' + self.worker.queue_name)
|
||||
self.worker.start()
|
||||
|
||||
@@ -1,17 +1,22 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.core.management import CommandError
|
||||
from zerver.lib.queue import SimpleQueueClient
|
||||
|
||||
class Command(BaseCommand):
|
||||
def add_arguments(self, parser):
|
||||
# type: (ArgumentParser) -> None
|
||||
parser.add_argument('queue_name', metavar='<queue name>', type=str,
|
||||
help="queue to purge")
|
||||
|
||||
help = "Discards all messages from the given queue"
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **str) -> None
|
||||
queue_name = options['queue_name']
|
||||
queue = SimpleQueueClient()
|
||||
queue.ensure_queue(queue_name, lambda: None)
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any
|
||||
|
||||
from argparse import ArgumentParser
|
||||
import sys
|
||||
|
||||
from django.contrib.auth import authenticate, login, get_backends
|
||||
@@ -12,6 +15,7 @@ from django_auth_ldap.backend import LDAPBackend, _LDAPUser
|
||||
|
||||
# Quick tool to test whether you're correctly authenticating to LDAP
|
||||
def query_ldap(**options):
|
||||
# type: (**str) -> None
|
||||
email = options['email']
|
||||
for backend in get_backends():
|
||||
if isinstance(backend, LDAPBackend):
|
||||
@@ -24,8 +28,10 @@ def query_ldap(**options):
|
||||
|
||||
class Command(BaseCommand):
|
||||
def add_arguments(self, parser):
|
||||
# type: (ArgumentParser) -> None
|
||||
parser.add_argument('email', metavar='<email>', type=str,
|
||||
help="email of user to query")
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **str) -> None
|
||||
query_ldap(**options)
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from zerver.models import UserProfile, get_user_profile_by_email
|
||||
from zerver.lib.rate_limiter import block_user, unblock_user
|
||||
|
||||
@@ -11,6 +14,7 @@ class Command(BaseCommand):
|
||||
help = """Manually block or unblock a user from accessing the API"""
|
||||
|
||||
def add_arguments(self, parser):
|
||||
# type: (ArgumentParser) -> None
|
||||
parser.add_argument('-e', '--email',
|
||||
dest='email',
|
||||
help="Email account of user.")
|
||||
@@ -35,6 +39,7 @@ class Command(BaseCommand):
|
||||
help="operation to perform (block or unblock)")
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **Any) -> None
|
||||
if (not options['api_key'] and not options['email']) or \
|
||||
(options['api_key'] and options['email']):
|
||||
print("Please enter either an email or API key to manage")
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
import sys
|
||||
@@ -12,10 +15,12 @@ class Command(BaseCommand):
|
||||
help = """Script to reactivate a deactivated realm."""
|
||||
|
||||
def add_arguments(self, parser):
|
||||
# type: (ArgumentParser) -> None
|
||||
parser.add_argument('domain', metavar='<domain>', type=str,
|
||||
help='domain of realm to reactivate')
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **str) -> None
|
||||
realm = get_realm(options["domain"])
|
||||
if realm is None:
|
||||
print("Could not find realm %s" % (options["domain"],))
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from django.core.management.base import BaseCommand
|
||||
from zerver.models import Realm, RealmAlias, get_realm
|
||||
from zerver.lib.actions import realm_aliases
|
||||
@@ -10,6 +13,7 @@ class Command(BaseCommand):
|
||||
help = """Manage aliases for the specified realm"""
|
||||
|
||||
def add_arguments(self, parser):
|
||||
# type: (ArgumentParser) -> None
|
||||
parser.add_argument('-r', '--realm',
|
||||
dest='domain',
|
||||
type=str,
|
||||
@@ -24,6 +28,7 @@ class Command(BaseCommand):
|
||||
help="alias to add or remove")
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **str) -> None
|
||||
realm = get_realm(options["domain"])
|
||||
if options["op"] == "show":
|
||||
print("Aliases for %s:" % (realm.domain,))
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from django.core.management.base import BaseCommand
|
||||
from zerver.models import Realm, get_realm
|
||||
from zerver.lib.actions import check_add_realm_emoji, do_remove_realm_emoji
|
||||
@@ -16,6 +19,7 @@ Example: python manage.py realm_emoji --realm=zulip.com --op=show
|
||||
"""
|
||||
|
||||
def add_arguments(self, parser):
|
||||
# type: (ArgumentParser) -> None
|
||||
parser.add_argument('-r', '--realm',
|
||||
dest='domain',
|
||||
type=str,
|
||||
@@ -32,6 +36,7 @@ Example: python manage.py realm_emoji --realm=zulip.com --op=show
|
||||
help="URL of image to display for the emoji")
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **str) -> None
|
||||
realm = get_realm(options["domain"])
|
||||
if options["op"] == "show":
|
||||
for name, url in six.iteritems(realm.get_emoji()):
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from optparse import make_option
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
@@ -22,6 +26,7 @@ Example: python manage.py realm_filters --realm=zulip.com --op=show
|
||||
"""
|
||||
|
||||
def add_arguments(self, parser):
|
||||
# type: (ArgumentParser) -> None
|
||||
parser.add_argument('-r', '--realm',
|
||||
dest='domain',
|
||||
type=str,
|
||||
@@ -38,6 +43,7 @@ Example: python manage.py realm_filters --realm=zulip.com --op=show
|
||||
help="format string to substitute")
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **str) -> None
|
||||
realm = get_realm(options["domain"])
|
||||
if options["op"] == "show":
|
||||
print("%s: %s" % (realm.domain, all_realm_filters().get(realm.domain, [])))
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from optparse import make_option
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
@@ -33,6 +36,7 @@ class Command(BaseCommand):
|
||||
)
|
||||
|
||||
def handle(self, **options):
|
||||
# type: (*Any, **Any) -> None
|
||||
if options["domain"] is None or options["stream"] is None or \
|
||||
(options["users"] is None and options["all_users"] is None):
|
||||
self.print_help("python manage.py", "remove_users_from_stream")
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from zerver.lib.actions import do_rename_stream
|
||||
@@ -12,6 +15,7 @@ class Command(BaseCommand):
|
||||
help = """Change the stream name for a realm."""
|
||||
|
||||
def add_arguments(self, parser):
|
||||
# type: (ArgumentParser) -> None
|
||||
parser.add_argument('domain', metavar='<domain>', type=str,
|
||||
help="domain to operate on")
|
||||
parser.add_argument('old_name', metavar='<old name>', type=str,
|
||||
@@ -20,6 +24,7 @@ class Command(BaseCommand):
|
||||
help='new name to rename the stream to')
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **str) -> None
|
||||
domain = options['domain']
|
||||
old_name = options['old_name']
|
||||
new_name = options['new_name']
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
# Wrapper around Django's runserver to allow filtering logs.
|
||||
|
||||
from typing import Any
|
||||
|
||||
from django.core.servers.basehttp import WSGIRequestHandler
|
||||
orig_log_message = WSGIRequestHandler.log_message
|
||||
def log_message_monkey(self, format, *args):
|
||||
# type: (Any, str, *Any) -> None
|
||||
# Filter output for 200 or 304 responses.
|
||||
if args[1] == '200' or args[1] == '304':
|
||||
return
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any
|
||||
|
||||
from django.conf import settings
|
||||
settings.RUNNING_INSIDE_TORNADO = True
|
||||
# We must call zerver.lib.tornado_ioloop_logging.instrument_tornado_ioloop
|
||||
@@ -12,6 +14,7 @@ from zerver.lib.tornado_ioloop_logging import instrument_tornado_ioloop
|
||||
instrument_tornado_ioloop()
|
||||
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from optparse import make_option
|
||||
import os
|
||||
import sys
|
||||
@@ -55,6 +58,7 @@ class Command(BaseCommand):
|
||||
args = '[optional port number or ipaddr:port]\n (use multiple ports to start multiple servers)'
|
||||
|
||||
def handle(self, addrport, **options):
|
||||
# type: (str, **bool) -> None
|
||||
# setup unbuffered I/O
|
||||
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
|
||||
sys.stderr = os.fdopen(sys.stderr.fileno(), 'w', 0)
|
||||
@@ -83,6 +87,7 @@ class Command(BaseCommand):
|
||||
format='%(asctime)s %(levelname)-8s %(message)s')
|
||||
|
||||
def inner_run():
|
||||
# type: () -> None
|
||||
from django.conf import settings
|
||||
from django.utils import translation
|
||||
translation.activate(settings.LANGUAGE_CODE)
|
||||
@@ -139,6 +144,7 @@ class AsyncDjangoHandler(tornado.web.RequestHandler, base.BaseHandler):
|
||||
initLock = Lock()
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
# type: (*Any, **Any) -> None
|
||||
super(AsyncDjangoHandler, self).__init__(*args, **kwargs)
|
||||
|
||||
# Set up middleware if needed. We couldn't do this earlier, because
|
||||
@@ -155,9 +161,11 @@ class AsyncDjangoHandler(tornado.web.RequestHandler, base.BaseHandler):
|
||||
allocate_handler_id(self)
|
||||
|
||||
def __repr__(self):
|
||||
# type: () -> str
|
||||
return "AsyncDjangoHandler<%s, %s>" % (self.handler_id, get_descriptor_by_handler_id(self.handler_id))
|
||||
|
||||
def get(self, *args, **kwargs):
|
||||
# type: (*Any, **Any) -> None
|
||||
environ = WSGIContainer.environ(self.request)
|
||||
environ['PATH_INFO'] = urllib.parse.unquote(environ['PATH_INFO'])
|
||||
request = WSGIRequest(environ)
|
||||
@@ -186,21 +194,26 @@ class AsyncDjangoHandler(tornado.web.RequestHandler, base.BaseHandler):
|
||||
|
||||
|
||||
def head(self, *args, **kwargs):
|
||||
# type: (*Any, **Any) -> None
|
||||
self.get(*args, **kwargs)
|
||||
|
||||
def post(self, *args, **kwargs):
|
||||
# type: (*Any, **Any) -> None
|
||||
self.get(*args, **kwargs)
|
||||
|
||||
def delete(self, *args, **kwargs):
|
||||
# type: (*Any, **Any) -> None
|
||||
self.get(*args, **kwargs)
|
||||
|
||||
def on_connection_close(self):
|
||||
# type: () -> None
|
||||
client_descriptor = get_descriptor_by_handler_id(self.handler_id)
|
||||
if client_descriptor is not None:
|
||||
client_descriptor.disconnect_handler(client_closed=True)
|
||||
|
||||
# Based on django.core.handlers.base: get_response
|
||||
def get_response(self, request):
|
||||
# type: (HttpRequest) -> HttpResponse
|
||||
"Returns an HttpResponse object for the given HttpRequest"
|
||||
try:
|
||||
try:
|
||||
@@ -325,6 +338,7 @@ class AsyncDjangoHandler(tornado.web.RequestHandler, base.BaseHandler):
|
||||
|
||||
### Copied from get_response (above in this file)
|
||||
def apply_response_middleware(self, request, response, resolver):
|
||||
# type: (HttpRequest, HttpResponse, urlresolvers.RegexURLResolver) -> HttpResponse
|
||||
try:
|
||||
# Apply response middleware, regardless of the response
|
||||
for middleware_method in self._response_middleware:
|
||||
@@ -337,6 +351,7 @@ class AsyncDjangoHandler(tornado.web.RequestHandler, base.BaseHandler):
|
||||
return response
|
||||
|
||||
def zulip_finish(self, response, request, apply_markdown):
|
||||
# type: (HttpResponse, HttpRequest, bool) -> None
|
||||
# Make sure that Markdown rendering really happened, if requested.
|
||||
# This is a security issue because it's where we escape HTML.
|
||||
# c.f. ticket #64
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from typing import Any
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.conf import settings
|
||||
|
||||
@@ -7,6 +10,7 @@ class Command(BaseCommand):
|
||||
help = """Send some stats to statsd."""
|
||||
|
||||
def add_arguments(self, parser):
|
||||
# type: (ArgumentParser) -> None
|
||||
parser.add_argument('operation', metavar='<operation>', type=str,
|
||||
choices=['incr', 'decr', 'timing', 'timer', 'gauge'],
|
||||
help="incr|decr|timing|timer|gauge")
|
||||
@@ -14,6 +18,7 @@ class Command(BaseCommand):
|
||||
parser.add_argument('val', metavar='<val>', type=str)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **str) -> None
|
||||
operation = options['operation']
|
||||
name = options['name']
|
||||
val = options['val']
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from typing import Any
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
from django.conf import settings
|
||||
from django.core.mail import send_mail, BadHeaderError
|
||||
@@ -8,10 +11,12 @@ class Command(BaseCommand):
|
||||
help = """Send email to specified email address."""
|
||||
|
||||
def add_arguments(self, parser):
|
||||
# type: (ArgumentParser) -> None
|
||||
parser.add_argument('to', metavar='<to>', type=str,
|
||||
help="email of user to send the email")
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **str) -> None
|
||||
subject = "Zulip Test email"
|
||||
message = "Success! If you receive this message, you've successfully " + \
|
||||
"configured sending email from your Zulip server."
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any
|
||||
|
||||
import os
|
||||
import ujson
|
||||
from optparse import make_option
|
||||
@@ -32,6 +34,7 @@ Example:
|
||||
)
|
||||
|
||||
def handle(self, **options):
|
||||
# type: (*Any, **str) -> None
|
||||
if options['fixture'] is None or options['url'] is None:
|
||||
self.print_help('python manage.py', 'send_webhook_fixture_message')
|
||||
exit(1)
|
||||
@@ -47,7 +50,9 @@ Example:
|
||||
client.post(options['url'], json, content_type="application/json")
|
||||
|
||||
def _does_fixture_path_exist(self, fixture_path):
|
||||
# type: (str) -> bool
|
||||
return os.path.exists(fixture_path)
|
||||
|
||||
def _get_fixture_as_json(self, fixture_path):
|
||||
# type: (str) -> str
|
||||
return ujson.dumps(ujson.loads(open(fixture_path).read()))
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from zerver.models import get_realm
|
||||
@@ -36,6 +38,7 @@ python manage.py set_default_streams --domain=foo.com --streams=
|
||||
)
|
||||
|
||||
def handle(self, **options):
|
||||
# type: (*Any, **str) -> None
|
||||
if options["domain"] is None or options["streams"] is None:
|
||||
print("Please provide both a domain name and a default \
|
||||
set of streams (which can be empty, with `--streams=`).", file=sys.stderr)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any, Iterable
|
||||
|
||||
from optparse import make_option
|
||||
import logging
|
||||
import sys
|
||||
@@ -41,6 +43,7 @@ class Command(BaseCommand):
|
||||
)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **Any) -> None
|
||||
if not options["flag"] or not options["op"] or not options["email"]:
|
||||
print("Please specify an operation, a flag and an email")
|
||||
exit(1)
|
||||
@@ -65,6 +68,7 @@ class Command(BaseCommand):
|
||||
sys.stderr.close()
|
||||
|
||||
def do_update(batch):
|
||||
# type: (Iterable[int]) -> None
|
||||
msgs = UserMessage.objects.filter(id__in=batch)
|
||||
if op == 'add':
|
||||
msgs.update(flags=models.F('flags').bitor(flag))
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from django.core.management.base import BaseCommand
|
||||
from zerver.models import get_realm, Realm
|
||||
import sys
|
||||
@@ -9,16 +12,18 @@ class Command(BaseCommand):
|
||||
help = """Show the admins in a realm."""
|
||||
|
||||
def add_arguments(self, parser):
|
||||
# type: (ArgumentParser) -> None
|
||||
parser.add_argument('realm', metavar='<realm>', type=str,
|
||||
help="realm to show admins for")
|
||||
|
||||
def handle(self, *args, **options):
|
||||
realm = options['realm']
|
||||
# type: (*Any, **str) -> None
|
||||
realm_name = options['realm']
|
||||
|
||||
try:
|
||||
realm = get_realm(realm)
|
||||
realm = get_realm(realm_name)
|
||||
except Realm.DoesNotExist:
|
||||
print('There is no realm called %s.' % (realm,))
|
||||
print('There is no realm called %s.' % (realm_name,))
|
||||
sys.exit(1)
|
||||
|
||||
users = realm.get_admin_users()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.db.utils import IntegrityError
|
||||
@@ -24,6 +25,7 @@ logger.addHandler(file_handler)
|
||||
|
||||
# Run this on a cronjob to pick up on name changes.
|
||||
def sync_ldap_user_data():
|
||||
# type: () -> None
|
||||
logger.info("Starting update.")
|
||||
backend = ZulipLDAPUserPopulator()
|
||||
for u in UserProfile.objects.select_related().filter(is_active=True, is_bot=False).all():
|
||||
@@ -40,4 +42,5 @@ def sync_ldap_user_data():
|
||||
|
||||
class Command(BaseCommand):
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **Any) -> None
|
||||
sync_ldap_user_data()
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any
|
||||
|
||||
from optparse import make_option
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
@@ -23,6 +25,7 @@ class Command(BaseCommand):
|
||||
)
|
||||
|
||||
def handle(self, **options):
|
||||
# type: (**str) -> None
|
||||
if options["domain"] is None and options["users"] is None:
|
||||
self.print_help("python manage.py", "turn_off_digests")
|
||||
exit(1)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from typing import Any
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.db.models import get_app, get_models
|
||||
from django.contrib.auth.management import create_permissions
|
||||
@@ -8,5 +10,6 @@ class Command(BaseCommand):
|
||||
help = "Sync newly created object permissions to the database"
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **Any) -> None
|
||||
# From http://stackoverflow.com/a/11914435/90777
|
||||
create_permissions(get_app("zerver"), get_models(), 2)
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from optparse import make_option
|
||||
import sys
|
||||
from typing import Any
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
@@ -31,6 +33,7 @@ class Command(BaseCommand):
|
||||
)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **Any) -> None
|
||||
if None in (options["api"], options["web"], options["domain"]):
|
||||
print("\033[1;31mYou must provide a domain, an API URL, and a web URL.\033[0m\n", file=sys.stderr)
|
||||
self.print_help("python manage.py", "create_realm")
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from typing import Any
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from zerver.lib.actions import send_referral_event
|
||||
@@ -9,12 +12,14 @@ class Command(BaseCommand):
|
||||
help = """Grants a user invites and resets the number of invites they've used."""
|
||||
|
||||
def add_arguments(self, parser):
|
||||
# type: (ArgumentParser) -> None
|
||||
parser.add_argument('email', metavar='<email>', type=str,
|
||||
help="user to grant invites to")
|
||||
parser.add_argument('num_invites', metavar='<num invites>', type=int,
|
||||
help="number of invites to grant")
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **Any) -> None
|
||||
email = options['email']
|
||||
num_invites = options['num_invites']
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from typing import Any
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
from zerver.models import Subscription
|
||||
|
||||
@@ -7,6 +9,7 @@ class Command(BaseCommand):
|
||||
help = """One-off script to migration users' stream notification settings."""
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **Any) -> None
|
||||
for subscription in Subscription.objects.all():
|
||||
subscription.desktop_notifications = subscription.notifications
|
||||
subscription.audible_notifications = subscription.notifications
|
||||
|
||||
@@ -31,11 +31,12 @@ import glob
|
||||
import os
|
||||
from optparse import make_option
|
||||
from six.moves import range
|
||||
from typing import Any, Dict, Set, Tuple
|
||||
from typing import Any, Dict, List, IO, Iterable, Mapping, Set, Tuple
|
||||
|
||||
settings.TORNADO_SERVER = None
|
||||
|
||||
def create_users(realms, name_list, bot_type=None):
|
||||
# type: (Mapping[str, Realm], Iterable[Tuple[str, str]], int) -> None
|
||||
user_set = set()
|
||||
for full_name, email in name_list:
|
||||
short_name = email_to_username(email)
|
||||
@@ -43,6 +44,7 @@ def create_users(realms, name_list, bot_type=None):
|
||||
bulk_create_users(realms, user_set, bot_type)
|
||||
|
||||
def create_streams(realms, realm, stream_list):
|
||||
# type: (Mapping[str, Realm], Realm, Iterable[str]) -> None
|
||||
stream_set = set()
|
||||
for stream_name in stream_list:
|
||||
stream_set.add((realm.domain, stream_name))
|
||||
@@ -109,6 +111,7 @@ class Command(BaseCommand):
|
||||
)
|
||||
|
||||
def handle(self, **options):
|
||||
# type: (**Any) -> None
|
||||
if options["percent_huddles"] + options["percent_personals"] > 100:
|
||||
self.stderr.write("Error! More than 100% of messages allocated.\n")
|
||||
return
|
||||
@@ -257,11 +260,13 @@ class Command(BaseCommand):
|
||||
|
||||
recipient_hash = {} # type: Dict[int, Recipient]
|
||||
def get_recipient_by_id(rid):
|
||||
# type: (int) -> Recipient
|
||||
if rid in recipient_hash:
|
||||
return recipient_hash[rid]
|
||||
return Recipient.objects.get(id=rid)
|
||||
|
||||
def restore_saved_messages():
|
||||
# type: () -> None
|
||||
old_messages = []
|
||||
duplicate_suppression_hash = {} # type: Dict[str, bool]
|
||||
|
||||
@@ -276,6 +281,7 @@ def restore_saved_messages():
|
||||
# First, determine all the objects our messages will need.
|
||||
print(datetime.datetime.now(), "Creating realms/streams/etc...")
|
||||
def process_line(line):
|
||||
# type: (str) -> None
|
||||
old_message_json = line.strip()
|
||||
|
||||
# Due to populate_db's shakespeare mode, we have a lot of
|
||||
@@ -302,6 +308,7 @@ def restore_saved_messages():
|
||||
# Lower case emails and domains; it will screw up
|
||||
# deduplication if we don't
|
||||
def fix_email(email):
|
||||
# type: (str) -> str
|
||||
return email.strip().lower()
|
||||
|
||||
if message_type in ["stream", "huddle", "personal"]:
|
||||
@@ -708,6 +715,7 @@ def restore_saved_messages():
|
||||
# - multiple messages per subject
|
||||
# - both single and multi-line content
|
||||
def send_messages(data):
|
||||
# type: ignore # Should be (Tuple[int, List[UserProfile], Dict[str, Any], Any]) -> int
|
||||
(tot_messages, personals_pairs, options, output) = data
|
||||
random.seed(os.getpid())
|
||||
texts = open("zilencer/management/commands/test_messages.txt", "r").readlines()
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from django.core.management.base import BaseCommand
|
||||
from zerver.lib.initial_password import initial_password
|
||||
from zerver.models import get_user_profile_by_email
|
||||
@@ -11,10 +14,12 @@ class Command(BaseCommand):
|
||||
fmt = '%-30s %-16s %-32s'
|
||||
|
||||
def add_arguments(self, parser):
|
||||
# type: (ArgumentParser) -> None
|
||||
parser.add_argument('emails', metavar='<email>', type=str, nargs='*',
|
||||
help="email of user to show password and API key for")
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **str) -> None
|
||||
print(self.fmt % ('email', 'password', 'API key'))
|
||||
for email in options['emails']:
|
||||
if '@' not in email:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from __future__ import absolute_import
|
||||
from typing import Any, Dict
|
||||
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from optparse import make_option
|
||||
from django.core.management.base import BaseCommand
|
||||
from zerver.models import get_user_profile_by_email, UserMessage
|
||||
@@ -13,10 +14,12 @@ request_logger = LogRequests()
|
||||
|
||||
class MockSession(object):
|
||||
def __init__(self):
|
||||
# type: () -> None
|
||||
self.modified = False
|
||||
|
||||
class MockRequest(object):
|
||||
class MockRequest(HttpRequest):
|
||||
def __init__(self, email):
|
||||
# type: (str) -> None
|
||||
self.user = get_user_profile_by_email(email)
|
||||
self.path = '/'
|
||||
self.method = "POST"
|
||||
@@ -28,9 +31,11 @@ class MockRequest(object):
|
||||
self.session = MockSession()
|
||||
|
||||
def get_full_path(self):
|
||||
# type: () -> str
|
||||
return self.path
|
||||
|
||||
def profile_request(request):
|
||||
# type: (HttpRequest) -> HttpResponse
|
||||
request_logger.process_request(request)
|
||||
prof = cProfile.Profile()
|
||||
prof.enable()
|
||||
@@ -48,4 +53,5 @@ class Command(BaseCommand):
|
||||
)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **Any) -> None
|
||||
profile_request(MockRequest(options["email"]))
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from zerver.models import Message
|
||||
@@ -13,6 +15,7 @@ class Command(BaseCommand):
|
||||
Usage: python manage.py render_old_messages"""
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **Any) -> None
|
||||
total_rendered = 0
|
||||
while True:
|
||||
messages = Message.objects.filter(rendered_content_version=None)[0:100]
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
from typing import Any
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
from zerver.models import get_user_profile_by_email, UserProfile
|
||||
import os
|
||||
@@ -10,6 +12,7 @@ class Command(BaseCommand):
|
||||
help = """Sync your API key from ~/.zuliprc into your development instance"""
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# type: (*Any, **Any) -> None
|
||||
config_file = os.path.join(os.environ["HOME"], ".zuliprc")
|
||||
if not os.path.exists(config_file):
|
||||
raise RuntimeError("No ~/.zuliprc found")
|
||||
|
||||
Reference in New Issue
Block a user