Skip to content

Commit

Permalink
Merge remote-tracking branch 'benoitc/pr/3124' into unmaintained
Browse files Browse the repository at this point in the history
  • Loading branch information
pajod committed May 21, 2024
2 parents 365990a + 7fbeb07 commit 9fdf544
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 10 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ details.

* [PR #3214: document server hooks](https://github.com/benoitc/gunicorn/pull/3214)
* [PR #3127: refactor socket wrappers](https://github.com/benoitc/gunicorn/pull/3127)
* [PR #3124: multiple --reload-extra-file](https://github.com/benoitc/gunicorn/pull/3124)
* [PR #3134: CI test older dependencies](https://github.com/benoitc/gunicorn/pull/3134)
* [PR #3192: fix 22.0 regression: `SCRIPT_NAME` forbidden](https://github.com/benoitc/gunicorn/pull/3192)
* [PR #3191: correct log severity](https://github.com/benoitc/gunicorn/pull/3191)
Expand Down
18 changes: 14 additions & 4 deletions gunicorn/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import copy
import inspect
import ipaddress
import itertools
import os
import re
import shlex
Expand Down Expand Up @@ -949,17 +950,26 @@ class ReloadExtraFiles(Setting):
section = "Debugging"
cli = ["--reload-extra-file"]
meta = "FILES"
validator = validate_list_of_existing_files
default = []
nargs = '+'
desc = """\
Reload when these files appear modified. Can be used either on its own or to extend
the :ref:`reload` option to also watch and reload on additional files
(e.g., templates, configurations, specifications, etc.).
Behaviour changed in 22.1.0: No longer implicitly depends on :ref:`reload` enabled.
.. versionadded:: 19.8
"""
.. versionchanged:: 22.1.0
No longer implicitly depends on :ref:`reload` enabled.
.. versionchanged:: 22.0
It is now possible to pass multiple arguments to each instance of the flag.
Hint: if passed last, you may need to separate options and arguments using double dash:
``gunicon --reload-extra-file file1 file2 -- example:wsgiapp``
"""

# Once Python 3.8 is required, the `extend` makes this overload unnecessary
def validator(val):
flat = list(itertools.chain.from_iterable(val))
return validate_list_of_existing_files(flat)


class Spew(BoolSetting):
Expand Down
30 changes: 30 additions & 0 deletions tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,36 @@ def nworkers_changed_3(server, new_value, old_value):
assert c.nworkers_changed(1, 2, 3) == 3


def test_reload_extra_files(tmp_path):
try:
tmp_path.mkdir()
except FileExistsError:
pass

foo_path = tmp_path / 'foo'
bar_path = tmp_path / 'bar'
baz_path = tmp_path / 'baz'
foo_path.touch()
bar_path.touch()
baz_path.touch()

args = ["prog_name", "--config", cfg_file()]
with AltArgs(args):
app = NoConfigApp()
assert app.cfg.reload_extra_files == []

args.extend(['--reload-extra-file', str(foo_path)])
with AltArgs(args):
app = NoConfigApp()
print(app.cfg.reload_extra_files)
assert app.cfg.reload_extra_files == [str(foo_path)]

args.extend(['--reload-extra-file', str(bar_path), str(baz_path)])
with AltArgs(args):
app = NoConfigApp()
assert app.cfg.reload_extra_files == [str(foo_path), str(bar_path), str(baz_path)]


def test_statsd_host():
c = config.Config()
assert c.statsd_host is None
Expand Down
30 changes: 24 additions & 6 deletions tests/test_e2e.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@
logging.basicConfig()
logger = logging.getLogger(__name__)
import syntax_ok
def wsgiapp(environ_, start_response):
# print("stdout from app", file=sys.stdout)
print("stderr from app", file=sys.stderr)
Expand All @@ -107,13 +109,18 @@ def wsgiapp(environ_, start_response):
return iter([body])
"""

PY_BAD_CONFIG = """
PY_VALID_CONFIG = """
def post_fork(a_, b_):
pass # import syntax_error
def post_worker_init(_):
pass # raise KeyboardInterrupt
"""

PY_GOOD_IMPORT = """
def good_method():
pass
"""

PY_BAD_IMPORT = """
def bad_method():
syntax_error:
Expand All @@ -136,6 +143,7 @@ def bad_method():
# os.kill(os.getppid(), signal.SIGTERM)
# sys.exit(3)
import syntax_ok
import syntax_error
def wsgiapp(environ_, start_response_):
Expand Down Expand Up @@ -180,27 +188,37 @@ def __init__(
"--graceful-timeout=%d" % (GRACEFUL_TIMEOUT,),
"--on-fatal={}".format("world-readable" if public_traceback else "quiet"),
# "--reload",
"--reload-extra=%s" % self.py_path,
# sandwich the one we care for: verify multiple instances of --reload-extra
"--reload-extra",
"{}".format(self.temp_path / "syntax_ok.py"),
f"{self.py_path}",
"{}".format(self.temp_path / "syntax_ok.py"),
# FIXME: not utilizing inotify reduces test coverage
"--reload-engine=poll",
"--bind=%s" % server_bind,
"--reuse-port",
"--",
f"{APP_BASENAME}:{APP_APPNAME}",
]

def write_bad(self):
with open(self.conf_path, "w+") as f:
f.write(PY_BAD_CONFIG)
with open(self.temp_path / "syntax_error.py", "w+") as f:
f.write(PY_BAD_IMPORT)
with open(self.py_path, "w+") as f:
f.write(PY_BAD)

def write_ok(self):
with open(self.py_path, "w+") as f:
f.write(PY_OK)

def _write_support(self):
with open(self.conf_path, "w+") as f:
f.write(PY_VALID_CONFIG)
with open(self.temp_path / "syntax_error.py", "w+") as f:
f.write(PY_BAD_IMPORT)
with open(self.temp_path / "syntax_ok.py", "w+") as f:
f.write(PY_GOOD_IMPORT)

def __enter__(self):
self._write_support()
self._write_initial()
self.run()
return self
Expand Down

0 comments on commit 9fdf544

Please sign in to comment.