From 8500a8444ad8d1ecd1ffc6ff53f9c8d635417124 Mon Sep 17 00:00:00 2001 From: Sergei Ozeranskii Date: Fri, 16 Jun 2023 06:24:44 +0800 Subject: [PATCH] Allow gunicorn timeout be set in pcconfig.py (#1193) --- CONTRIBUTING.md | 2 +- pynecone/config.py | 9 ++++++--- pynecone/constants.py | 2 +- pyproject.toml | 2 +- tests/test_config.py | 41 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 50 insertions(+), 6 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a5309f899..ab2cac2e1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,7 +8,7 @@ To navigate our codebase with confidence, see [Pynecone Docs](https://pynecone.i - Have a question? Want to discuss a feature? [Start a discussion](https://github.com/pynecone-io/pynecone/discussions) - We welome and discussions and questions. We want to make sure that Pynecone is the best it can be, and we can't do that without your help. + We welcome any discussions and questions. We want to make sure that Pynecone is the best it can be, and we can't do that without your help. ### Issues diff --git a/pynecone/config.py b/pynecone/config.py index 861e3beba..67889ac98 100644 --- a/pynecone/config.py +++ b/pynecone/config.py @@ -174,7 +174,7 @@ class Config(Base): # Additional frontend packages to install. frontend_packages: List[str] = [] - # The Admin Dash + # The Admin Dash. admin_dash: Optional[AdminDash] = None # Backend transport methods. @@ -191,12 +191,15 @@ class Config(Base): # The maximum size of a message when using the polling backend transport. polling_max_http_buffer_size: Optional[int] = constants.POLLING_MAX_HTTP_BUFFER_SIZE - # Dotenv file path + # Dotenv file path. env_path: Optional[str] = constants.DOT_ENV_FILE - # Whether to override OS environment variables + # Whether to override OS environment variables. override_os_envs: Optional[bool] = True + # Timeout when launching the gunicorn server. + timeout: int = constants.TIMEOUT + def __init__(self, *args, **kwargs): """Initialize the config values. diff --git a/pynecone/constants.py b/pynecone/constants.py index 32fe398ac..36681a20f 100644 --- a/pynecone/constants.py +++ b/pynecone/constants.py @@ -106,7 +106,7 @@ INSTALL_BUN = f"curl -fsSL https://bun.sh/install | bash -s -- bun-v{MAX_BUN_VER # Default host in dev mode. BACKEND_HOST = get_value("BACKEND_HOST", "0.0.0.0") # The default timeout when launching the gunicorn server. -TIMEOUT = 120 +TIMEOUT = get_value("TIMEOUT", 120, type_=int) # The command to run the backend in production mode. RUN_BACKEND_PROD = f"gunicorn --worker-class uvicorn.workers.UvicornH11Worker --preload --timeout {TIMEOUT} --log-level critical".split() RUN_BACKEND_PROD_WINDOWS = f"uvicorn --timeout-keep-alive {TIMEOUT}".split() diff --git a/pyproject.toml b/pyproject.toml index 6627a4e26..239743b8e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -65,7 +65,7 @@ pre-commit = {version = "^3.2.1", python = ">=3.8,<4.0"} pc = "pynecone.pc:main" [build-system] -requires = ["poetry-core>=1.0.0"] +requires = ["poetry-core>=1.5.1"] build-backend = "poetry.core.masonry.api" [tool.pyright] diff --git a/tests/test_config.py b/tests/test_config.py index 2323eb601..e137d8abf 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -6,6 +6,7 @@ import pytest import pynecone as pc from pynecone import constants from pynecone.config import DBConfig +from pynecone.constants import get_value @pytest.fixture @@ -34,6 +35,21 @@ def config_empty_db_url_values(base_config_values): """ base_config_values["db_url"] = None yield base_config_values + os.environ.pop("DB_URL", None) + + +@pytest.fixture +def config_none_db_url_values(base_config_values): + """Create config values with None (string) db_url. + + Args: + base_config_values: Base config values fixture. + + Yields: + Config values + """ + base_config_values["db_url"] = "None" + yield base_config_values os.environ.pop("DB_URL") @@ -68,6 +84,16 @@ def test_empty_db_url(config_empty_db_url_values): assert config.db_url is None +def test_none_db_url(config_none_db_url_values): + """Test that db_url is set 'None' (string) assigned if an 'None' (string) value is defined. + + Args: + config_none_db_url_values: Config values with None (string) db_url. + """ + config = pc.Config(**config_none_db_url_values) + assert config.db_url == "None" + + def test_db_url_precedence(base_config_values, sqlite_db_config_values): """Test that db_url is not overwritten when db_url is defined. @@ -92,3 +118,18 @@ def test_db_url_from_db_config(config_no_db_url_values, sqlite_db_config_values) config_no_db_url_values["db_config"] = db_config config = pc.Config(**config_no_db_url_values) assert config.db_url == db_config.get_url() + + +@pytest.mark.parametrize( + "key, value, expected_value_type_in_config", + ( + ("TIMEOUT", "1", int), + ("CORS_ALLOWED_ORIGINS", "[1, 2, 3]", list), + ("DB_NAME", "dbname", str), + ), +) +def test_get_value(monkeypatch, key, value, expected_value_type_in_config): + monkeypatch.setenv(key, value) + casted_value = get_value(key, type_=expected_value_type_in_config) + + assert isinstance(casted_value, expected_value_type_in_config)