fix: avoid mutables as defaults. Compute date default arguments at runtime rather than loadtime. (#4144)
This commit is contained in:
parent
75bb797d9e
commit
b988850985
|
@ -226,7 +226,11 @@ class JsonExportMixin(object):
|
|||
# content_type = 'application/json'
|
||||
# return HttpResponse(serialize([ obj ], sort_keys=True, indent=3)[2:-2], content_type=content_type)
|
||||
|
||||
def json_view(self, request, filter={}, expand=[]):
|
||||
def json_view(self, request, filter=None, expand=None):
|
||||
if expand is None:
|
||||
expand = []
|
||||
if filter is None:
|
||||
filter = {}
|
||||
qfilter, exclude = filter_from_queryargs(request)
|
||||
for k in list(qfilter.keys()):
|
||||
if k.startswith("_"):
|
||||
|
|
|
@ -650,10 +650,12 @@ def nice_consensus(consensus):
|
|||
}
|
||||
return mapping[consensus]
|
||||
|
||||
def has_same_ballot(doc, date1, date2=datetime.date.today()):
|
||||
def has_same_ballot(doc, date1, date2=None):
|
||||
""" Test if the most recent ballot created before the end of date1
|
||||
is the same as the most recent ballot created before the
|
||||
end of date 2. """
|
||||
if date2 is None:
|
||||
date2 = datetime.date.today()
|
||||
ballot1 = doc.latest_event(BallotDocEvent,type='created_ballot',time__lt=date1+datetime.timedelta(days=1))
|
||||
ballot2 = doc.latest_event(BallotDocEvent,type='created_ballot',time__lt=date2+datetime.timedelta(days=1))
|
||||
return ballot1==ballot2
|
||||
|
@ -926,7 +928,9 @@ def extract_complete_replaces_ancestor_mapping_for_docs(names):
|
|||
def make_rev_history(doc):
|
||||
# return document history data for inclusion in doc.json (used by timeline)
|
||||
|
||||
def get_predecessors(doc, predecessors=[]):
|
||||
def get_predecessors(doc, predecessors=None):
|
||||
if predecessors is None:
|
||||
predecessors = []
|
||||
if hasattr(doc, 'relateddocument_set'):
|
||||
for alias in doc.related_that_doc('replaces'):
|
||||
for document in alias.docs.all():
|
||||
|
@ -935,7 +939,9 @@ def make_rev_history(doc):
|
|||
predecessors.extend(get_predecessors(document, predecessors))
|
||||
return predecessors
|
||||
|
||||
def get_ancestors(doc, ancestors = []):
|
||||
def get_ancestors(doc, ancestors = None):
|
||||
if ancestors is None:
|
||||
ancestors = []
|
||||
if hasattr(doc, 'relateddocument_set'):
|
||||
for alias in doc.related_that('replaces'):
|
||||
for document in alias.docs.all():
|
||||
|
@ -1328,4 +1334,4 @@ def fuzzy_find_documents(name, rev=None):
|
|||
rev = None # found a doc by name with rev = None, so update that
|
||||
|
||||
FoundDocuments = namedtuple('FoundDocuments', 'documents matched_name matched_rev')
|
||||
return FoundDocuments(docs, name, rev)
|
||||
return FoundDocuments(docs, name, rev)
|
||||
|
|
|
@ -600,7 +600,9 @@ def get_eligibility_date(nomcom=None, date=None):
|
|||
else:
|
||||
return datetime.date(datetime.date.today().year,5,1)
|
||||
|
||||
def previous_five_meetings(date = datetime.date.today()):
|
||||
def previous_five_meetings(date = None):
|
||||
if date is None:
|
||||
date = datetime.date.today()
|
||||
return Meeting.objects.filter(type='ietf',date__lte=date).order_by('-date')[:5]
|
||||
|
||||
def three_of_five_eligible(previous_five, queryset=None):
|
||||
|
|
|
@ -13,7 +13,9 @@ register = template.Library()
|
|||
|
||||
|
||||
@register.filter
|
||||
def is_nomcom_eligible(person, date=datetime.date.today()):
|
||||
def is_nomcom_eligible(person, date=None):
|
||||
if date is None:
|
||||
date = datetime.date.today()
|
||||
return is_eligible(person=person, date=date)
|
||||
|
||||
|
||||
|
@ -88,4 +90,4 @@ def email_person_link(email, **kwargs):
|
|||
"title": title,
|
||||
"class": cls,
|
||||
"with_email": with_email,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -140,10 +140,13 @@ ReviewAssignmentData = namedtuple("ReviewAssignmentData", [
|
|||
"request_to_assignment_days", "assignment_to_closure_days", "request_to_closure_days"])
|
||||
|
||||
|
||||
def extract_review_assignment_data(teams=None, reviewers=None, time_from=None, time_to=None, ordering=[]):
|
||||
def extract_review_assignment_data(teams=None, reviewers=None, time_from=None, time_to=None, ordering=None):
|
||||
"""Yield data on each review assignment, sorted by (*ordering, assigned_on)
|
||||
for easy use with itertools.groupby. Valid entries in *ordering are "team" and "reviewer"."""
|
||||
|
||||
if ordering is None:
|
||||
ordering = []
|
||||
|
||||
filters = Q()
|
||||
|
||||
if teams:
|
||||
|
|
|
@ -133,7 +133,9 @@ def add_labeled_top_series_from_bins(chart_data, bins, limit):
|
|||
})
|
||||
|
||||
def document_stats(request, stats_type=None):
|
||||
def build_document_stats_url(stats_type_override=Ellipsis, get_overrides={}):
|
||||
def build_document_stats_url(stats_type_override=Ellipsis, get_overrides=None):
|
||||
if get_overrides is None:
|
||||
get_overrides={}
|
||||
kwargs = {
|
||||
"stats_type": stats_type if stats_type_override is Ellipsis else stats_type_override,
|
||||
}
|
||||
|
@ -762,7 +764,9 @@ def meeting_stats(request, num=None, stats_type=None):
|
|||
if num is not None:
|
||||
meeting = get_object_or_404(Meeting, number=num, type="ietf")
|
||||
|
||||
def build_meeting_stats_url(number=None, stats_type_override=Ellipsis, get_overrides={}):
|
||||
def build_meeting_stats_url(number=None, stats_type_override=Ellipsis, get_overrides=None):
|
||||
if get_overrides is None:
|
||||
get_overrides = {}
|
||||
kwargs = {
|
||||
"stats_type": stats_type if stats_type_override is Ellipsis else stats_type_override,
|
||||
}
|
||||
|
@ -1009,7 +1013,9 @@ def review_stats(request, stats_type=None, acronym=None):
|
|||
# and statistics type) are incorporated directly into the URL to
|
||||
# be a bit nicer.
|
||||
|
||||
def build_review_stats_url(stats_type_override=Ellipsis, acronym_override=Ellipsis, get_overrides={}):
|
||||
def build_review_stats_url(stats_type_override=Ellipsis, acronym_override=Ellipsis, get_overrides=None):
|
||||
if get_overrides is None:
|
||||
get_overrides = {}
|
||||
kwargs = {
|
||||
"stats_type": stats_type if stats_type_override is Ellipsis else stats_type_override,
|
||||
}
|
||||
|
|
|
@ -405,8 +405,12 @@ def send_mail_mime(request, to, frm, subject, msg, cc=None, extra=None, toUser=F
|
|||
|
||||
return msg
|
||||
|
||||
def parse_preformatted(preformatted, extra={}, override={}):
|
||||
def parse_preformatted(preformatted, extra=None, override=None):
|
||||
"""Parse preformatted string containing mail with From:, To:, ...,"""
|
||||
if extra is None:
|
||||
extra = {}
|
||||
if override is None:
|
||||
override = {}
|
||||
assert isinstance(preformatted, str)
|
||||
msg = message_from_bytes(preformatted.encode('utf-8'))
|
||||
msg.set_charset('UTF-8')
|
||||
|
@ -458,19 +462,26 @@ def parse_preformatted(preformatted, extra={}, override={}):
|
|||
assertion('len(list(set(v))) == len(v)')
|
||||
return (msg, extra, bcc)
|
||||
|
||||
def send_mail_preformatted(request, preformatted, extra={}, override={}):
|
||||
def send_mail_preformatted(request, preformatted, extra=None, override=None):
|
||||
"""Parse preformatted string containing mail with From:, To:, ...,
|
||||
and send it through the standard IETF mail interface (inserting
|
||||
extra headers as needed)."""
|
||||
|
||||
if extra is None:
|
||||
extra = {}
|
||||
if override is None:
|
||||
override = {}
|
||||
|
||||
(msg, extra, bcc) = parse_preformatted(preformatted, extra, override)
|
||||
txt = msg.get_payload()
|
||||
send_mail_text(request, msg['To'], msg["From"], msg["Subject"], txt, extra=extra, bcc=bcc)
|
||||
return msg
|
||||
|
||||
def send_mail_message(request, message, extra={}):
|
||||
def send_mail_message(request, message, extra=None):
|
||||
"""Send a Message object."""
|
||||
# note that this doesn't handle MIME messages at the moment
|
||||
if extra is None:
|
||||
extra = {}
|
||||
assertion('isinstance(message.to, str) and isinstance(message.cc, str) and isinstance(message.bcc, str)')
|
||||
|
||||
e = extra.copy()
|
||||
|
|
|
@ -157,7 +157,9 @@ class Command(DumpdataCommand):
|
|||
yield obj
|
||||
|
||||
|
||||
def handle(self, filenames=[], **options):
|
||||
def handle(self, filenames=None, **options):
|
||||
if filenames is None:
|
||||
filenames = []
|
||||
self.verbosity = int(options.get('verbosity'))
|
||||
format = options['format']
|
||||
indent = options['indent']
|
||||
|
|
|
@ -1036,11 +1036,14 @@ class IetfTestRunner(DiscoverRunner):
|
|||
test_paths = [ os.path.join(*app.split('.')) for app in test_apps ]
|
||||
return test_apps, test_paths
|
||||
|
||||
def run_tests(self, test_labels, extra_tests=[], **kwargs):
|
||||
def run_tests(self, test_labels, extra_tests=None, **kwargs):
|
||||
global old_destroy, old_create, test_database_name, template_coverage_collection, code_coverage_collection, url_coverage_collection
|
||||
from django.db import connection
|
||||
from ietf.doc.tests import TemplateTagTest
|
||||
|
||||
if extra_tests is None:
|
||||
extra_tests=[]
|
||||
|
||||
# Tests that involve switching back and forth between the real
|
||||
# database and the test database are way too dangerous to run
|
||||
# against the production database
|
||||
|
|
|
@ -67,7 +67,7 @@ class SMTPTestServer(smtpd.SMTPServer):
|
|||
#channel = SMTPTestChannel(self, conn, addr)
|
||||
SMTPTestChannel(self, conn, addr)
|
||||
|
||||
def process_message(self, peer, mailfrom, rcpttos, data, mail_options=[], rcpt_options=[]):
|
||||
def process_message(self, peer, mailfrom, rcpttos, data, mail_options=None, rcpt_options=None):
|
||||
self.inbox.append(data)
|
||||
|
||||
|
||||
|
|
|
@ -110,7 +110,7 @@ def format_addresses(addresses, header_name=None, charset=None):
|
|||
return header
|
||||
|
||||
|
||||
def build_mail(text, html=None, attachments=[], embeddeds=[]):
|
||||
def build_mail(text, html=None, attachments=None, embeddeds=None):
|
||||
"""
|
||||
Generate the core of the email message regarding the parameters.
|
||||
The structure of the MIME email may vary, but the general one is as follow::
|
||||
|
@ -184,6 +184,11 @@ def build_mail(text, html=None, attachments=[], embeddeds=[]):
|
|||
--===limit1==--
|
||||
"""
|
||||
|
||||
if attachments is None:
|
||||
attachments = []
|
||||
if embeddeds is None:
|
||||
embeddeds = []
|
||||
|
||||
main=text_part=html_part=None
|
||||
if text:
|
||||
content, charset=text
|
||||
|
@ -234,7 +239,7 @@ def build_mail(text, html=None, attachments=[], embeddeds=[]):
|
|||
|
||||
return main
|
||||
|
||||
def complete_mail(message, sender, recipients, subject, default_charset, cc=[], bcc=[], message_id_string=None, date=None, headers=[]):
|
||||
def complete_mail(message, sender, recipients, subject, default_charset, cc=None, bcc=None, message_id_string=None, date=None, headers=None):
|
||||
"""
|
||||
Fill in the From, To, Cc, Subject, Date and Message-Id I{headers} of
|
||||
one existing message regarding the parameters.
|
||||
|
@ -312,6 +317,13 @@ def complete_mail(message, sender, recipients, subject, default_charset, cc=[],
|
|||
else:
|
||||
return address
|
||||
|
||||
if cc is None:
|
||||
cc=[]
|
||||
if bcc is None:
|
||||
bcc=[]
|
||||
if headers is None:
|
||||
headers=[]
|
||||
|
||||
mail_from=getaddr(sender[1])
|
||||
rcpt_to=list(map(getaddr, recipients))
|
||||
rcpt_to.extend(list(map(getaddr, cc)))
|
||||
|
@ -341,7 +353,7 @@ def complete_mail(message, sender, recipients, subject, default_charset, cc=[],
|
|||
|
||||
return payload, mail_from, rcpt_to, msg_id
|
||||
|
||||
def compose_mail(sender, recipients, subject, default_charset, text, html=None, attachments=[], embeddeds=[], cc=[], bcc=[], message_id_string=None, date=None, headers=[]):
|
||||
def compose_mail(sender, recipients, subject, default_charset, text, html=None, attachments=None, embeddeds=None, cc=None, bcc=None, message_id_string=None, date=None, headers=None):
|
||||
"""
|
||||
Compose an email regarding the arguments. Call L{build_mail()} and
|
||||
L{complete_mail()} at once.
|
||||
|
@ -356,6 +368,17 @@ def compose_mail(sender, recipients, subject, default_charset, text, html=None,
|
|||
|
||||
>>> payload, mail_from, rcpt_to, msg_id=compose_mail((u'Me', 'me@foo.com'), [(u'Him', 'him@bar.com')], u'the subject', 'iso-8859-1', ('Hello world', 'us-ascii'), attachments=[('attached', 'text', 'plain', 'text.txt', 'us-ascii')])
|
||||
"""
|
||||
if attachments is None:
|
||||
attachments=[]
|
||||
if embeddeds is None:
|
||||
embeddeds=[]
|
||||
if cc is None:
|
||||
cc=[]
|
||||
if bcc is None:
|
||||
bcc = []
|
||||
if headers is None:
|
||||
headers=[]
|
||||
|
||||
message=build_mail(text, html, attachments, embeddeds)
|
||||
return complete_mail(message, sender, recipients, subject, default_charset, cc, bcc, message_id_string, date, headers)
|
||||
|
||||
|
|
Loading…
Reference in a new issue