#36163: Change mail APIs to (mostly) keyword-only parameters
-------------------------------------+-------------------------------------
     Reporter:  Mike Edmunds         |                    Owner:  Chaitanya
         Type:                       |  Rahalkar
  Cleanup/optimization               |                   Status:  assigned
    Component:  Core (Mail)          |                  Version:  dev
     Severity:  Normal               |               Resolution:
     Keywords:                       |             Triage Stage:  Accepted
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------

Old description:

> Several of Django's email APIs have extremely long parameter lists. This
> complicates adding—and documenting—new parameters where they would
> logically fit, as the existing positional order must be maintained for
> compatibility.
>
> This ticket proposes changing the public django.core.mail APIs to require
> keyword-only arguments, starting at the first boolean or "uncommon"
> parameter. That's `fail_silently` for the functional APIs, and `bcc` for
> the class constructors (specifics below).
>
> Forum discussion: https://forum.djangoproject.com/t/change-send-mail-and-
> emailmessage-to-kwargs-only/38239
>
> Consensus in the forum was that this change should be made '''without a
> deprecation period.''' Existing code that uses positional arguments for
> the affected params would raise a TypeError after the change.
>
> A quick (and by no means exhaustive) GitHub code search suggests a lot of
> existing code already uses keyword arguments for these params, but that
> positional arguments are common for the earlier ones. One potential
> exception is custom EmailMultiAlternatives subclasses. (More details in
> the forum.)
>
> (This originally came up in the context of #35514, which must add a new
> `provider` parameter to several existing APIs—including the
> "[https://github.com/django/django/blob/8eca4077f60fa0705ecfd9437c9ceaeef7a3808b/django/core/mail/__init__.py#L78-L79
> frozen]" send_mail() and send_mass_mail() functions, and the EmailMessage
> class with its [https://docs.djangoproject.com/en/5.1/topics/email
> /#emailmessage-
> objects:~:text=in%20the%20given%20order%2C%20if%20positional%20arguments%20are%20used
> documented parameter ordering].)
>
> === Proposed changes ===
>
> This change would add `*,`s where indicated below. All parameters after
> the `*,` would become keyword only.
>
> {{{#!python
> # django/core/mail/__init__.py
> def get_connection(
>     backend=None,
>     *,
>     fail_silently=False, **kwds):
>
> def send_mail(
>     subject, message, from_email, recipient_list,
>     *,
>     fail_silently=False, auth_user=None, auth_password=None,
>     connection=None, html_message=None):
>
> def send_mass_mail(
>     datatuple,
>     *,
>     fail_silently=False, auth_user=None, auth_password=None,
>     connection=None):
>
> def mail_admins(
>     subject, message,
>     *,
>     fail_silently=False, connection=None, html_message=None):
>
> def mail_managers(
>     subject, message,
>     *,
>     fail_silently=False, connection=None, html_message=None):
> }}}
>
> {{{#!python
> # django/core/mail/message.py
> class EmailMessage:
>     def __init__(
>         self,
>         subject="", body="", from_email=None, to=None,
>         *,
>         bcc=None, connection=None,
>         attachments=None, headers=None,
>         cc=None, reply_to=None):
>

> class EmailMultiAlternatives(EmailMessage):
>     def __init__(
>         self,
>         subject="", body="", from_email=None, to=None,
>         *,
>         bcc=None, connection=None,
>         attachments=None, headers=None,
>         alternatives=None,
>         cc=None, reply_to=None):
>
> }}}

New description:

 Several of Django's email APIs have extremely long parameter lists. This
 complicates adding—and documenting—new parameters where they would
 logically fit, as the existing positional order must be maintained for
 compatibility.

 This ticket proposes changing the public django.core.mail APIs to require
 keyword-only arguments, starting at the first boolean or "uncommon"
 parameter. That's `fail_silently` for the functional APIs, and `bcc` for
 the class constructors (specifics below).

 Forum discussion: https://forum.djangoproject.com/t/change-send-mail-and-
 emailmessage-to-kwargs-only/38239

 ~~Consensus in the forum was that this change should be made '''without a
 deprecation period.''' Existing code that uses positional arguments for
 the affected params would raise a TypeError after the change.~~ __During a
 standard deprecation period, the affected parameters would be accepted as
 either positional or keyword arguments, but using posargs would raise a
 deprecation warning. After the deprecation period, continuing to use
 posargs for those params would result in Python's usual TypeError.__
 [Edit: further forum discussion clarified need to follow the deprecation
 process.]

 A quick (and by no means exhaustive) GitHub code search suggests a lot of
 existing code already uses keyword arguments for these params, but that
 positional arguments are common for the earlier ones. One potential
 exception is custom EmailMultiAlternatives subclasses. (More details in
 the forum.)

 (This originally came up in the context of #35514, which must add a new
 `provider` parameter to several existing APIs—including the
 
"[https://github.com/django/django/blob/8eca4077f60fa0705ecfd9437c9ceaeef7a3808b/django/core/mail/__init__.py#L78-L79
 frozen]" send_mail() and send_mass_mail() functions, and the EmailMessage
 class with its [https://docs.djangoproject.com/en/5.1/topics/email
 /#emailmessage-
 
objects:~:text=in%20the%20given%20order%2C%20if%20positional%20arguments%20are%20used
 documented parameter ordering].)

 === Proposed changes ===

 This change would add `*,`s where indicated below. All parameters after
 the `*,` would become keyword only.

 {{{#!python
 # django/core/mail/__init__.py
 def get_connection(
     backend=None,
     *,
     fail_silently=False, **kwds):

 def send_mail(
     subject, message, from_email, recipient_list,
     *,
     fail_silently=False, auth_user=None, auth_password=None,
     connection=None, html_message=None):

 def send_mass_mail(
     datatuple,
     *,
     fail_silently=False, auth_user=None, auth_password=None,
     connection=None):

 def mail_admins(
     subject, message,
     *,
     fail_silently=False, connection=None, html_message=None):

 def mail_managers(
     subject, message,
     *,
     fail_silently=False, connection=None, html_message=None):
 }}}

 {{{#!python
 # django/core/mail/message.py
 class EmailMessage:
     def __init__(
         self,
         subject="", body="", from_email=None, to=None,
         *,
         bcc=None, connection=None,
         attachments=None, headers=None,
         cc=None, reply_to=None):


 class EmailMultiAlternatives(EmailMessage):
     def __init__(
         self,
         subject="", body="", from_email=None, to=None,
         *,
         bcc=None, connection=None,
         attachments=None, headers=None,
         alternatives=None,
         cc=None, reply_to=None):

 }}}

--
Comment (by Mike Edmunds):

 Updated description to require a deprecation period based on additional
 forum feedback (and per the original proposal in the forum).

 Opened https://github.com/django/django/pull/19145 with an implementation
 of an `@deprecate_posargs` decorator to simplify the deprecation process.
-- 
Ticket URL: <https://code.djangoproject.com/ticket/36163#comment:3>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/django-updates/01070194e1d66fc2-bf186d01-24ad-497a-b8ef-81cd788fbaf9-000000%40eu-central-1.amazonses.com.

Reply via email to