From 159e7949f1693f51d076a7d1b7046e6c6150cc85 Mon Sep 17 00:00:00 2001 From: Nikhil Rao Date: Sun, 20 Nov 2022 16:12:46 -0800 Subject: [PATCH] Create config class (#8) --- pynecone/.templates/app/tutorial.py | 15 ++++++++++----- pynecone/__init__.py | 2 ++ pynecone/app.py | 6 +++--- pynecone/compiler/templates.py | 11 +++++------ pynecone/config.py | 29 ++++++++++++++++++++++++++++ pynecone/constants.py | 6 ++++-- pynecone/model.py | 4 ++-- pynecone/pc.py | 12 ++++++------ pynecone/utils.py | 30 ++++++++++++++++++----------- 9 files changed, 80 insertions(+), 35 deletions(-) create mode 100644 pynecone/config.py diff --git a/pynecone/.templates/app/tutorial.py b/pynecone/.templates/app/tutorial.py index 4a93a3a0a..55ec6a503 100644 --- a/pynecone/.templates/app/tutorial.py +++ b/pynecone/.templates/app/tutorial.py @@ -1,10 +1,10 @@ """Welcome to Pynecone! This file outlines the steps to create a basic app.""" -import pcconfig +from pcconfig import config import pynecone as pc docs_url = "https://pynecone.io/docs/getting-started/introduction" -filename = f"{pcconfig.APP_NAME}/{pcconfig.APP_NAME}.py" +filename = f"{config.app_name}/{config.app_name}.py" class State(pc.State): @@ -16,17 +16,22 @@ class State(pc.State): def index(): return pc.center( pc.vstack( - pc.heading("Welcome to Pynecone!"), - pc.box("Get started by editing ", pc.code(filename)), + pc.heading("Welcome to Pynecone!", font_size="2em"), + pc.box("Get started by editing ", pc.code(filename, font_size="1em")), pc.link( "Check out our docs!", href=docs_url, border="0.1em solid", padding="0.5em", border_radius="0.5em", + _hover={ + "color": "rgb(107,99,246)", + }, ), + spacing="1.5em", + font_size="2em", ), - padding="5em", + padding_top="10%", ) diff --git a/pynecone/__init__.py b/pynecone/__init__.py index b4b3c0dbc..a619370ad 100644 --- a/pynecone/__init__.py +++ b/pynecone/__init__.py @@ -6,6 +6,8 @@ Anything imported here will be available in the default Pynecone import as `pc.* from .app import App from .base import Base from .components import * +from .config import Config +from .constants import Env from .event import console_log, redirect, window_alert from .model import Model, session from .state import ComputedVar as var diff --git a/pynecone/app.py b/pynecone/app.py index 0d0aa5549..cf0c75b0c 100644 --- a/pynecone/app.py +++ b/pynecone/app.py @@ -215,15 +215,15 @@ class App(Base): def compile(self, ignore_env: bool = False): """Compile the app and output it to the pages folder. - If the pcconfig environment is set to production, the app will + If the config environment is set to production, the app will not be compiled. Args: - ignore_env: Whether to ignore the pcconfig environment. + ignore_env: Whether to ignore the config environment. """ # Get the env mode. config = utils.get_config() - if not ignore_env and config.ENV != constants.Env.DEV.value: + if not ignore_env and config.env != constants.Env.DEV: print("Skipping compilation in non-dev mode.") return diff --git a/pynecone/compiler/templates.py b/pynecone/compiler/templates.py index d4bb08e54..d785ca4aa 100644 --- a/pynecone/compiler/templates.py +++ b/pynecone/compiler/templates.py @@ -6,13 +6,12 @@ from pynecone import constants from pynecone.utils import join # Template for the Pynecone config file. -PCCONFIG = f"""# The Pynecone configuration file. +PCCONFIG = f"""import pynecone as pc -APP_NAME = "{{app_name}}" -API_HOST = "http://localhost:8000" -BUN_PATH = "$HOME/.bun/bin/bun" -ENV = "{constants.Env.DEV.value}" -DB_URI = "sqlite:///{constants.DB_NAME}" + +config = pc.Config( + app_name="{{app_name}}", +) """ # Javascript formatting. diff --git a/pynecone/config.py b/pynecone/config.py new file mode 100644 index 000000000..ec46d28d2 --- /dev/null +++ b/pynecone/config.py @@ -0,0 +1,29 @@ +from typing import Optional + +from pynecone import constants +from pynecone.base import Base + + +class Config(Base): + """A Pynecone config.""" + + # The name of the app. + app_name: str + + # The backend API url. + api_url: str = "http://localhost:8000" + + # The database url. + db_url: str = f"sqlite:///{constants.DB_NAME}" + + # The redis url. + redis_url: Optional[str] = None + + # The deploy url. + deploy_url: Optional[str] = None + + # The environment mode. + env: constants.Env = constants.Env.DEV + + # The path to the bun executable. + bun_path: str = "$HOME/.bun/bin/bun" diff --git a/pynecone/constants.py b/pynecone/constants.py index 735da0624..4c3d04211 100644 --- a/pynecone/constants.py +++ b/pynecone/constants.py @@ -134,5 +134,7 @@ class Endpoint(Enum): Returns: The full URL for the endpoint. """ - pcconfig = __import__(CONFIG_MODULE) - return "".join([pcconfig.API_HOST, str(self)]) + from pynecone import utils + + config = utils.get_config() + return "".join([config.api_url, str(self)]) diff --git a/pynecone/model.py b/pynecone/model.py index baec3da1b..1171beb31 100644 --- a/pynecone/model.py +++ b/pynecone/model.py @@ -12,8 +12,8 @@ def get_engine(): Returns: The database engine. """ - uri = utils.get_config().DB_URI - return sqlmodel.create_engine(uri, echo=False) + url = utils.get_config().db_url + return sqlmodel.create_engine(url, echo=False) class Model(Base, sqlmodel.SQLModel): diff --git a/pynecone/pc.py b/pynecone/pc.py index 138a93837..07b743c85 100644 --- a/pynecone/pc.py +++ b/pynecone/pc.py @@ -87,11 +87,11 @@ def deploy(dry_run: bool = False): dry_run: Whether to run a dry run. """ # Get the app config. - pcconfig = utils.get_config() - pcconfig.API_HOST = utils.get_production_backend_url() + config = utils.get_config() + config.api_url = utils.get_production_backend_url() - # Check if the deploy URI is set. - if not hasattr(pcconfig, "DEPLOY_URI"): + # Check if the deploy url is set. + if config.deploy_url is None: typer.echo("This feature is coming soon!") typer.echo("Join our waitlist to be notified: https://pynecone.io/waitlist") return @@ -106,8 +106,8 @@ def deploy(dry_run: bool = False): return # Deploy the app. - data = {"userId": pcconfig.USERNAME, "projectId": pcconfig.APP_NAME} - original_response = requests.get(pcconfig.DEPLOY_URI, params=data) + data = {"userId": config.username, "projectId": config.app_name} + original_response = requests.get(config.deploy_url, params=data) response = original_response.json() print("response", response) frontend = response["frontend_resources_url"] diff --git a/pynecone/utils.py b/pynecone/utils.py index bc380a35c..3383d14e7 100644 --- a/pynecone/utils.py +++ b/pynecone/utils.py @@ -36,6 +36,7 @@ from pynecone import constants if TYPE_CHECKING: from pynecone.components.component import ImportDict + from pynecone.config import Config from pynecone.event import Event, EventHandler, EventSpec from pynecone.var import Var @@ -233,14 +234,19 @@ def which(program: str) -> Optional[str]: return shutil.which(program) -def get_config() -> Any: - """Get the default pcconfig. +def get_config() -> Config: + """Get the app config. Returns: - The default pcconfig. + The app config. """ sys.path.append(os.getcwd()) - return __import__(constants.CONFIG_MODULE) + try: + return __import__(constants.CONFIG_MODULE).config + except: + print(f"No {constants.CONFIG_MODULE} module found.") + print("Using default config.") + return Config(app_name="") def get_bun_path(): @@ -249,7 +255,7 @@ def get_bun_path(): Returns: The path to the bun executable. """ - return os.path.expandvars(get_config().BUN_PATH) + return os.path.expandvars(get_config().bun_path) def get_app() -> Any: @@ -259,7 +265,7 @@ def get_app() -> Any: The app based on the default config. """ config = get_config() - module = ".".join([config.APP_NAME, config.APP_NAME]) + module = ".".join([config.app_name, config.app_name]) app = __import__(module, fromlist=(constants.APP_VAR,)) return app @@ -364,8 +370,8 @@ def get_production_backend_url() -> str: """ config = get_config() return constants.PRODUCTION_BACKEND_URL.format( - username=config.USERNAME, - app_name=config.APP_NAME, + username=config.username, + app_name=config.app_name, ) @@ -861,8 +867,10 @@ def get_redis(): import redis config = get_config() - redis_host, redis_port = config.REDIS_HOST.split(":") - print("Using redis at", config.REDIS_HOST) - return redis.Redis(host=redis_host, port=redis_port, db=0) + if config.redis_url is None: + return None + redis_url, redis_port = config.redis_url.split(":") + print("Using redis at", config.redis_url) + return redis.Redis(host=redis_url, port=redis_port, db=0) except: return None