Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "nitro-cli"
version = "1.0.13"
version = "1.0.14"
description = "Build static sites with Python code instead of template engines"
authors = [
{name = "Sean Nieuwoudt", email = "sean@nitro.sh"}
Expand Down
2 changes: 1 addition & 1 deletion src/nitro/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Nitro CLI - A static site generator"""

__version__ = "1.0.10"
__version__ = "1.0.14"
__author__ = "Sean Nieuwoudt"

from .core.config import Config
Expand Down
39 changes: 38 additions & 1 deletion src/nitro/core/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,32 @@


class Config:
"""Configuration class for Nitro projects."""
"""Project-level configuration for a Nitro site.

A `Config` instance is typically declared in `nitro.config.py` at the
project root as a module-level `config = Config(...)` binding. The CLI
loads it via `load_config()` during build and dev workflows, and its
fields drive output paths, URL rewriting, renderer behavior, and plugin
activation.

Attributes:
site_name: Human-readable site name, available to plugins and templates.
base_url: Canonical site URL, used for sitemaps, absolute links, and RSS.
build_dir: Directory where generated HTML and assets are written.
source_dir: Directory containing `pages/`, `data/`, and other source files.
renderer: Renderer options (e.g. `minify_html`, `pretty_print`). Merges
with defaults; user keys win.
plugins: Dotted import paths of plugins to activate for this project.
clean_urls: If True, emit `about/index.html` so URLs can omit `.html`.

Example:
>>> from nitro import Config
>>> config = Config(
... site_name="My Site",
... base_url="https://mysite.com",
... renderer={"minify_html": True},
... )
"""

def __init__(
self,
Expand All @@ -17,6 +42,18 @@ def __init__(
plugins: Optional[List[str]] = None,
clean_urls: bool = True,
):
"""Initialize a Config with project settings.

Args:
site_name: Human-readable site name.
base_url: Canonical site URL (no trailing slash required).
build_dir: Output directory for generated files, relative to project root.
source_dir: Source directory containing pages and data.
renderer: Renderer overrides merged on top of
`{"pretty_print": False, "minify_html": False}`.
plugins: Dotted import paths of plugins to enable.
clean_urls: When True, write `about/index.html` instead of `about.html`.
"""
self.site_name = site_name
self.base_url = base_url
self.build_dir = Path(build_dir)
Expand Down
74 changes: 52 additions & 22 deletions src/nitro/core/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,28 @@


class Env:
"""Lazy-loading environment variable accessor.
"""Lazy-loading accessor for environment variables.

Automatically loads .env file on first access if python-dotenv is installed.
Reads variables from `os.environ` and, if `python-dotenv` is installed,
auto-loads a `.env` file from the current working directory on first
access. Missing variables return `""` rather than raising, so pages can
treat optional config as falsy without guarding every lookup.

Usage:
from nitro import env
A module-level instance is exported as `nitro.env` - prefer that over
constructing `Env()` directly.

# Access environment variables as attributes
api_key = env.API_KEY

# Check if in production
if env.is_production():
# Production-only code
pass
Example:
>>> from nitro import env
>>> api_key = env.API_KEY
>>> if env.is_production():
... ...
"""

def __init__(self):
"""Initialize the accessor in an unloaded state.

The `.env` file is not touched until the first variable read.
"""
self._loaded = False

def _load(self):
Expand All @@ -43,13 +48,24 @@ def _load(self):
self._loaded = True

def __getattr__(self, name: str) -> str:
"""Get environment variable by attribute name.
"""Return the environment variable named `name`.

Triggers a one-time `.env` load on first access.

Args:
name: Environment variable name
name: Environment variable name. Leading underscores are reserved
for internal state and raise `AttributeError`.

Returns:
Value of environment variable, or empty string if not set
The variable's value, or `""` if it is not set.

Raises:
AttributeError: If `name` starts with an underscore.

Example:
>>> from nitro import env
>>> env.DATABASE_URL
'postgres://...'
"""
if name.startswith("_"):
raise AttributeError(name)
Expand All @@ -58,31 +74,45 @@ def __getattr__(self, name: str) -> str:
return os.environ.get(name, "")

def get(self, name: str, default: str = "") -> str:
"""Get environment variable with optional default.
"""Return an environment variable, falling back to `default`.

Use this instead of attribute access when you need a non-empty
fallback, or when the variable name is only known at runtime.

Args:
name: Environment variable name
default: Default value if not set
name: Environment variable name.
default: Value to return when the variable is unset.

Returns:
Value of environment variable, or default if not set
The variable's value, or `default` if it is not set.

Example:
>>> from nitro import env
>>> env.get("LOG_LEVEL", "info")
'info'
"""
self._load()
return os.environ.get(name, default)

def is_production(self) -> bool:
"""Check if running in production mode.
"""Return True when running under a production build.

Detected by `NITRO_ENV=production` in the environment; the CLI sets
this for you during `nitro build`.

Returns:
True if NITRO_ENV is set to 'production'
True if `NITRO_ENV` equals `"production"`, else False.
"""
return os.environ.get("NITRO_ENV") == "production"

def is_development(self) -> bool:
"""Check if running in development mode.
"""Return True when not running under a production build.

Complement of `is_production()`; treats any missing or non-production
`NITRO_ENV` value as development.

Returns:
True if not in production mode
True unless `NITRO_ENV` equals `"production"`.
"""
return not self.is_production()

Expand Down
Loading
Loading