{"id":2657,"library":"pastedeploy","title":"PasteDeploy","description":"PasteDeploy is a system for loading, configuring, and composing WSGI applications and servers from configuration files (typically INI files). It provides a standardized way to define and chain middleware, applications, and servers for Python web projects. The current version is 3.1.0, with ongoing maintenance for compatibility and minor enhancements, typically released yearly or as needed.","status":"active","version":"3.1.0","language":"en","source_language":"en","source_url":"https://github.com/Pylons/pastedeploy","tags":["wsgi","deployment","configuration","web development","middleware","pylons"],"install":[{"cmd":"pip install pastedeploy","lang":"bash","label":"Install stable release"}],"dependencies":[],"imports":[{"note":"PasteDeploy's main functions are typically imported directly from the `paste.deploy` namespace, not as submodules of `pastedeploy`.","wrong":"import pastedeploy.loadapp","symbol":"loadapp","correct":"from paste.deploy import loadapp"},{"symbol":"loadserver","correct":"from paste.deploy import loadserver"},{"symbol":"loadfilter","correct":"from paste.deploy import loadfilter"},{"symbol":"appconfig","correct":"from paste.deploy import appconfig"}],"quickstart":{"code":"import os\nimport sys\nfrom io import StringIO\nfrom paste.deploy import loadapp\n\n# --- 1. Create a dummy config.ini for demonstration ---\n# This config uses 'call:__main__:create_app' to reference an app factory\n# defined directly in this script. It also shows `eval` for env vars.\nconfig_content = \"\"\"\n[app:main]\nuse = call:__main__:create_app\nsome_setting = hello\nanother_setting = world\nmy_env_var = eval(os.environ.get('QUICKSTART_ENV_VAR', 'default_env_val'))\n\n[server:main]\nuse = egg:waitress#main  # Waitress is a common WSGI server\nhost = 127.0.0.1\nport = 8080\n\"\"\"\n\nwith open(\"config.ini\", \"w\") as f:\n    f.write(config_content)\n\n# --- 2. Define the WSGI application factory ---\n# This factory function will be called by PasteDeploy to create the app.\n# It receives `global_conf` and other settings from the INI file.\ndef create_app(global_conf, some_setting, another_setting, my_env_var):\n    # Using wsgiref.simple_server.demo_app as a placeholder WSGI app\n    from wsgiref.simple_server import demo_app\n    print(f\"[create_app] App factory called with global_conf: {global_conf}\")\n    print(f\"[create_app]   some_setting: {some_setting}\")\n    print(f\"[create_app]   another_setting: {another_setting}\")\n    print(f\"[create_app]   my_env_var (from os.environ via eval): {my_env_var}\")\n    return demo_app\n\n# --- 3. Load the application using paste.deploy ---\nprint(\"\\n--- Attempting to load WSGI application from config.ini ---\")\n\n# Set an environment variable for testing `eval` in the config.\nos.environ['QUICKSTART_ENV_VAR'] = 'set_from_env_value'\n\n# `global_conf` is passed to the app factory (read-only configuration).\n# The '#main' refers to the `[app:main]` section in config.ini.\ntry:\n    app = loadapp('config:config.ini#main', global_conf={'process_id': os.getpid(), 'api_key': os.environ.get('PASTEDEPLOY_API_KEY', '')})\n    print(f\"Successfully loaded WSGI application: {app}\")\n\n    # Verify the loaded app is callable (a basic WSGI check)\n    assert callable(app)\n    # A minimal test of the WSGI app (not actually running a server)\n    response_body = []\n    def start_response(status, headers):\n        pass\n    list(app({'REQUEST_METHOD': 'GET', 'PATH_INFO': '/'}, start_response))\n    print(\"WSGI app is callable and passes a basic test.\")\n\nfinally:\n    # --- 4. Clean up (important for a self-contained quickstart) ---\n    os.remove(\"config.ini\")\n    if 'QUICKSTART_ENV_VAR' in os.environ:\n        del os.environ['QUICKSTART_ENV_VAR']\n    print(\"\\n--- Cleanup: Removed config.ini and environment variable ---\")\n","lang":"python","description":"This quickstart demonstrates how to define a WSGI application factory, configure it in an `INI` file, and load it using `paste.deploy.loadapp`. It also shows how to pass `global_conf` values and use `eval()` to pull environment variables into the configuration, which is a common pattern for sensitive values (though with security caveats as noted in warnings). Running this code will create a temporary `config.ini`, load a dummy WSGI app, print its configuration, and then clean up."},"warnings":[{"fix":"Avoid `eval()` for dynamic configuration values if the configuration source is untrusted. Prefer explicit environment variable lookups or secure configuration management systems. If `eval()` is necessary, ensure the configuration file's integrity and source are highly trusted.","message":"Using `eval()` directly in PasteDeploy configuration files (`.ini`) can pose a security risk. If an untrusted user can modify the configuration file, they could inject and execute arbitrary Python code.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Treat `global_conf` as read-only. If a component needs to store or modify its own state, use `local_conf` or instance attributes. Avoid passing sensitive information directly in `global_conf` from a file; prefer environment variables or secure vault integrations, potentially accessed within the app factory.","message":"The `global_conf` dictionary passed to app factories is typically a shallow copy or reference to the entire configuration. Modifying `global_conf` within an app factory or middleware can lead to unexpected side effects, especially if the same `global_conf` object is reused across multiple components.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Upgrade your entire project to Python 3. Ensure all dependencies are Python 3 compatible. Review `pastedeploy`'s changelog for `2.0.0` and subsequent versions for specific API changes related to Python 3. The `pastedeploy` package itself requires Python 3.7+ as of version 3.x.","message":"Versions of PasteDeploy prior to 2.0.0 supported Python 2. Versions 2.0.0 and later are Python 3-only. Migrating from older projects will require significant code changes for Python 3 compatibility, beyond just updating PasteDeploy itself.","severity":"breaking","affected_versions":"< 2.0.0 to >= 2.0.0"},{"fix":"Understand the difference: `egg:` is for applications installed as Python packages that register `setuptools` entry points (e.g., `pastedeploy.app_factory` entry points). `call:` is for directly importing a function or callable from a module path. For local development or simple scripts, `call:` is often easier to use directly with a Python file, while `egg:` is common for reusable middleware or frameworks.","message":"PasteDeploy configuration for application factories can use `egg:package_name#entry_point` or `call:module_name:factory_function`. Developers often confuse these, especially how `egg:` relies on `setuptools` entry points vs. `call:` which requires the module to be importable and the factory function directly discoverable.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-10T00:00:00.000Z","next_check":"2026-07-09T00:00:00.000Z"}