Skip to content

Commit 1c9ca9d

Browse files
📝 Add docstrings to MPT-16255/Seeding-for-catalog
Docstrings generation was requested by @albertsola. * #152 (comment) The following files were modified: * `seed/accounts/api_tokens.py` * `seed/accounts/buyer.py` * `seed/accounts/licensee.py` * `seed/accounts/module.py` * `seed/accounts/seller.py` * `seed/accounts/user_group.py` * `seed/catalog/authorization.py` * `seed/catalog/catalog.py` * `seed/catalog/item.py` * `seed/catalog/listing.py` * `seed/catalog/price_list.py` * `seed/catalog/product.py` * `seed/context.py` * `seed/helper.py` * `seed/seed_api.py` * `tests/seed/catalog/test_authorization.py` * `tests/seed/catalog/test_listing.py` * `tests/seed/catalog/test_price_list.py` * `tests/seed/catalog/test_product.py`
1 parent e80c818 commit 1c9ca9d

19 files changed

Lines changed: 406 additions & 74 deletions

seed/accounts/api_tokens.py

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,14 @@ async def get_api_token(
1616
context: Context = Provide[Container.context],
1717
mpt_ops: AsyncMPTClient = Provide[Container.mpt_operations],
1818
) -> ApiToken | None:
19-
"""Get API token from context or fetch from API."""
19+
"""
20+
Retrieve the ApiToken from context if present; otherwise fetch it from the API and store it in context.
21+
22+
If the token is fetched, it is saved in the context resources under "accounts.api_token" and "accounts.api_token.id" is updated.
23+
24+
Returns:
25+
`ApiToken` if found or fetched, `None` if no token id is present in context.
26+
"""
2027
api_token_id = context.get_string("accounts.api_token.id")
2128
if not api_token_id:
2229
return None
@@ -36,7 +43,19 @@ async def get_api_token(
3643
def build_api_token_data(
3744
context: Context = Provide[Container.context],
3845
) -> dict[str, object]:
39-
"""Get API token data dictionary for creation."""
46+
"""
47+
Builds the dictionary of fields required to create an API token used for end-to-end testing.
48+
49+
The returned mapping includes:
50+
- `account`: `{"id": <CLIENT_ACCOUNT_ID environment variable>}`
51+
- `name`: token display name
52+
- `description`: token description
53+
- `icon`: token icon (empty string when not set)
54+
- `modules`: list containing a module object with `id` read from the context key "accounts.module.id"
55+
56+
Returns:
57+
dict[str, object]: The payload suitable for API token creation.
58+
"""
4059
account_id = os.getenv("CLIENT_ACCOUNT_ID")
4160
module_id = context.get_string("accounts.module.id")
4261
return {
@@ -53,7 +72,14 @@ async def init_api_token(
5372
context: Context = Provide[Container.context],
5473
mpt_ops: AsyncMPTClient = Provide[Container.mpt_operations],
5574
) -> ApiToken:
56-
"""Get or create API token."""
75+
"""
76+
Ensure an API token exists for the account, creating and persisting one if necessary.
77+
78+
If an API token is not already available, creates a new token and stores it in the context resource "accounts.api_token" and updates "accounts.api_token.id".
79+
80+
Returns:
81+
ApiToken: The existing or newly created API token instance.
82+
"""
5783
api_token = await get_api_token(context=context, mpt_ops=mpt_ops)
5884
if api_token is None:
5985
logger.debug("Creating API token ...")
@@ -72,4 +98,4 @@ async def seed_api_token() -> None:
7298
"""Seed API token."""
7399
logger.debug("Seeding API token ...")
74100
await init_api_token()
75-
logger.debug("Seeding API token completed.")
101+
logger.debug("Seeding API token completed.")

seed/accounts/buyer.py

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,14 @@ async def get_buyer(
1919
context: Context = Provide[Container.context],
2020
mpt_operations: AsyncMPTClient = Provide[Container.mpt_operations],
2121
) -> Buyer | None:
22-
"""Get buyer from context or fetch from API."""
22+
"""
23+
Retrieve the buyer identified by "accounts.buyer.id" from the context or fetch it from the API and cache it.
24+
25+
If the context does not contain "accounts.buyer.id", returns `None`. If the id exists but no valid Buyer instance is cached, fetches the buyer from the API, stores it in the context under "accounts.buyer", updates "accounts.buyer.id" with the fetched buyer's id, and returns the Buyer.
26+
27+
Returns:
28+
Buyer or `None` if "accounts.buyer.id" is not set in the context.
29+
"""
2330
buyer_id = context.get_string("accounts.buyer.id")
2431
if not buyer_id:
2532
return None
@@ -37,7 +44,21 @@ async def get_buyer(
3744

3845
@inject
3946
def build_buyer_data(context: Context = Provide[Container.context]) -> dict[str, object]:
40-
"""Build buyer data dictionary for creation."""
47+
"""
48+
Builds the payload dictionary used to create a buyer in the MPT API.
49+
50+
Reads CLIENT_ACCOUNT_ID from the environment and `accounts.seller.id` from the provided context to populate required account and seller references.
51+
52+
Parameters:
53+
context (Context): Application context used to read `accounts.seller.id`.
54+
55+
Returns:
56+
dict[str, object]: Buyer data payload including name, account, sellers, contact, and address.
57+
58+
Raises:
59+
ValueError: If CLIENT_ACCOUNT_ID environment variable is missing.
60+
ValueError: If `accounts.seller.id` is not found in the context.
61+
"""
4162
buyer_account_id = os.getenv("CLIENT_ACCOUNT_ID")
4263
if not buyer_account_id:
4364
raise ValueError("CLIENT_ACCOUNT_ID environment variable is required")
@@ -68,7 +89,15 @@ async def init_buyer(
6889
context: Context = Provide[Container.context],
6990
mpt_operations: AsyncMPTClient = Provide[Container.mpt_operations],
7091
) -> Buyer:
71-
"""Get or create buyer."""
92+
"""
93+
Ensure a Buyer exists in the provided context, creating one via the API if none is present.
94+
95+
Returns:
96+
Buyer: The existing or newly created Buyer instance.
97+
98+
Raises:
99+
ValueError: If buyer creation via the API fails.
100+
"""
72101
buyer = await get_buyer(context=context, mpt_operations=mpt_operations)
73102
if buyer is None:
74103
buyer_data = build_buyer_data(context=context)
@@ -91,4 +120,4 @@ async def seed_buyer() -> None:
91120
"""Seed buyer."""
92121
logger.debug("Seeding buyer ...")
93122
await init_buyer()
94-
logger.debug("Seeding buyer completed.")
123+
logger.debug("Seeding buyer completed.")

seed/accounts/licensee.py

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,14 @@ async def get_licensee(
1919
context: Context = Provide[Container.context],
2020
mpt_client: AsyncMPTClient = Provide[Container.mpt_client],
2121
) -> Licensee | None:
22-
"""Get licensee from context or fetch from API."""
22+
"""
23+
Retrieve the current licensee from the context or fetch it from the MPT API and cache it in the context.
24+
25+
If a licensee is not present in the context but a licensee id exists, the function fetches the licensee from the MPT API, stores the licensee as the context resource "accounts.licensee", and updates "accounts.licensee.id" in the context.
26+
27+
Returns:
28+
Licensee | None: `Licensee` instance if found, `None` if no licensee id is present.
29+
"""
2330
licensee_id = context.get_string("accounts.licensee.id")
2431
if not licensee_id:
2532
return None
@@ -39,7 +46,20 @@ async def get_licensee(
3946
def build_licensee_data( # noqa: WPS238
4047
context: Context = Provide[Container.context],
4148
) -> dict[str, object]:
42-
"""Get licensee data dictionary for creation."""
49+
"""
50+
Constructs a licensee payload dictionary used to create a licensee.
51+
52+
Parameters:
53+
context (Context): Context used to read required values: `accounts.seller.id`, `accounts.buyer.id`, and the `accounts.user_group` resource.
54+
55+
Returns:
56+
dict[str, object]: A dictionary containing licensee fields required by the API (name, address, seller, buyer, account, eligibility, groups, type, status, and defaultLanguage).
57+
58+
Raises:
59+
ValueError: If the environment variable `CLIENT_ACCOUNT_ID` is not set.
60+
ValueError: If `accounts.seller.id` or `accounts.buyer.id` is missing from the context.
61+
ValueError: If the `accounts.user_group` resource is missing from the context.
62+
"""
4363
account_id = os.getenv("CLIENT_ACCOUNT_ID")
4464
if not account_id:
4565
raise ValueError("CLIENT_ACCOUNT_ID environment variable is required")
@@ -79,7 +99,17 @@ async def init_licensee(
7999
context: Context = Provide[Container.context],
80100
mpt_client: AsyncMPTClient = Provide[Container.mpt_client],
81101
) -> Licensee:
82-
"""Get or create licensee."""
102+
"""
103+
Ensure a licensee exists for the current context, creating one if none is present.
104+
105+
If no licensee is found in the provided context, attempts to create one using the MPT client and the prepared licensee data, then stores the created licensee in the context.
106+
107+
Returns:
108+
The Licensee instance associated with the context.
109+
110+
Raises:
111+
ValueError: If licensee creation fails.
112+
"""
83113
licensee = await get_licensee(context=context, mpt_client=mpt_client)
84114
if licensee is None:
85115
licensee_data = build_licensee_data(context=context)
@@ -102,4 +132,4 @@ async def seed_licensee() -> None:
102132
"""Seed licensee."""
103133
logger.debug("Seeding licensee ...")
104134
await init_licensee()
105-
logger.info("Seeding licensee completed.")
135+
logger.info("Seeding licensee completed.")

seed/accounts/module.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,14 @@ async def get_module(
1616
context: Context = Provide[Container.context],
1717
mpt_operations: AsyncMPTClient = Provide[Container.mpt_operations],
1818
) -> Module | None:
19-
"""Get module from context or fetch from API."""
19+
"""
20+
Retrieve the Module stored in the context or fetch it from the API if not cached.
21+
22+
If the context does not contain "accounts.module.id", returns None. When a cached resource is absent or not a Module, the function fetches the module from the API and stores it in the context.
23+
24+
Returns:
25+
Module if found or fetched, `None` if "accounts.module.id" is not set.
26+
"""
2027
module_id = context.get_string("accounts.module.id")
2128
if not module_id:
2229
return None
@@ -37,7 +44,14 @@ async def refresh_module(
3744
context: Context = Provide[Container.context],
3845
mpt_operations: AsyncMPTClient = Provide[Container.mpt_operations],
3946
) -> Module | None:
40-
"""Refresh module in context (always fetch)."""
47+
"""
48+
Ensure the context contains a current "Access Management" Module by fetching it if missing.
49+
50+
If the context has no module, query the API for modules named "Access Management". Cache the first found Module in the context under "accounts.module" and store its id at "accounts.module.id". Logs a warning and returns None if no suitable Module is found.
51+
52+
Returns:
53+
Module if available, None otherwise.
54+
"""
4155
module = await get_module(context=context, mpt_operations=mpt_operations)
4256
if module is None:
4357
filtered_modules = mpt_operations.accounts.modules.filter(
@@ -69,4 +83,4 @@ async def seed_module() -> Module:
6983
raise ValueError("Could not seed module: no valid Module found.")
7084
return refreshed
7185
logger.debug("Seeding module completed.")
72-
return existing_module
86+
return existing_module

seed/accounts/seller.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,14 @@ async def get_seller(
1717
context: Context = Provide[Container.context],
1818
mpt_operations: AsyncMPTClient = Provide[Container.mpt_operations],
1919
) -> Seller | None:
20-
"""Get seller from context or fetch from API."""
20+
"""
21+
Retrieve the Seller stored in the provided context or fetch it from the API and cache it in context.
22+
23+
If the context does not contain a seller id ("accounts.seller.id"), returns `None`. If a seller id exists but the context has no matching Seller resource, fetches the Seller using the provided MPT client, stores the Seller in the context under "accounts.seller" and updates "accounts.seller.id" with the Seller's id before returning it.
24+
25+
Returns:
26+
Seller | None: The Seller retrieved from context or API, or `None` if no seller id is present.
27+
"""
2128
seller_id = context.get_string("accounts.seller.id")
2229
if not seller_id:
2330
return None
@@ -57,7 +64,14 @@ async def init_seller(
5764
context: Context = Provide[Container.context],
5865
mpt_operations: AsyncMPTClient = Provide[Container.mpt_operations],
5966
) -> Seller | None:
60-
"""Get or create seller. Returns Seller if successful, None otherwise."""
67+
"""
68+
Ensure a seller exists in the provided context by retrieving it or creating a new one.
69+
70+
If no seller is found in context, a seller will be created via the MPT API. On successful creation the function sets the created Seller in the context under "accounts.seller" and its id under "accounts.seller.id".
71+
72+
Returns:
73+
`Seller` if the seller was retrieved or created, `None` otherwise.
74+
"""
6175
seller = await get_seller(context=context, mpt_operations=mpt_operations)
6276
if seller is None:
6377
logger.debug("Creating seller ...")
@@ -79,4 +93,4 @@ async def seed_seller() -> None:
7993
"""Seed seller."""
8094
logger.debug("Seeding seller ...")
8195
await init_seller()
82-
logger.debug("Seeding seller completed.")
96+
logger.debug("Seeding seller completed.")

seed/accounts/user_group.py

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,12 @@ async def get_user_group(
1717
context: Context = Provide[Container.context],
1818
mpt_operations: AsyncMPTClient = Provide[Container.mpt_operations],
1919
) -> UserGroup | None:
20-
"""Get user group from context or fetch from API."""
20+
"""
21+
Retrieve a UserGroup from the context or fetch it from the API when not present in the context.
22+
23+
Returns:
24+
The retrieved `UserGroup` if available (from context or fetched), `None` if no user group ID is set in the context.
25+
"""
2126
user_group_id = context.get_string("accounts.user_group.id")
2227
if not user_group_id:
2328
return None
@@ -37,7 +42,21 @@ async def get_user_group(
3742
def build_user_group_data(
3843
context: Context = Provide[Container.context],
3944
) -> dict[str, object]:
40-
"""Get user group data dictionary for creation."""
45+
"""
46+
Builds the payload dictionary used to create a UserGroup.
47+
48+
Returns:
49+
dict: Payload with keys:
50+
- name: display name for the user group
51+
- account: dict containing the account `id` from the CLIENT_ACCOUNT_ID environment variable
52+
- buyers: currently `None`
53+
- logo: string (empty by default)
54+
- description: textual description
55+
- modules: list containing a dict with the module `id` read from context ("accounts.module.id")
56+
57+
Raises:
58+
ValueError: If the CLIENT_ACCOUNT_ID environment variable is not set.
59+
"""
4160
account_id = os.getenv("CLIENT_ACCOUNT_ID")
4261
if not account_id:
4362
raise ValueError("CLIENT_ACCOUNT_ID environment variable is required")
@@ -57,7 +76,14 @@ async def init_user_group(
5776
context: Context = Provide[Container.context],
5877
mpt_operations: AsyncMPTClient = Provide[Container.mpt_operations],
5978
) -> UserGroup | None:
60-
"""Get or create user group."""
79+
"""
80+
Ensure a UserGroup exists for the current context, creating and storing one if it does not.
81+
82+
If an existing UserGroup is present in the context it is returned unchanged. When creation succeeds the new UserGroup is saved in the context under "accounts.user_group" and "accounts.user_group.id".
83+
84+
Returns:
85+
UserGroup | None: The retrieved or newly created `UserGroup`, or `None` if creation failed or no group could be obtained.
86+
"""
6187
user_group = await get_user_group(context=context, mpt_operations=mpt_operations)
6288
if user_group is not None:
6389
logger.info("User group already exists: %s", user_group.id)
@@ -82,4 +108,4 @@ async def seed_user_group() -> UserGroup | None:
82108
logger.debug("Seeding user group ...")
83109
user_group = await init_user_group()
84110
logger.debug("Seeding user group completed.")
85-
return user_group
111+
return user_group

seed/catalog/authorization.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,24 @@
1010

1111

1212
async def seed_authorization() -> None:
13-
"""Seed authorization."""
13+
"""
14+
Ensure the catalog authorization resource is seeded.
15+
16+
Creates the authorization resource if it does not exist and stores its identifier under the context key "catalog.authorization.id".
17+
"""
1418
await init_resource("catalog.authorization.id", create_authorization)
1519

1620

1721
async def create_authorization(
1822
operations: AsyncMPTClient = Provide[Container.mpt_operations],
1923
context: Context = Provide[Container.context],
2024
) -> Authorization:
21-
"""Creates an authorization."""
25+
"""
26+
Create an authorization in the catalog using required IDs from the provided context.
27+
28+
Returns:
29+
Authorization: The created Authorization object returned by the catalog service.
30+
"""
2231
product_id = require_context_id(context, "catalog.product.id", "Create authorization")
2332
seller_id = require_context_id(context, "accounts.seller.id", "Create authorization")
2433
account_id = require_context_id(context, "accounts.account.id", "Create authorization")
@@ -35,4 +44,4 @@ async def create_authorization(
3544
"name": "E2E Seeded",
3645
"vendor": {"id": account_id},
3746
}
38-
return await operations.catalog.authorizations.create(authorization_data)
47+
return await operations.catalog.authorizations.create(authorization_data)

seed/catalog/catalog.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,15 @@
99

1010

1111
async def seed_catalog() -> None:
12-
"""Seed catalog data including products, item groups, and parameters."""
12+
"""
13+
Seed catalog data in a defined sequence.
14+
15+
Seeds products first, then authorization data, then price lists, and finally listings to ensure dependent catalog data is created in order.
16+
"""
1317
logger.debug("Seeding catalog ...")
1418
await seed_product()
1519
await seed_authorization()
1620
await seed_price_list()
1721
await seed_listing()
1822

19-
logger.debug("Seeded catalog completed.")
23+
logger.debug("Seeded catalog completed.")

0 commit comments

Comments
 (0)