Skip to content

Commit c7bdcaf

Browse files
committed
use Pydantic to parse yaml
1 parent 52eb004 commit c7bdcaf

File tree

5 files changed

+103
-105
lines changed

5 files changed

+103
-105
lines changed

README.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,15 @@ Example of `config.yaml`:
3939
```yaml
4040
tables:
4141
# An example of additional Piccolo Admin configuration
42-
Actor:
42+
- table_name: actor
4343
visible_columns:
4444
- first_name
4545
visible_filters:
4646
- actor_id
4747
- first_name
4848
menu_group: Movies
4949
link_column: first_name
50-
Address:
50+
- table_name: address
5151
visible_columns:
5252
- address_id
5353
- address
@@ -58,22 +58,21 @@ tables:
5858
- city_id
5959
menu_group: Location
6060
rich_text_columns: address
61-
City:
61+
- table_name: city
6262
visible_columns:
6363
- city_id
6464
- city
6565
visible_filters:
6666
- city_id
6767
- city
6868
menu_group: Location
69-
Country:
69+
- table_name: country
7070
visible_columns:
7171
- country_id
7272
- country
7373
visible_filters:
7474
- country_id
7575
- country
76-
menu_group: Location
7776

7877
sidebar_links:
7978
Piccolo Admin: https://piccolo-admin.readthedocs.io/en/latest/index.html

app/main.py

Lines changed: 46 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,16 @@
11
import asyncio
22
import os
33

4-
import yaml
54
from hypercorn import Config
65
from hypercorn.asyncio import serve
7-
from piccolo.apps.user.tables import BaseUser
86
from piccolo.engine import PostgresEngine
9-
from piccolo.engine.sqlite import SQLiteEngine
107
from piccolo.table import create_db_tables
118
from piccolo.table_reflection import TableStorage
129
from piccolo_admin.endpoints import TableConfig, create_admin
1310
from piccolo_api.encryption.providers import XChaCha20Provider
1411
from piccolo_api.mfa.authenticator.provider import AuthenticatorProvider
15-
from piccolo_api.mfa.authenticator.tables import (
16-
AuthenticatorSecret as AuthenticatorSecret_,
17-
)
18-
from piccolo_api.session_auth.tables import SessionsBase
19-
20-
with open("config.yaml") as stream:
21-
try:
22-
admin_config = yaml.safe_load(stream)
23-
BASE_CONFIG = admin_config.get("tables")
24-
except yaml.YAMLError as exc:
25-
raise exc
26-
27-
DB = SQLiteEngine()
28-
29-
30-
class Sessions(SessionsBase, db=DB):
31-
pass
32-
33-
34-
class User(BaseUser, tablename="piccolo_user", db=DB):
35-
pass
36-
37-
38-
class AuthenticatorSecret(AuthenticatorSecret_, db=DB):
39-
pass
12+
from tables import AuthenticatorSecret, Sessions, User
13+
from utils import additional_config
4014

4115

4216
async def main():
@@ -72,79 +46,51 @@ async def main():
7246
await storage.reflect(schema_name="public")
7347

7448
# additional configuration of admin tables
75-
if BASE_CONFIG is not None:
76-
tables_to_show = [table.lower() for table in BASE_CONFIG]
77-
found_tables = [
78-
table
79-
for table in storage.tables.values()
80-
if table._meta.tablename in tables_to_show
81-
]
49+
if additional_config.tables is not None:
8250
admin_tables = []
83-
for table in found_tables:
84-
capitalize_table_name = table._meta.tablename.capitalize()
85-
# visible columns
86-
try:
87-
visible_columns = [
88-
column
89-
for column in table._meta.columns
90-
if column._meta.name
91-
in BASE_CONFIG[capitalize_table_name].get(
92-
"visible_columns", None
93-
)
94-
]
95-
except TypeError:
96-
visible_columns = None
97-
# visible filters
98-
try:
99-
visible_filters = [
100-
column
101-
for column in table._meta.columns
102-
if column._meta.name
103-
in BASE_CONFIG[capitalize_table_name].get(
104-
"visible_filters", None
51+
for config in additional_config.tables:
52+
for table in storage.tables.values():
53+
if table._meta.tablename == config.table_name:
54+
# visible columns
55+
visible_columns = [
56+
column
57+
for column in table._meta.columns
58+
if column._meta.name in config.visible_columns
59+
]
60+
# visible filters
61+
visible_filters = [
62+
column
63+
for column in table._meta.columns
64+
if column._meta.name in config.visible_filters
65+
]
66+
# rich text columns
67+
rich_text_columns = [
68+
column
69+
for column in table._meta.columns
70+
if column._meta.name == config.rich_text_columns
71+
]
72+
# link column
73+
try:
74+
link_column = [
75+
column
76+
for column in table._meta.columns
77+
if column._meta.name == config.link_column
78+
][0]
79+
except IndexError:
80+
link_column = None
81+
# menu_group
82+
menu_group = config.menu_group
83+
84+
admin_tables.append(
85+
TableConfig(
86+
table_class=table,
87+
visible_columns=visible_columns,
88+
visible_filters=visible_filters,
89+
rich_text_columns=rich_text_columns,
90+
link_column=link_column,
91+
menu_group=menu_group,
92+
)
10593
)
106-
]
107-
except TypeError:
108-
visible_filters = None
109-
# rich text columns
110-
try:
111-
rich_text_columns = [
112-
column
113-
for column in table._meta.columns
114-
if column._meta.name
115-
in BASE_CONFIG[capitalize_table_name].get(
116-
"rich_text_columns", None
117-
)
118-
]
119-
except TypeError:
120-
rich_text_columns = None
121-
# link column
122-
try:
123-
link_column = [
124-
column
125-
for column in table._meta.columns
126-
if column._meta.name
127-
== BASE_CONFIG[capitalize_table_name].get(
128-
"link_column", None
129-
)
130-
][0]
131-
except IndexError:
132-
link_column = None
133-
# menu_group
134-
menu_group = BASE_CONFIG[capitalize_table_name].get(
135-
"menu_group", None
136-
)
137-
138-
admin_tables.append(
139-
TableConfig(
140-
table_class=table,
141-
visible_columns=visible_columns,
142-
visible_filters=visible_filters,
143-
rich_text_columns=rich_text_columns,
144-
link_column=link_column,
145-
menu_group=menu_group,
146-
)
147-
)
14894
else:
14995
admin_tables = storage.tables.values()
15096

@@ -170,7 +116,7 @@ async def main():
170116
secret_table=AuthenticatorSecret,
171117
),
172118
],
173-
sidebar_links=admin_config.get("sidebar_links", None),
119+
sidebar_links=additional_config.sidebar_links or {},
174120
)
175121

176122
# Server

app/models.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import typing as t
2+
3+
from pydantic import BaseModel
4+
5+
6+
class AdminTable(BaseModel):
7+
table_name: t.Optional[str] = None
8+
visible_columns: t.Optional[list[str]] = None
9+
visible_filters: t.Optional[list[str]] = None
10+
rich_text_columns: t.Optional[str] = None
11+
link_column: t.Optional[str] = None
12+
menu_group: t.Optional[str] = None
13+
14+
15+
class AdditionalConfig(BaseModel):
16+
tables: t.Optional[list[AdminTable]] = None
17+
sidebar_links: t.Optional[dict[str, str]] = None

app/tables.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from piccolo.apps.user.tables import BaseUser
2+
from piccolo.engine.sqlite import SQLiteEngine
3+
from piccolo_api.mfa.authenticator.tables import (
4+
AuthenticatorSecret as AuthenticatorSecret_,
5+
)
6+
from piccolo_api.session_auth.tables import SessionsBase
7+
8+
DB = SQLiteEngine()
9+
10+
11+
class Sessions(SessionsBase, db=DB):
12+
pass
13+
14+
15+
class User(BaseUser, tablename="piccolo_user", db=DB):
16+
pass
17+
18+
19+
class AuthenticatorSecret(AuthenticatorSecret_, db=DB):
20+
pass

app/utils.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import typing as t
2+
3+
import yaml
4+
from models import AdditionalConfig
5+
6+
7+
def load_yaml() -> dict[str, t.Any]:
8+
with open("config.yaml") as stream:
9+
try:
10+
admin_config = yaml.safe_load(stream)
11+
return AdditionalConfig(**admin_config)
12+
except yaml.YAMLError as exc:
13+
raise exc
14+
15+
16+
additional_config = load_yaml()

0 commit comments

Comments
 (0)