# AppConfig lifecycle: Class Definition, Instantiation, and Runtime Usage

| Step | Context / Object (Class or Module) | Method / Mechanism Invoked | What Python is Doing (Action) | MRO Printed by Your `print` Loop |
|---:|---|---|---|---|
| 1 | Module `my_app_config` (`__main__`) | Module loading | Starts executing `my_app_config.py` top-level statements | — |
| 2 | Module import system | `import app_config` | Resolves and begins importing `app_config` (creates module object, executes its top-level code) | — |
| 3 | Module `app_config` | `from __future__ import annotations` | Enables postponed evaluation of annotations in this module | — |
| 4 | Module import system | `import app_config_meta` | Resolves and begins importing `app_config_meta` (executes its top-level code) | — |
| 5 | Module `app_config_meta` | Class statement execution | Defines `AppConfigMeta` (metaclass object created by `type`) | — |
| 6 | Module `app_config` | `from typing import Any` | Imports `Any` (no class creation side effects) | — |
| 7 | Module import system | `import attr_dict` | Imports `attr_dict` and executes it | — |
| 8 | Module `attr_dict` | Class statement execution | Defines `AttrDict` class object (regular class, metaclass `type`) | — |
| 9 | Module import system | `import auto_prolog` | Imports `auto_prolog` and executes it | — |
|10 | Module `auto_prolog` | Class statement execution | Defines `AutoProlog` class object (regular class, metaclass `type`) | — |
|11 | Class being defined: `AppConfig` | Metaclass selection | Determines metaclass for `AppConfig` is `AppConfigMeta` (explicitly provided) | — |
|12 | Class being defined: `AppConfig` | `AppConfigMeta.__prepare__` (inherited from `type`) | Creates the class namespace mapping (a plain `dict`) | — |
|13 | Class body: `AppConfig` | Class body execution | Executes the body of `AppConfig`, defining `__init_subclass__` in the namespace | — |
|14 | Class creation: `AppConfig` | `AppConfigMeta.__new__` (inherited from `type.__new__`) | Allocates/creates the `AppConfig` class object; computes C3 MRO | — |
|15 | Class creation: `AppConfig` | Descriptor naming phase | Calls `__set_name__` on any descriptors defined in `AppConfig`’s body (none here) | — |
|16 | Class creation: `AppConfig` | Base hooks phase | Calls `__init_subclass__` of `AppConfig`’s bases (only if they define it; typically none) | — |
|17 | Class creation: `AppConfig` | `AppConfigMeta.__init__` | Runs your metaclass `__init__`, then iterates `AppConfig.__mro__` and prints names | `AppConfig → AttrDict → AutoProlog → object` |
|18 | Module `app_config` | Module finalization | `app_config` import completes; `AppConfig` is now available to importers | — |
|19 | Module `my_app_config` (`__main__`) | `from app_config import AppConfig` | Binds imported `AppConfig` name in `my_app_config` | — |
|20 | Module import system | `import config_var` | Imports `config_var` (so `ConfigVarDef` becomes available) | — |
|21 | Module `config_var` | Class statement execution | Defines `ConfigVarDef` class object | — |
|22 | Module `my_app_config` (`__main__`) | `from config_var import ConfigVarDef` | Binds `ConfigVarDef` name in `my_app_config` | — |
|23 | Class being defined: `MyAppConfig` | Metaclass selection | Determines metaclass for `MyAppConfig` is `AppConfigMeta` (inherited from base class `AppConfig`) | — |
|24 | Class being defined: `MyAppConfig` | `AppConfigMeta.__prepare__` (inherited from `type`) | Creates `MyAppConfig` namespace mapping (plain `dict`) | — |
|25 | Class body: `MyAppConfig` | Class body execution | Evaluates `var1: ConfigVarDef = ConfigVarDef()` → instantiates `ConfigVarDef` now | — |
|26 | Object: `ConfigVarDef` instance (assigned to `var1`) | `ConfigVarDef.__init__` | Runs initializer for the descriptor instance created in the class body | — |
|27 | Class creation: `MyAppConfig` | `AppConfigMeta.__new__` (inherited from `type.__new__`) | Creates the `MyAppConfig` class object; computes C3 MRO | — |
|28 | Class creation: `MyAppConfig` | Descriptor naming phase | Calls `ConfigVarDef.__set_name__(owner=MyAppConfig, name="var1")` | — |
|29 | Class creation: `MyAppConfig` | Base hooks phase | Calls `AppConfig.__init_subclass__(cls=MyAppConfig, **kwargs)` | — |
|30 | Hook execution: `AppConfig` | `AppConfig.__init_subclass__` | Your loop iterates `MyAppConfig.__mro__` and prints names | `MyAppConfig → AppConfig → AttrDict → AutoProlog → object` |
|31 | Class creation: `MyAppConfig` | `AppConfigMeta.__init__` | Metaclass `__init__` runs for `MyAppConfig`, prints its MRO again | `MyAppConfig → AppConfig → AttrDict → AutoProlog → object` |
|32 | Module `my_app_config` (`__main__`) | Instantiation | Executes `my_app_config = MyAppConfig()` | — |
|33 | Metaclass call machinery | `type.__call__` (via `AppConfigMeta`, unless overridden) | Allocates instance: calls `MyAppConfig.__new__`, then `MyAppConfig.__init__` | — |

