diff --git a/.agents/skills/fastapi-startkit-best-practices/SKILL.md b/.agents/skills/fastapi-startkit-best-practices/SKILL.md deleted file mode 100644 index e69de29b..00000000 diff --git a/.agents/skills/fastapi-startkit-best-practices/rules/contribution.md b/.agents/skills/fastapi-startkit-best-practices/rules/contribution.md deleted file mode 100644 index 320a4fb7..00000000 --- a/.agents/skills/fastapi-startkit-best-practices/rules/contribution.md +++ /dev/null @@ -1,12 +0,0 @@ -# Contribution - -This repository contains several packages and examples that to support the fastapi_starkit. The main components of fastapi_startkit stay inside `fastapi_startkit/src` directory and docs are available in `fastapi_startkit.github.io`, examples in examples and starter application in application. - -## Fastapi_startkit Contribution Guides -1. This is the core components of this starter kit/framework, while making change, or adding any feature, or fixing anything in examples, application or even in the starterkit, always consider not to CHANGE `fastapi_startkit/src` unless Explict necessary. -2. If there is an absolute necessary to make any changes in the `fastapi_startkit/src`, please consider any alternatives approaches, or any potential impacts on the other sides of the components, and if it's not possbile unless making change, consider creating a document explaining the chnages that you are going to make, and it's potential affects and impacts, and submit for review. - -3. Add potential test cases that can be used to validate the changes made to the codebase. Consider looking into the existing code structure, fixtures, database structures, etc., before writing any - test cases. -4. You are allowed to run test suite and self-verify if the fixes are correct or not, but don't try to wipe the database, nor any destructive operations that could break the system or loss data. - To run the tests, go the `fastapi_startkit` directory and run with `uv run pytest {path}`, to run startkit's component-related tests. diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 21d3b308..4dbd792e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -44,6 +44,10 @@ jobs: working-directory: example/config-app run: uv sync + - name: Copy .env.example to .env (config-app) + working-directory: example/config-app + run: cp .env.example .env + - name: Run tests (config-app) working-directory: example/config-app run: uv run pytest tests/ -v diff --git a/.gitignore b/.gitignore index e180872d..e0930bcd 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,5 @@ fastapi_startkit/dist fastapi_startkit.github.io.git laravel-repo application +.agents +.uv_cache diff --git a/bin/test.sh b/bin/test.sh index 31298042..7cfbdece 100755 --- a/bin/test.sh +++ b/bin/test.sh @@ -21,7 +21,7 @@ echo "" echo "============================================================" echo " Running: fastapi_startkit package tests" echo "============================================================" -(cd "$ROOT/fastapi_startkit" && uv run pytest) +(cd "$ROOT/fastapi_startkit" && uv run pytest tests) echo "" echo "============================================================" @@ -33,4 +33,4 @@ echo "" echo "============================================================" echo " Running: example/database-app tests" echo "============================================================" -(cd "$ROOT/example/database-app" && uv run pytest) \ No newline at end of file +(cd "$ROOT/example/database-app" && uv run pytest) diff --git a/example/config-app/.env.example b/example/config-app/.env.example new file mode 100644 index 00000000..fe4bbb09 --- /dev/null +++ b/example/config-app/.env.example @@ -0,0 +1,5 @@ +APP_ENV=development + +REDIS_HOST=host.default +REDIS_PORT=0000 +REDIS_DB=0 diff --git a/example/config-app/uv.lock b/example/config-app/uv.lock index b4cec0e5..4404d604 100644 --- a/example/config-app/uv.lock +++ b/example/config-app/uv.lock @@ -198,6 +198,7 @@ dev = [ { name = "dumpdie", specifier = ">=1.5.0" }, { name = "pytest", specifier = ">=9.0.3" }, { name = "pytest-asyncio", specifier = ">=1.3.0" }, + { name = "ruff", specifier = ">=0.9.0" }, { name = "twine", specifier = ">=6.2.0" }, ] diff --git a/example/database-app/uv.lock b/example/database-app/uv.lock index e2071d70..e4bb9324 100644 --- a/example/database-app/uv.lock +++ b/example/database-app/uv.lock @@ -546,6 +546,7 @@ dev = [ { name = "dumpdie", specifier = ">=1.5.0" }, { name = "pytest", specifier = ">=9.0.3" }, { name = "pytest-asyncio", specifier = ">=1.3.0" }, + { name = "ruff", specifier = ">=0.9.0" }, { name = "twine", specifier = ">=6.2.0" }, ] diff --git a/fastapi_startkit/src/fastapi_startkit/application.py b/fastapi_startkit/src/fastapi_startkit/application.py index 3249fbd7..3701052a 100644 --- a/fastapi_startkit/src/fastapi_startkit/application.py +++ b/fastapi_startkit/src/fastapi_startkit/application.py @@ -67,6 +67,12 @@ def set_environment(self, env: str): self.env = env return self + def load_environment(self): + """Reload environment variables for the current self.env.""" + Environment.load_base(base_path=self.base_path) + Environment.load(self.env, base_path=self.base_path) + return self + def configure_exception_handler(self): self.exception_manager: ExceptionHandler = self._exception_handler_class( application=self @@ -176,6 +182,7 @@ def __call__(self, *args, **kwargs): def resolve_environment(self): self.env = Environment.resolve_environment(base_path=self.base_path, env=self.env) + Environment.load_base(base_path=self.base_path) Environment.load(self.env, base_path=self.base_path) def is_debug(self) -> bool: diff --git a/fastapi_startkit/src/fastapi_startkit/environment/environment.py b/fastapi_startkit/src/fastapi_startkit/environment/environment.py index af993008..3cbd5721 100644 --- a/fastapi_startkit/src/fastapi_startkit/environment/environment.py +++ b/fastapi_startkit/src/fastapi_startkit/environment/environment.py @@ -13,17 +13,18 @@ def resolve_environment(base_path=None, env: str | None = None): if "PYTEST_CURRENT_TEST" in os.environ: return "testing" - if os.environ.get("APP_ENV"): - return os.environ["APP_ENV"] - + # Explicit env parameter takes priority over os.environ APP_ENV if env: return env + if os.environ.get("APP_ENV"): + return os.environ["APP_ENV"] + path = base_path / ".env" if not path.exists(): raise ValueError("Unable to determine environment.") - load_dotenv(path) + load_dotenv(path, override=True) env = os.environ.get("APP_ENV") if not env: @@ -31,6 +32,13 @@ def resolve_environment(base_path=None, env: str | None = None): return env + @staticmethod + def load_base(base_path=None): + """Load the base .env file, resetting vars to their default values.""" + path = base_path / ".env" + if path.exists(): + load_dotenv(path, override=True) + @staticmethod def load(env: str, override=True, only=None, base_path=None): path = base_path / f".env.{env}" diff --git a/fastapi_startkit/src/fastapi_startkit/masoniteorm/relationships/MorphTo.py b/fastapi_startkit/src/fastapi_startkit/masoniteorm/relationships/MorphTo.py index dda53cfa..bdc7270a 100644 --- a/fastapi_startkit/src/fastapi_startkit/masoniteorm/relationships/MorphTo.py +++ b/fastapi_startkit/src/fastapi_startkit/masoniteorm/relationships/MorphTo.py @@ -1,4 +1,3 @@ -from dumpdie import dd from fastapi_startkit.masoniteorm.models import registry from .BaseRelationship import BaseRelationship from ..collection import Collection diff --git a/fastapi_startkit/src/fastapi_startkit/masoniteorm/schema/platforms/SQLitePlatform.py b/fastapi_startkit/src/fastapi_startkit/masoniteorm/schema/platforms/SQLitePlatform.py index 190c0c03..5dcfcf21 100644 --- a/fastapi_startkit/src/fastapi_startkit/masoniteorm/schema/platforms/SQLitePlatform.py +++ b/fastapi_startkit/src/fastapi_startkit/masoniteorm/schema/platforms/SQLitePlatform.py @@ -211,23 +211,21 @@ def compile_alter_sql(self, diff): or diff.changed_columns or diff.added_foreign_keys ): - original_columns = diff.from_table.added_columns + original_columns = dict(diff.from_table.added_columns) # pop off the dropped columns. No need for them here for column in diff.dropped_columns: - original_columns.pop(column) + original_columns.pop(column, None) sql.append( "CREATE TEMPORARY TABLE __temp__{table} AS SELECT {original_column_names} FROM {table}".format( table=diff.name, - original_column_names=", ".join( - diff.from_table.added_columns.keys() - ), + original_column_names=", ".join(original_columns.keys()), ) ) sql.append("DROP TABLE {table}".format(table=self.wrap_table(diff.name))) - columns = diff.from_table.added_columns + columns = dict(original_columns) columns.update(diff.renamed_columns) columns.update(diff.changed_columns) @@ -264,9 +262,7 @@ def compile_alter_sql(self, diff): quoted_table=self.wrap_table(diff.name), table=diff.name, new_columns=", ".join(self.columnize_names(columns)), - original_column_names=", ".join( - diff.from_table.added_columns.keys() - ), + original_column_names=", ".join(columns.keys()), ) ) sql.append("DROP TABLE __temp__{table}".format(table=diff.name))