Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed #32813 -- Made development server display address after server bind. #14250

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
45 changes: 24 additions & 21 deletions django/core/management/commands/runserver.py
Expand Up @@ -108,22 +108,9 @@ def run(self, **options):
else:
self.inner_run(None, **options)

def inner_run(self, *args, **options):
# If an exception was silenced in ManagementUtility.execute in order
# to be raised in the child process, raise it now.
autoreload.raise_last_exception()

threading = options['use_threading']
# 'shutdown_message' is a stealth option.
shutdown_message = options.get('shutdown_message', '')
def _on_bind(self, server_name, server_port):
fmwviormv marked this conversation as resolved.
Show resolved Hide resolved
"""Display server name and port after server bind."""
quit_command = 'CTRL-BREAK' if sys.platform == 'win32' else 'CONTROL-C'

if not options['skip_checks']:
self.stdout.write('Performing system checks...\n\n')
self.check(display_num_errors=True)
# Need to check migrations here, so can't use the
# requires_migrations_check attribute.
self.check_migrations()
now = datetime.now().strftime('%B %d, %Y - %X')
self.stdout.write(now)
self.stdout.write((
Expand All @@ -135,23 +122,39 @@ def inner_run(self, *args, **options):
"settings": settings.SETTINGS_MODULE,
"protocol": self.protocol,
"addr": '[%s]' % self.addr if self._raw_ipv6 else self.addr,
"port": self.port,
"port": server_port,
"quit_command": quit_command,
})

def inner_run(self, *args, **options):
# If an exception was silenced in ManagementUtility.execute in order
# to be raised in the child process, raise it now.
autoreload.raise_last_exception()

threading = options['use_threading']
# 'shutdown_message' is a stealth option.
shutdown_message = options.get('shutdown_message', '')

if not options['skip_checks']:
self.stdout.write('Performing system checks...\n\n')
self.check(display_num_errors=True)
# Need to check migrations here, so can't use the
# requires_migrations_check attribute.
self.check_migrations()
try:
handler = self.get_handler(*args, **options)
run(self.addr, int(self.port), handler,
ipv6=self.use_ipv6, threading=threading, server_cls=self.server_cls)
ipv6=self.use_ipv6, threading=threading,
server_cls=self.server_cls, on_bind=self._on_bind)
except OSError as e:
# Use helpful error messages instead of ugly tracebacks.
ERRORS = {
errno.EACCES: "You don't have permission to access that port.",
errno.EADDRINUSE: "That port is already in use.",
errno.EADDRNOTAVAIL: "That IP address can't be assigned to.",
errno.EACCES: "You don't have permission to access port %(port)s.",
errno.EADDRINUSE: "Port %(port)s is already in use.",
errno.EADDRNOTAVAIL: "IP address %(addr)r can't be assigned to.",
Comment on lines +152 to +154
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could just use f-strings here:

Suggested change
errno.EACCES: "You don't have permission to access port %(port)s.",
errno.EADDRINUSE: "Port %(port)s is already in use.",
errno.EADDRNOTAVAIL: "IP address %(addr)r can't be assigned to.",
errno.EACCES: f"You don't have permission to access port {self.port}.",
errno.EADDRINUSE: f"Port {self.port} is already in use.",
errno.EADDRNOTAVAIL: f"IP address {self.addr!r} can't be assigned to.",

(I know this means generating three strings when we'll only show one, but it isn't really going to add any significant overhead.)

}
try:
error_text = ERRORS[e.errno]
error_text = ERRORS[e.errno] % dict(addr=self.addr, port=self.port)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we don't go with the above, this should at least use a dict literal:

Suggested change
error_text = ERRORS[e.errno] % dict(addr=self.addr, port=self.port)
error_text = ERRORS[e.errno] % {'addr': self.addr, 'port': self.port}

except KeyError:
error_text = e
self.stderr.write("Error: %s" % error_text)
Expand Down
13 changes: 10 additions & 3 deletions django/core/servers/basehttp.py
Expand Up @@ -219,12 +219,19 @@ def handle_one_request(self):
handler.run(self.server.get_app())


def run(addr, port, wsgi_handler, ipv6=False, threading=False, server_cls=WSGIServer):
def run(addr, port, wsgi_handler, ipv6=False, threading=False,
server_cls=WSGIServer, on_bind=None):
server_address = (addr, port)
cls_dict = {}
if on_bind is not None:
def server_bind(self):
server_cls.server_bind(self)
on_bind(self.server_name, self.server_port)
cls_dict['server_bind'] = server_bind
if threading:
httpd_cls = type('WSGIServer', (socketserver.ThreadingMixIn, server_cls), {})
httpd_cls = type('WSGIServer', (socketserver.ThreadingMixIn, server_cls), cls_dict)
else:
httpd_cls = server_cls
httpd_cls = type('WSGIServer', (server_cls,), cls_dict)
Comment on lines 231 to +234
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we simplify this?

    bases = (socketserver.ThreadingMixIn, server_cls) if threading else (server_cls,)
    httpd_cls = type('WSGIServer', bases, cls_dict)

httpd = httpd_cls(server_address, WSGIRequestHandler, ipv6=ipv6)
if threading:
# ThreadingMixIn.daemon_threads indicates how threads will behave on an
Expand Down