## Phase 1: Class Definition (`MyAppConfig(AppConfig)`)

*This phase occurs **once**, as soon as Python executes the `class MyAppConfig(AppConfig):` block.*

MyAppConfig is defined as a subclass of AppConfig and contains ConfigVarDef attribute (defined with the configvar() function). During this phase, Python processes the class body, creating the class object and setting up the descriptor and metaclass machinery.

| Order | Method Called | Actor | Action Performed |
| :--- | :--- | :--- | :--- |
| **1** | `ConfigVarDef.__init__` | **Descriptor** | ConfigVarDef is a descriptor object. It is created and stored in the MyAppConfig class's temporary namespace. Initialize config directives with values provided or to default |
| **2** | `type.__new__` | **Metaclass** | Python allocates the `MyAppConfig` class object. It identifies `AppConfigMeta` as the controller. |
| **3** | `ConfigVarDef.__set_name__` | **Descriptor** | **Crucial:** Python binds the descriptor to the class. Set attribute _name on ConfigVarDef instance, look at type annotation and determine the type set by user, check if the type annotation denotes a list and in this case set _split_to_list in this case. Look up a doc string for the attribute and set the help directive if a documentation is found.  |
| **4** | `BaseMeta.__init__` | **Metaclass** | The metaclass initializes the newly created class object. |
| **5** | `AppConfig.__init_subclass__` | **Parent Class** | The AppConfig class hook is triggered to allow customization of the new subclass. Set AppConfig._config_var_defs with an OrderedDict and AppConfig._autoprolog_var_names |

---

## Phase 2: Object Instantiation (`app_config = MyAppConfig()`)
*This phase occurs **every time** you call the class to create a new instance.*

| Order | Method Called | Actor | Action Performed |
| :--- | :--- | :--- | :--- |
| **6** | `type.__call__` | **Metaclass** | Since `MyAppConfig` is an instance of `BaseMeta`, the `()` operator triggers the metaclass orchestration. |
| **7** | `object.__new__` | **Instance** | Memory is allocated for the `MyAppConfig` instance. The object now exists in a "raw" state. |
| **8** | `object.__init__` | **Instance** | The instance is initialized. call `MyAppConfig.__init__()`. |

---

## Phase 3: Runtime Usage (Descriptor Protocol)
*This occurs after instantiation, whenever a ConfigVarDef attribute is accessed.*

| Order | Method Called | Actor | Action Performed |
| :--- | :--- | :--- | :--- |
| **9** | `ConfigVarDef.__get__` | **Descriptor** | Triggered when reading an ConfigVarDef attribute of an instance of `MyAppConfig`. Intercepts the lookup. |
| **10** | `ConfigVarDef.__set__` | **Descriptor** | Triggered when assigning a ConfigVarDef attribute of an instance of `MyAppConfig`. Intercepts the write. |

---

### Key Technical Summary
* **Metaclass vs. `__init_subclass__`**: The Metaclass `__init__` runs **before** `__init_subclass__`.
* **Naming**: `__set_name__` is called automatically by `type.__new__`, ensuring the descriptor knows its name before the metaclass or subclass hooks start.
* **Instance creation**: The Metaclass's `__call__` is the "boss" that decides how `__new__` and `__init__` are invoked for the instance.