### Setup Function for Plain CLI Registration Source: https://plainframework.com/docs/plain-vendor/plain/vendor/entrypoints This Python function, `setup()`, is designed to handle the initial setup for a Plain package that is not installed as a typical application. It explicitly imports the `cli` module from the current package, which is necessary to trigger its registration and make command-line interface functionalities available. ```python def setup(): # This package isn't an installed app, # so we need to trigger our own import and cli registration. from .cli import cli # noqa ``` -------------------------------- ### Implement Package `ready()` Method (Python) Source: https://plainframework.com/docs/plain/plain/packages Shows how to define a package configuration and implement the `ready()` method to execute setup code when the package is loaded. This example uses `plain.packages.PackageConfig` and `register_config`. ```Python # /config.py from plain.packages import PackageConfig, register_config @register_config class TeamsConfig(PackageConfig): def ready(self): print("Teams package is ready!") ``` -------------------------------- ### Python: MkcertManager Class for Setup Source: https://plainframework.com/docs/plain-dev/plain/dev/mkcert This Python class, `MkcertManager`, handles the setup and management of the `mkcert` tool. It first checks if `mkcert` is already installed on the system. If not, it proceeds to download the appropriate binary based on the operating system (Darwin, Linux) and architecture (amd64, arm64), and then installs the local CA for development purposes. ```Python import platform import shutil import subprocess import sys import time import urllib.request import click class MkcertManager: def __init__(self): self.mkcert_bin = None def setup_mkcert(self, install_path): """Set up mkcert by checking if it's installed or downloading the binary and installing the local CA.""" if mkcert_path := shutil.which("mkcert"): # mkcert is already installed somewhere self.mkcert_bin = mkcert_path else: self.mkcert_bin = install_path / "mkcert" install_path.mkdir(parents=True, exist_ok=True) if not self.mkcert_bin.exists(): system = platform.system() arch = platform.machine() # Map platform.machine() to mkcert's expected architecture strings arch_map = { "x86_64": "amd64", "amd64": "amd64", "AMD64": "amd64", "arm64": "arm64", "aarch64": "arm64" } arch = arch_map.get( arch.lower(), "amd64" ) # Default to amd64 if unknown if system == "Darwin": os_name = "darwin" elif system == "Linux": os_name = "linux" ``` -------------------------------- ### Plain Code CLI Setup Function Source: https://plainframework.com/docs/plain-code/plain/code/entrypoints This Python `setup()` function is designed to manually trigger the import and registration of the command-line interface (CLI) for the Plain framework. It's used when the package is not installed as a typical application, ensuring the CLI is available. ```Python def setup(): # This package isn't an installed app, # so we need to trigger our own import and cli registration. from .cli import cli # noqa ``` -------------------------------- ### Setup plain-pytest CLI Entry Point Source: https://plainframework.com/docs/plain-pytest/plain/pytest/entrypoints This Python function, `setup`, is responsible for triggering the import and CLI registration for the plain-pytest package. It's necessary because the package is not installed as a typical application, requiring manual initialization of its command-line interface. ```Python def setup(): # This package isn't an installed app, # so we need to trigger our own import and cli registration. from .cli import cli # noqa ``` -------------------------------- ### Setup Function for Plain CLI Registration Source: https://plainframework.com/docs/plain-tunnel/plain/tunnel/entrypoints This Python function, `setup`, is designed to handle the initial import and CLI registration for a package that is not installed as a typical application. It specifically imports the `cli` object from the local `cli` module to ensure its functionality is available. ```Python def setup(): # This package isn't an installed app, # so we need to trigger our own import and cli registration. from .cli import cli # noqa ``` -------------------------------- ### Python: Context Manager __enter__ for Service Startup Source: https://plainframework.com/docs/plain-dev/plain/dev/services This `__enter__` method, part of a Python context manager, handles the initial setup for Plain Framework development services. It prevents redundant starts if services are already running. If not, it launches the 'plain dev services' command as a subprocess and includes a timed delay to allow for service initialization, with a specific wait for database services if `plain.models` is detected. ```python def __enter__(self): if not self.get_services(APP_PATH.parent): # No-op if no services are defined return if self.are_running(): click.secho("Services already running", fg="yellow") return print("Starting `plain dev services`") self._subprocess = subprocess.Popen( ["plain", "dev", "services"], cwd=APP_PATH.parent ) if find_spec("plain.models"): time.sleep(0.5) # Give it a chance to hit on the first try subprocess.check_call(["plain", "models", "db-wait"], env=os.environ) else: # A bit of a hack to wait for the services to start time.sleep(3) ``` -------------------------------- ### Configure Plain Application Settings in app/settings.py Source: https://plainframework.com/docs/plain/plain/runtime This example `app/settings.py` file demonstrates how to configure core Plain framework settings. It shows how to define URL routing, time zone, installed packages, authentication models, and middleware, overriding default values. ```python # app/settings.py URLS_ROUTER = "app.urls.AppRouter" TIME_ZONE = "America/Chicago" INSTALLED_PACKAGES = [ "plain.models", "plain.tailwind", "plain.auth", "plain.passwords", "plain.sessions", "plain.htmx", "plain.admin", "plain.elements", # Local packages "app.users", ] AUTH_USER_MODEL = "users.User" AUTH_LOGIN_URL = "login" MIDDLEWARE = [ "plain.sessions.middleware.SessionMiddleware", "plain.auth.middleware.AuthenticationMiddleware", "plain.admin.AdminMiddleware", ] ``` -------------------------------- ### Python: Setup Plain Framework Entry Points and Environment Source: https://plainframework.com/docs/plain-dev/plain/dev/entrypoints This Python function `setup()` initializes the Plain framework's entry points. It registers various command-line interfaces (CLIs) from `cli`, `precommit`, and `contribute` modules. Additionally, it configures a remote debugging breakpoint hook and loads environment variables from `.env` files, supporting environment-specific configurations. ```Python import os from dotenv import load_dotenv from .debug import set_breakpoint_hook def setup(): # Make sure our clis are registered # since this isn't an installed app from .cli import cli # noqa from .precommit import cli # noqa from .contribute import cli # noqa # Try to set a new breakpoint() hook # so we can connect to pdb remotely. set_breakpoint_hook() # Load environment variables from .env file if plain_env := os.environ.get("PLAIN_ENV", ""): load_dotenv(f".env.{plain_env}") else: load_dotenv(".env") ``` -------------------------------- ### Override `ready` Method for Plain Framework App Initialization Source: https://plainframework.com/docs/plain/plain/packages/config This Python method `ready` is designed to be overridden by subclasses of `AppConfig` (or similar in Plain framework). It provides a hook to execute custom code when the Plain framework starts, allowing for application-specific setup and initialization. ```python def ready(self): """ Override this method in subclasses to run code when Plain starts. """ ``` -------------------------------- ### Install plain.admin package Source: https://plainframework.com/docs/plain-admin/README Installs the `plain.admin` package and its dependencies using the `uv` package manager. ```Shell uv add plain.admin ``` -------------------------------- ### Install plain-oauth Python Package Source: https://plainframework.com/docs/plain-oauth This command installs the plain-oauth library from the Python Package Index (PyPI) into your project's environment, making it available for use. ```Shell pip install plain-oauth ``` -------------------------------- ### Demonstrate Plain Test Client and RequestFactory Usage Source: https://plainframework.com/docs/plain/plain/test This Python code snippet illustrates how to use Plain's testing utilities. It shows examples of making GET requests, managing sessions, handling user login and logout with the Client class, and creating basic requests using the RequestFactory. ```Python from plain.test import Client def test_client_example(): client = Client() # Getting responses response = client.get("/") assert response.status_code == 200 # Modifying sessions client.session["example"] = "value" assert client.session["example"] == "value" # Logging in user = User.objects.first() client.force_login(user) response = client.get("/protected/") assert response.status_code == 200 # Logging out client.logout() response = client.get("/protected/") assert response.status_code == 302 def test_request_factory_example(): request = RequestFactory().get("/") assert request.method == "GET" ``` -------------------------------- ### Install plain.admin package with uv Source: https://plainframework.com/docs/plain-admin This command installs the `plain.admin` package and its required dependencies using the `uv` package manager, which is the first step to setting up the admin interface. ```Shell uv add plain.admin ``` -------------------------------- ### Install Plain Admin Package Source: https://plainframework.com/docs/plain-admin/plain/admin Command to install the `plain.admin` package and its dependencies using the `uv` package manager. ```Shell uv add plain.admin ``` -------------------------------- ### Install plain-oauth Python Package Source: https://plainframework.com/docs/plain-oauth/README Installs the `plain-oauth` library from PyPi using pip, the Python package installer. This is the first step to integrate the library into your project. ```shell pip install plain-oauth ``` -------------------------------- ### Install plain-oauth Python Package Source: https://plainframework.com/docs/plain-oauth/plain/oauth/README Installs the plain-oauth library using pip, the Python package installer. This command fetches the package from PyPI and makes it available in your Python environment. ```Shell pip install plain-oauth ``` -------------------------------- ### Manage Additional Services for Plain Framework Source: https://plainframework.com/docs/plain-dev/plain/dev/cli Starts additional background services defined within the project's configuration (e.g., `pyproject.toml`). It checks if services are already running before attempting to start them. ```Python @cli.command() def services(): """Start additional services defined in pyproject.toml""" _services = Services() if _services.are_running(): click.secho("Services already running", fg="yellow") return _services.run() ``` -------------------------------- ### Install plain.admin package via uv Source: https://plainframework.com/docs/plain-admin/plain/admin/README Install the `plain.admin` package and its dependencies using the `uv` package manager, a common tool for Python project management. ```CLI uv add plain.admin ``` -------------------------------- ### Get Installed Plain Packages from uv.lock Source: https://plainframework.com/docs/plain-upgrade/plain/upgrade/cli This Python function reads the `uv.lock` file, parses its TOML content, and extracts the names of installed packages that start with "plain" (excluding "plain-upgrade"). It returns a list of these filtered package names. ```Python def get_installed_plain_packages() -> list[str]: lock_text = LOCK_FILE.read_text() data = tomllib.loads(lock_text) names: list[str] = [] for pkg in data.get("package", []): name = pkg.get("name", "") if name.startswith("plain") and name != "plain-upgrade": names.append(name) return names ``` -------------------------------- ### Plain CLI Database Backups Module Setup Source: https://plainframework.com/docs/plain-models/plain/models/backups/cli This snippet defines the necessary imports for the Plain framework's database backup CLI module, including `os`, `time`, `pathlib`, `click`, and internal Plain utilities. It also initializes the main 'backups' command group using Click, serving as the entry point for all subsequent backup commands. ```Python import os import time from pathlib import Path import click from plain.cli import register_cli from .core import DatabaseBackups @register_cli("backups") @click.group("backups") def cli(): """Local database backups""" pass ``` -------------------------------- ### Initialize and Load Installed Packages (`populate` method) Source: https://plainframework.com/docs/plain/plain/packages/registry The `populate` method orchestrates the loading and configuration of all installed packages. It performs a two-phase initialization: first, registering package configurations and importing modules, then running `ready()` methods. It includes checks for reentrancy, ensures all packages are registered, and validates for duplicate package names, raising `RuntimeError` or `ImproperlyConfigured` exceptions on issues. ```Python # An RLock prevents other threads from entering this section. The # compare and set operation below is atomic. if self.loading: # Prevent reentrant calls to avoid running PackageConfig.ready() # methods twice. raise RuntimeError("populate() isn't reentrant") self.loading = True # Phase 1: initialize app configs and import app modules. for entry in installed_packages: if isinstance(entry, PackageConfig): # Some instances of the registry pass in the # PackageConfig directly... self.register_config(package_config=entry) else: try: import_module(f"{entry}.{CONFIG_MODULE_NAME}") except ModuleNotFoundError: pass # The config for the package should now be registered, if it existed. # And if it didn't, now we can auto generate one. entry_config = None for config in self.package_configs.values(): if config.name == entry: entry_config = config break if not entry_config: # Use PackageConfig class as-is, without any customization. auto_package_config = PackageConfig(entry) entry_config = self.register_config(auto_package_config) # Make sure we have the same number of configs as we have installed packages if len(self.package_configs) != len(installed_packages): raise ImproperlyConfigured( f"The number of installed packages ({len(installed_packages)}) does not match the number of " f"registered configs ({len(self.package_configs)})." ) # Check for duplicate app names. counts = Counter( package_config.name for package_config in self.package_configs.values() ) duplicates = [name for name, count in counts.most_common() if count > 1] if duplicates: raise ImproperlyConfigured( "Package names aren't unique, duplicates: {}".format( ", ".join(duplicates) ) ) self.packages_ready = True # Phase 3: run ready() methods of app configs. for package_config in self.get_package_configs(): package_config.ready() self.ready = True ``` -------------------------------- ### Discover Installed Plain Packages with uv pip freeze (Python) Source: https://plainframework.com/docs/plain-dev/plain/dev/contribute/cli This Python snippet uses `uv pip freeze` to list all installed Python packages. It then filters the list to identify packages starting with 'plain' or 'plainx-', categorizing them for further processing. It handles cases where no packages are found. ```Python output = subprocess.check_output(["uv", "pip", "freeze"]) installed_packages = output.decode() if not installed_packages: click.secho("No installed packages found", fg="red") sys.exit(1) packages = [] for line in installed_packages.splitlines(): if not line.startswith("plain"): continue package = line.split("==")[0] if package.startswith("plainx-"): skipped_plainx_packages.append(package) else: packages.append(package) ``` -------------------------------- ### Initialize Application Processes (Python) Source: https://plainframework.com/docs/plain-dev/plain/dev/cli This method is responsible for starting the core application processes, such as Gunicorn, entrypoints, and pyproject run commands. It can be invoked directly or triggered by a `SIGUSR1` signal, typically after a database or other prerequisite services are ready. ```Python def start_app(self, signum, frame): # This runs in the main thread when SIGUSR1 is received # (or called directly if no thread). click.secho("\nStarting app...", italic=True, dim=True) # Manually start the status bar now so it isn't bungled by # another thread checking db stuff... self.console_status.start() self.add_gunicorn() self.add_entrypoints() self.add_pyproject_run() ``` -------------------------------- ### Configure Plain Tunnel in pyproject.toml Source: https://plainframework.com/docs/plain-tunnel This configuration snippet shows how to integrate plain.tunnel into your plain.dev setup. By adding this to your pyproject.toml file, the tunnel will automatically start when your development server runs, forwarding traffic to your local environment. ```Configuration [tool.plain.dev.run] tunnel = {cmd = "plain tunnel $PLAIN_DEV_URL --subdomain myappname --quiet"} ``` -------------------------------- ### Plain Framework ModelBase Metadata Setup Source: https://plainframework.com/docs/plain-models/plain/models/base The `_setup_meta` method within `ModelBase` is responsible for initializing the model's `_meta` attribute, which holds model options and metadata. It determines the `package_label` for the model, either from an explicit `Meta` class definition or by inferring it from the containing package configuration, ensuring models are correctly associated with their applications. ```Python def _setup_meta(cls): name = cls.__name__ module = cls.__module__ # The model's Meta class, if it has one. meta = getattr(cls, "Meta", None) # Look for an application configuration to attach the model to. package_config = packages_registry.get_containing_package_config(module) package_label = getattr(meta, "package_label", None) if package_label is None: if package_config is None: raise RuntimeError( f"Model class {module}.{name} doesn't declare an explicit " "package_label and isn't in an application in " "INSTALLED_PACKAGES." ) else: package_label = package_config.package_label cls.add_to_class("_meta", Options(meta, package_label)) ``` -------------------------------- ### Get Number of Managed Processes Source: https://plainframework.com/docs/plain-dev/plain/dev/poncho/manager Returns the current count of processes that are being managed by this `Manager` instance. This includes processes that have been added but not yet started, as well as running and stopped processes. ```Python def num_processes(self): """ Return the number of processes managed by this instance. """ return len(self._processes) ``` ```APIDOC Manager.num_processes(self) -> int Returns: int - The number of processes managed by this instance. ``` -------------------------------- ### Manage Application Lifecycle and Service Orchestration (Python) Source: https://plainframework.com/docs/plain-dev/plain/dev/cli This method orchestrates the primary application startup sequence. It handles PID file management, sets up SSL certificates using `mkcert`, modifies the hosts file, runs preflight checks, manages external services (starting them if not already running), and integrates with `plain.models` for database readiness, using `poncho` for process management. ```Python def run(self): self.pid.write() mkcert_manager = MkcertManager() mkcert_manager.setup_mkcert(install_path=Path.home() / ".plain" / "dev") self.ssl_cert_path, self.ssl_key_path = mkcert_manager.generate_certs( domain=self.hostname, storage_path=Path(PLAIN_TEMP_PATH) / "dev" / "certs", ) self.symlink_plain_src() self.modify_hosts_file() self.set_allowed_hosts() self.run_preflight() # If we start services ourselves, we should manage the pidfile services_pid = None # Services start first (or are already running from a separate command) if Services.are_running(): click.secho("Services already running", fg="yellow") elif services := Services.get_services(APP_PATH.parent): click.secho("\nStarting services...", italic=True, dim=True) services_pid = ServicesPid() services_pid.write() for name, data in services.items(): env = { **os.environ, "PYTHONUNBUFFERED": "true", **data.get("env", {}), } self.poncho.add_process(name, data["cmd"], env=env) # If plain.models is installed (common) then we # will do a couple extra things before starting all of the app-related # processes (this way they don't all have to db-wait or anything) process = None if find_spec("plain.models") is not None: # Use a custom signal to tell the main thread to add # the app processes once the db is ready signal.signal(signal.SIGUSR1, self.start_app) process = multiprocessing.Process( target=_process_task, args=(self.plain_env,) ) process.start() # If there are no poncho processes, then let this process finish before # continuing (vs running in parallel) if self.poncho.num_processes() == 0: # Wait for the process to finish process.join() else: # Start the app processes immediately self.start_app(None, None) try: # Start processes we know about and block the main thread self.poncho.loop() # Remove the status bar self.console_status.stop() finally: self.pid.rm() # Make sure the services pid gets removed if we set it if services_pid: services_pid.rm() # Make sure the process is terminated if it is still running if process and process.is_alive(): os.killpg(os.getpgid(process.pid), signal.SIGTERM) process.join(timeout=3) if process.is_alive(): os.killpg(os.getpgid(process.pid), signal.SIGKILL) process.join() return self.poncho.returncode ``` -------------------------------- ### Define a Basic Plain View Class Source: https://plainframework.com/docs/plain/plain/views This example demonstrates how to define a simple view class in Plain by inheriting from `plain.views.View` and implementing a `get` method to return an HTML string. This is the fundamental structure for creating a view. ```python from plain.views import View class ExampleView(View): def get(self): return "Hello, world!" ``` -------------------------------- ### Install Plain Worker Package in Python Settings Source: https://plainframework.com/docs/plain-worker This configuration example illustrates the necessary step to integrate the `plain.worker` package into a Plain project. By adding `'plain.worker'` to the `INSTALLED_PACKAGES` list within `app/settings.py`, the worker functionality becomes available for use. ```python # app/settings.py INSTALLED_PACKAGES = [ ... "plain.worker", ] ``` -------------------------------- ### Start Plain Framework Local Development Server Source: https://plainframework.com/docs/plain-dev/plain/dev/cli Initializes and runs a local development server for the Plain Framework. It checks if a development server is already running, determines the project name and hostname, finds an available port, and sets up environment variables for the server. It also handles SSL certificate paths and tunnel URLs. ```Python """Start local development""" if ctx.invoked_subcommand: return if DevPid().exists(): click.secho("`plain dev` already running", fg="yellow") sys.exit(1) if not hostname: project_name = os.path.basename( os.getcwd() ) # Use the directory name by default if has_pyproject_toml(APP_PATH.parent): with open(Path(APP_PATH.parent, "pyproject.toml"), "rb") as f: pyproject = tomllib.load(f) project_name = pyproject.get("project", {}).get("name", project_name) hostname = f"{project_name}.localhost" returncode = Dev(port=port, hostname=hostname, log_level=log_level).run() if returncode: sys.exit(returncode) class Dev: def __init__(self, *, port, hostname, log_level): self.hostname = hostname self.log_level = log_level self.pid = DevPid() if port: self.port = int(port) if not self._port_available(self.port): click.secho(f"Port {self.port} in use", fg="red") raise SystemExit(1) else: self.port = self._find_open_port(8443) if self.port != 8443: click.secho(f"Port 8443 in use, using {self.port}", fg="yellow") self.ssl_key_path = None self.ssl_cert_path = None self.url = f"https://{self.hostname}:{self.port}" self.tunnel_url = os.environ.get("PLAIN_DEV_TUNNEL_URL", "") self.plain_env = { "PYTHONUNBUFFERED": "true", "PLAIN_DEV": "true", **os.environ, } if log_level: self.plain_env["PLAIN_LOG_LEVEL"] = log_level.upper() self.plain_env["APP_LOG_LEVEL"] = log_level.upper() self.custom_process_env = { **self.plain_env, "PORT": str(self.port), "PLAIN_DEV_URL": self.url, } if self.tunnel_url: status_bar = Columns( [ Text.from_markup( f"[bold]Tunnel[/bold] [underline][link={self.tunnel_url}]{self.tunnel_url}[/link][/underline]" ), Text.from_markup( f"[dim][bold]Server[/bold] [link={self.url}]{self.url}[/link][/dim]" ), Text.from_markup( "[dim][bold]Ctrl+C[/bold] to stop[/dim]", justify="right", ), ], expand=True, ) else: status_bar = Columns( [ Text.from_markup( f"[bold]Server[/bold] [underline][link={self.url}]{self.url}[/link][/underline]" ), Text.from_markup( "[dim][bold]Ctrl+C[/bold] to stop[/dim]", justify="right" ), ], expand=True, ) ``` -------------------------------- ### Python: Get Forward Related Filter Arguments Source: https://plainframework.com/docs/plain-models/plain/models/fields/related This method is designed to return keyword arguments that can be supplied to filter related objects in a forward relationship. The provided snippet shows the method signature and the start of its docstring. ```Python def get_forward_related_filter(self, obj): """ Return the keyword arguments that when supplied to ``` -------------------------------- ### Initialize Plain Runtime and Customize Shell Startup Source: https://plainframework.com/docs/plain/plain/cli/startup This Python script initializes the Plain framework's runtime environment by calling `plain.runtime.setup()`. It includes helper functions for printing styled text (bold, italic, dim) to the console. Additionally, it supports dynamic module import based on the `settings.SHELL_IMPORT` configuration, allowing users to load and expose module contents directly into the shell's global scope for an enhanced interactive experience. ```python import plain.runtime plain.runtime.setup() def print_bold(s): print("\033[1m", end="") print(s) print("\033[0m", end="") def print_italic(s): print("\x1b[3m", end="") print(s) print("\x1b[0m", end="") def print_dim(s): print("\x1b[2m", end="") print(s) print("\x1b[0m", end="") print_bold("\n⬣ Welcome to the Plain shell! ⬣\n") if shell_import := plain.runtime.settings.SHELL_IMPORT: from importlib import import_module print_bold(f"Importing {shell_import}") module = import_module(shell_import) with open(module.__file__) as f: contents = f.read() for line in contents.splitlines(): print_dim(f"{line}") print() # Emulate `from module import *` names = getattr( module, "__all__", [name for name in dir(module) if not name.startswith("_")] ) globals().update({name: getattr(module, name) for name in names}) else: print_italic("Use settings.SHELL_IMPORT to customize the shell startup.\n") ``` -------------------------------- ### Python: Start Plain Framework Services with PID Management Source: https://plainframework.com/docs/plain-dev/plain/dev/services This Python code block initiates Plain Framework services. It writes a PID file to track the process, iterates through defined services, and starts each as a subprocess with specific environment variables. A `finally` block ensures the PID file is removed upon completion or error, maintaining system cleanliness. ```python pid = ServicesPid() pid.write() try: services = self.get_services(APP_PATH.parent) for name, data in services.items(): env = { **os.environ, "PYTHONUNBUFFERED": "true", **data.get("env", {}), } self.poncho.add_process(name, data["cmd"], env=env) self.poncho.loop() finally: pid.rm() ``` -------------------------------- ### Accessing and Managing Sessions in Plain Views Source: https://plainframework.com/docs/plain-sessions This example demonstrates how to store and retrieve data from the session object within a Plain framework view. It shows basic usage of `request.session` to manage user-specific data, including setting and getting values. ```Python class MyView(View): def get(self): # Store a value in the session self.request.session['key'] = 'value' # Retrieve a value from the session value = self.request.session.get('key') ``` -------------------------------- ### Use testbrowser fixture for Playwright-based browser testing Source: https://plainframework.com/docs/plain-pytest/README This fixture provides a lightweight wrapper around Playwright, enabling end-to-end browser testing by starting a gunicorn side-process. It requires 'playwright', 'pytest-playwright', and 'gunicorn' to be installed separately. If 'plain.models' is present, it also integrates with the 'isolated_db' fixture. ```python def test_example(testbrowser): page = testbrowser.new_page() page.goto('/') assert page.title() == 'Home Page' ``` -------------------------------- ### Manually Initialize Plain Runtime Environment Source: https://plainframework.com/docs/plain/plain/runtime This code demonstrates how to manually set up the Plain runtime environment by calling `plain.runtime.setup()`. This is useful for invoking Plain in standalone Python scripts or other non-standard environments. ```python import plain.runtime plain.runtime.setup() ``` -------------------------------- ### Apply OpenAPI Schema to Specific View Method in Plain Framework Source: https://plainframework.com/docs/plain-api This Python example demonstrates how to use the `@openapi.schema` decorator on a specific HTTP method within a view class (e.g., `get` method of `CurrentUserAPIView`). This allows for defining method-specific OpenAPI documentation, such as a summary for the endpoint. ```Python class CurrentUserAPIView(BaseAPIView): @openapi.schema({ "summary": "Get current user" }) def get(self): if self.request.user: user = self.request.user else: raise Http404 return schemas.UserSchema.from_user(user, self.request) ``` -------------------------------- ### Implement Plain Package Ready Method Source: https://plainframework.com/docs/plain/plain/packages/README This code demonstrates how to create a `PackageConfig` class in the Plain framework and register it. The `ready()` method within this class is automatically invoked when the package is loaded, allowing for execution of initialization logic. ```python from plain.packages import PackageConfig, register_config @register_config class TeamsConfig(PackageConfig): def ready(self): print("Teams package is ready!") ``` -------------------------------- ### Handle HTTP Requests and Responses in Plain Views Source: https://plainframework.com/docs/plain/plain/http This Python example demonstrates how to create a view in the Plain framework to handle HTTP GET requests. It illustrates accessing request headers and query parameters, creating a Response object, and setting response headers before returning the response. ```Python from plain.views import View from plain.http import Response class ExampleView(View): def get(self): # Accessing a request header print(self.request.headers.get("Example-Header")) # Accessing a query parameter print(self.request.query_params.get("example")) # Creating a response response = Response("Hello, world!", status_code=200) # Setting a response header response.headers["Example-Header"] = "Example Value" return response ``` -------------------------------- ### Retrieve Available Image Extensions (Python) Source: https://plainframework.com/docs/plain/plain/validators This function dynamically retrieves a list of image file extensions supported by the Pillow (PIL) library. It attempts to import PIL.Image and initializes it to get the available extensions, returning an empty list if PIL is not installed. ```python def get_available_image_extensions(): try: from PIL import Image except ImportError: return [] else: Image.init() return [ext.lower()[1:] for ext in Image.EXTENSION] ``` -------------------------------- ### Squash Migrations: User Confirmation and Operation Collection Setup Source: https://plainframework.com/docs/plain-models/plain/models/cli This part of the `squash_migrations` command prompts the user for confirmation before proceeding with the squashing process, if verbosity or interactivity is enabled. It also initializes lists for collecting operations and dependencies from the migrations to be squashed, preparing for the core squashing logic. ```python # Tell them what we're doing and optionally ask if we should proceed if verbosity > 0 or interactive: click.secho("Will squash the following migrations:", fg="cyan", bold=True) for migration in migrations_to_squash: click.echo(f" - {migration.name}") if interactive: if not click.confirm("Do you wish to proceed?"): return # Load the operations from all those migrations and concat together, # along with collecting external dependencies and detecting double-squashing operations = [] dependencies = set() # We need to take all dependencies from the first migration in the list # as it may be 0002 depending on 0001 first_migration = True for smigration in migrations_to_squash: if smigration.replaces: raise click.ClickException( ``` -------------------------------- ### Download and Prepare mkcert Binary for OS Source: https://plainframework.com/docs/plain-dev/plain/dev/mkcert This Python code block identifies the operating system and architecture to download the appropriate `mkcert` binary. It ensures the binary is executable and converts its path for further use, exiting if the OS is unsupported. ```Python elif system == "Windows": os_name = "windows" else: click.secho("Unsupported OS", fg="red") sys.exit(1) mkcert_url = f"https://dl.filippo.io/mkcert/latest?for={os_name}/{arch}" click.secho(f"Downloading mkcert from {mkcert_url}...", bold=True) urllib.request.urlretrieve(mkcert_url, self.mkcert_bin) self.mkcert_bin.chmod(0o755) self.mkcert_bin = str(self.mkcert_bin) # Convert Path object to string ``` -------------------------------- ### Python: Get Model Fields (Public API) Source: https://plainframework.com/docs/plain-models/plain/models/options Returns a list of fields associated with the model. By default, it includes forward and reverse fields, and fields derived from inheritance, but excludes hidden fields. The `include_hidden` parameter allows for the inclusion of fields with a related_name starting with a '+'. ```Python def get_fields(self, include_hidden=False): """ Return a list of fields associated to the model. By default, include forward and reverse fields, fields derived from inheritance, but not hidden fields. The returned fields can be changed using the parameters: - include_hidden: include fields that have a related_name that starts with a "+" """ return self._get_fields(include_hidden=include_hidden) ``` -------------------------------- ### Demonstrate Plain Test Client and RequestFactory Usage in Python Source: https://plainframework.com/docs/plain/plain/test/README This Python code snippet illustrates how to use Plain's testing utilities. It shows examples of making GET requests, modifying client sessions, forcing user login and logout with the Client, and creating test requests using the RequestFactory. ```python from plain.test import Client def test_client_example(): client = Client() # Getting responses response = client.get("/") assert response.status_code == 200 # Modifying sessions client.session["example"] = "value" assert client.session["example"] == "value" # Logging in user = User.objects.first() client.force_login(user) response = client.get("/protected/") assert response.status_code == 200 # Logging out client.logout() response = client.get("/protected/") assert response.status_code == 302 def test_request_factory_example(): request = RequestFactory().get("/") assert request.method == "GET" ``` -------------------------------- ### Manually Initialize Plain Runtime Source: https://plainframework.com/docs/plain/plain/runtime/README This snippet demonstrates how to manually set up the Plain runtime environment by calling `plain.runtime.setup()`. This is useful for invoking Plain in standalone Python scripts or other environments where automatic setup is not desired. ```python import plain.runtime plain.runtime.setup() ``` -------------------------------- ### Install Tailwind CSS Standalone Executable in Python Source: https://plainframework.com/docs/plain-tailwind/plain/tailwind/core Installs the Tailwind CSS standalone executable by first downloading it and then updating the project's configuration with the installed version. This method orchestrates the full installation process, ensuring the correct executable is in place and its version is recorded. It returns the version that was installed. ```Python def install(self, version="") -> str: installed_version = self.download(version) self.set_version_in_config(installed_version) return installed_version ``` -------------------------------- ### Create New Browser Context with Base URL and HTTPS Ignore Source: https://plainframework.com/docs/plain-pytest/plain/pytest/browser This function creates a new browser context, configuring it with a specified base URL and instructing it to ignore HTTPS errors. This setup is ideal for starting a fresh browsing session or isolating tests, especially when dealing with self-signed certificates or development servers. ```Python def reset_context(self): """Create a new browser context with the base URL and ignore HTTPS errors.""" self.context = self.browser.new_context( base_url=self.base_url, ignore_https_errors=True, ) ``` -------------------------------- ### Implement Recursive Help Command for Click CLI Source: https://plainframework.com/docs/plain/plain/cli/help This Python snippet defines a 'help' command using the Click library. It recursively traverses and prints the help documentation for all commands and subcommands registered within a Click application, providing a comprehensive overview of available CLI functionalities. It leverages `click.Context` and `click.secho` for formatted output. ```Python import click from click.core import Group @click.command("help") @click.pass_context def help_cmd(ctx): """Show help for all commands and subcommands.""" root = ctx.parent.command info_name = ctx.parent.info_name or "plain" def print_help(cmd, prog, parent=None): sub_ctx = click.Context(cmd, info_name=prog, parent=parent) title = sub_ctx.command_path click.secho(title, fg="green", bold=True) click.secho("-" * len(title), fg="green") click.echo(sub_ctx.get_help()) if isinstance(cmd, Group): for name in cmd.list_commands(sub_ctx): click.echo() sub_cmd = cmd.get_command(sub_ctx, name) print_help(sub_cmd, name, sub_ctx) print_help(root, info_name) ``` -------------------------------- ### Python DictWrapper Get Item with Prefix Processing Source: https://plainframework.com/docs/plain/plain/utils/datastructures Overrides the standard dictionary item retrieval (`__getitem__`) to implement conditional value processing. If the requested key starts with the configured prefix, the prefix is removed, and the retrieved value is passed through the wrapper's function before being returned; otherwise, the raw value is returned. ```Python def __getitem__(self, key): """ Retrieve the real value after stripping the prefix string (if present). If the prefix is present, pass the value through self.func before returning, otherwise return the raw value. """ use_func = key.startswith(self.prefix) key = key.removeprefix(self.prefix) value = super().__getitem__(key) if use_func: return self.func(value) return value ``` -------------------------------- ### Run Installed Package Build Entry Points (Python) Source: https://plainframework.com/docs/plain/plain/cli/build This code block discovers and executes build entry points registered under the 'plain.build' group. It uses the 'entry_points' mechanism to find and load functions, providing visual feedback on each entry point's execution. ```Python for entry_point in entry_points(group="plain.build"): click.secho(f"Running {entry_point.name}", bold=True) result = entry_point.load()() print() ``` -------------------------------- ### Execute Database Migrations with Backup and State Management in Python Source: https://plainframework.com/docs/plain-models/plain/models/cli This section orchestrates the application of database migrations. It includes logic for creating an optional database backup before migration, executes the migration plan using `executor.migrate`, and then updates the project's model registry to reflect the new state after migration. ```python if prune: return # Print some useful info if verbosity >= 1: click.echo("Operations to perform:", color="cyan") if target_package_labels_only: click.echo( " Apply all migrations: " + (", ".join(sorted({a for a, n in targets})) or "(none)"), color="yellow", ) else: click.echo( f" Target specific migration: {targets[0][1]}, from {targets[0][0]}", color="yellow", ) pre_migrate_state = executor._create_project_state(with_applied_migrations=True) # sql = executor.loader.collect_sql(migration_plan) # pprint(sql) if migration_plan: if backup or ( backup is None and settings.DEBUG and click.confirm( "\nYou are in DEBUG mode. Would you like to make a database backup before running migrations?", default=True, ) ): backup_name = f"migrate_{time.strftime('%Y%m%d_%H%M%S')}" # Can't use ctx.invoke because this is called by the test db creation currently, # which doesn't have a context. create_backup.callback( backup_name=backup_name, pg_dump=os.environ.get( "PG_DUMP", "pg_dump" ), # Have to this again manually ) print() if verbosity >= 1: click.echo("Running migrations:", color="cyan") post_migrate_state = executor.migrate( targets, plan=migration_plan, state=pre_migrate_state.clone(), fake=fake, fake_initial=fake_initial, ) # post_migrate signals have access to all models. Ensure that all models # are reloaded in case any are delayed. post_migrate_state.clear_delayed_models_cache() post_migrate_packages = post_migrate_state.models_registry # Re-render models of real packages to include relationships now that # we've got a final state. This wouldn't be necessary if real packages # models were rendered with relationships in the first place. with post_migrate_packages.bulk_update(): model_keys = [] for model_state in post_migrate_packages.real_models: model_key = model_state.package_label, model_state.name_lower model_keys.append(model_key) post_migrate_packages.unregister_model(*model_key) post_migrate_packages.render_multiple( [ ModelState.from_model(models_registry.get_model(*model)) for model in model_keys ] ) ``` -------------------------------- ### Map HTTP Methods to View Class Methods Source: https://plainframework.com/docs/plain/plain/views/README This example illustrates how Plain views automatically map incoming HTTP request methods (e.g., GET, POST, PUT, PATCH, DELETE, TRACE) to corresponding class methods. If a request comes in for a method not defined on the view, Plain will automatically return a `405 Method Not Allowed` response. ```python from plain.views import View class ExampleView(View): def get(self): pass def post(self): pass def put(self): pass def patch(self): pass def delete(self): pass def trace(self): pass ``` -------------------------------- ### Python: Setup Test Database Source: https://plainframework.com/docs/plain-models/plain/models/test/utils This function creates a new test database for testing purposes. It temporarily stores the original database name, creates a new test database using `db_connection.creation.create_test_db`, and returns the original name to allow for later restoration. It requires a `verbosity` level and accepts an optional `prefix` for the test database name. ```Python from plain.models import db_connection def setup_database(*, verbosity, prefix=""): old_name = db_connection.settings_dict["NAME"] db_connection.creation.create_test_db(verbosity=verbosity, prefix=prefix) return old_name ```