ppbase 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ppbase-0.1.0/PKG-INFO +20 -0
- ppbase-0.1.0/README.md +270 -0
- ppbase-0.1.0/ppbase/__init__.py +17 -0
- ppbase-0.1.0/ppbase/__main__.py +744 -0
- ppbase-0.1.0/ppbase/admin/dist/assets/_id_-DZJDi57q.js +65 -0
- ppbase-0.1.0/ppbase/admin/dist/assets/arrow-right-CFjpsotf.js +6 -0
- ppbase-0.1.0/ppbase/admin/dist/assets/badge-_xdB2pxd.js +1 -0
- ppbase-0.1.0/ppbase/admin/dist/assets/breadcrumb-BaA-PKls.js +1 -0
- ppbase-0.1.0/ppbase/admin/dist/assets/button-cOPHmTk3.js +1 -0
- ppbase-0.1.0/ppbase/admin/dist/assets/check-Bg_MTf5r.js +6 -0
- ppbase-0.1.0/ppbase/admin/dist/assets/checkbox-2bYeilqt.js +1 -0
- ppbase-0.1.0/ppbase/admin/dist/assets/chevron-left-iXTKBRUV.js +6 -0
- ppbase-0.1.0/ppbase/admin/dist/assets/circle-alert-C7lepEss.js +6 -0
- ppbase-0.1.0/ppbase/admin/dist/assets/collection-editor-7ZuVyhTs.js +19 -0
- ppbase-0.1.0/ppbase/admin/dist/assets/dashboard-DqfGINoH.js +16 -0
- ppbase-0.1.0/ppbase/admin/dist/assets/empty-state-BzTkdxCW.js +1 -0
- ppbase-0.1.0/ppbase/admin/dist/assets/index-BMDse7c9.js +1 -0
- ppbase-0.1.0/ppbase/admin/dist/assets/index-DhFFCX27.js +1 -0
- ppbase-0.1.0/ppbase/admin/dist/assets/index-hkEk4VxW.js +177 -0
- ppbase-0.1.0/ppbase/admin/dist/assets/index-rtXfCyLG.css +1 -0
- ppbase-0.1.0/ppbase/admin/dist/assets/input-DnqvRCla.js +1 -0
- ppbase-0.1.0/ppbase/admin/dist/assets/label--pbF4JwP.js +1 -0
- ppbase-0.1.0/ppbase/admin/dist/assets/layout-aHUI7-5O.js +26 -0
- ppbase-0.1.0/ppbase/admin/dist/assets/loading-spinner-C8DEbd0p.js +6 -0
- ppbase-0.1.0/ppbase/admin/dist/assets/login-WgIq_Ce2.js +1 -0
- ppbase-0.1.0/ppbase/admin/dist/assets/logs-BFWqXhLR.js +26 -0
- ppbase-0.1.0/ppbase/admin/dist/assets/migrations-pd8sJONp.js +6 -0
- ppbase-0.1.0/ppbase/admin/dist/assets/refresh-cw-CZn6LysZ.js +6 -0
- ppbase-0.1.0/ppbase/admin/dist/assets/select-DKsAFmxr.js +11 -0
- ppbase-0.1.0/ppbase/admin/dist/assets/settings-D35l31hS.js +1 -0
- ppbase-0.1.0/ppbase/admin/dist/assets/setup-B_Q4D5QZ.js +1 -0
- ppbase-0.1.0/ppbase/admin/dist/assets/sheet-C__RuiiA.js +1 -0
- ppbase-0.1.0/ppbase/admin/dist/assets/table-2-D8RuQ792.js +6 -0
- ppbase-0.1.0/ppbase/admin/dist/assets/use-logs-_ol7ma3T.js +1 -0
- ppbase-0.1.0/ppbase/admin/dist/assets/use-migrations-CAqT4Y4N.js +1 -0
- ppbase-0.1.0/ppbase/admin/dist/assets/use-settings-DMhcnSJU.js +1 -0
- ppbase-0.1.0/ppbase/admin/dist/fonts/Inter-Variable.woff2 +0 -0
- ppbase-0.1.0/ppbase/admin/dist/index.html +13 -0
- ppbase-0.1.0/ppbase/api/__init__.py +1 -0
- ppbase-0.1.0/ppbase/api/admins.py +349 -0
- ppbase-0.1.0/ppbase/api/collections.py +496 -0
- ppbase-0.1.0/ppbase/api/deps.py +246 -0
- ppbase-0.1.0/ppbase/api/files.py +647 -0
- ppbase-0.1.0/ppbase/api/health.py +13 -0
- ppbase-0.1.0/ppbase/api/logs.py +190 -0
- ppbase-0.1.0/ppbase/api/migrations.py +265 -0
- ppbase-0.1.0/ppbase/api/realtime.py +243 -0
- ppbase-0.1.0/ppbase/api/record_auth.py +1469 -0
- ppbase-0.1.0/ppbase/api/records.py +1587 -0
- ppbase-0.1.0/ppbase/api/router.py +90 -0
- ppbase-0.1.0/ppbase/api/settings.py +371 -0
- ppbase-0.1.0/ppbase/app.py +356 -0
- ppbase-0.1.0/ppbase/config.py +97 -0
- ppbase-0.1.0/ppbase/core/__init__.py +5 -0
- ppbase-0.1.0/ppbase/core/id_generator.py +25 -0
- ppbase-0.1.0/ppbase/db/__init__.py +5 -0
- ppbase-0.1.0/ppbase/db/bootstrap.py +399 -0
- ppbase-0.1.0/ppbase/db/engine.py +87 -0
- ppbase-0.1.0/ppbase/db/schema_manager.py +497 -0
- ppbase-0.1.0/ppbase/db/system_tables.py +266 -0
- ppbase-0.1.0/ppbase/ext/__init__.py +39 -0
- ppbase-0.1.0/ppbase/ext/events.py +501 -0
- ppbase-0.1.0/ppbase/ext/flask_like_pb.py +990 -0
- ppbase-0.1.0/ppbase/ext/hooks.py +137 -0
- ppbase-0.1.0/ppbase/ext/loading.py +47 -0
- ppbase-0.1.0/ppbase/ext/record_repository.py +102 -0
- ppbase-0.1.0/ppbase/ext/registry.py +334 -0
- ppbase-0.1.0/ppbase/middleware/__init__.py +1 -0
- ppbase-0.1.0/ppbase/middleware/auth.py +6 -0
- ppbase-0.1.0/ppbase/middleware/cors.py +23 -0
- ppbase-0.1.0/ppbase/middleware/request_logger.py +84 -0
- ppbase-0.1.0/ppbase/models/__init__.py +5 -0
- ppbase-0.1.0/ppbase/models/collection.py +237 -0
- ppbase-0.1.0/ppbase/models/field_types.py +622 -0
- ppbase-0.1.0/ppbase/models/record.py +227 -0
- ppbase-0.1.0/ppbase/services/__init__.py +1 -0
- ppbase-0.1.0/ppbase/services/admin_service.py +189 -0
- ppbase-0.1.0/ppbase/services/auth_service.py +281 -0
- ppbase-0.1.0/ppbase/services/collection_service.py +677 -0
- ppbase-0.1.0/ppbase/services/expand_service.py +277 -0
- ppbase-0.1.0/ppbase/services/file_storage.py +144 -0
- ppbase-0.1.0/ppbase/services/filter_parser.py +1111 -0
- ppbase-0.1.0/ppbase/services/mail_service.py +142 -0
- ppbase-0.1.0/ppbase/services/migration_generator.py +441 -0
- ppbase-0.1.0/ppbase/services/migration_runner.py +360 -0
- ppbase-0.1.0/ppbase/services/oauth2_service.py +550 -0
- ppbase-0.1.0/ppbase/services/realtime_service.py +665 -0
- ppbase-0.1.0/ppbase/services/record_auth_service.py +877 -0
- ppbase-0.1.0/ppbase/services/record_service.py +1110 -0
- ppbase-0.1.0/ppbase/services/rule_engine.py +79 -0
- ppbase-0.1.0/ppbase/storage/__init__.py +1 -0
- ppbase-0.1.0/ppbase.egg-info/PKG-INFO +20 -0
- ppbase-0.1.0/ppbase.egg-info/SOURCES.txt +98 -0
- ppbase-0.1.0/ppbase.egg-info/dependency_links.txt +1 -0
- ppbase-0.1.0/ppbase.egg-info/entry_points.txt +2 -0
- ppbase-0.1.0/ppbase.egg-info/requires.txt +17 -0
- ppbase-0.1.0/ppbase.egg-info/top_level.txt +1 -0
- ppbase-0.1.0/pyproject.toml +47 -0
- ppbase-0.1.0/setup.cfg +4 -0
- ppbase-0.1.0/tests/test_deps_optional_auth.py +56 -0
ppbase-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ppbase
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Requires-Python: >=3.11
|
|
5
|
+
Requires-Dist: fastapi>=0.115.0
|
|
6
|
+
Requires-Dist: uvicorn[standard]>=0.32.0
|
|
7
|
+
Requires-Dist: sqlalchemy[asyncio]>=2.0.36
|
|
8
|
+
Requires-Dist: asyncpg>=0.30.0
|
|
9
|
+
Requires-Dist: pydantic>=2.9.0
|
|
10
|
+
Requires-Dist: pydantic-settings>=2.6.0
|
|
11
|
+
Requires-Dist: pyjwt>=2.9.0
|
|
12
|
+
Requires-Dist: passlib[bcrypt]>=1.7.4
|
|
13
|
+
Requires-Dist: lark>=1.2.0
|
|
14
|
+
Requires-Dist: python-multipart>=0.0.12
|
|
15
|
+
Requires-Dist: aiofiles>=24.1.0
|
|
16
|
+
Provides-Extra: dev
|
|
17
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
18
|
+
Requires-Dist: pytest-asyncio>=0.24.0; extra == "dev"
|
|
19
|
+
Requires-Dist: httpx>=0.27.0; extra == "dev"
|
|
20
|
+
Requires-Dist: testcontainers[postgres]>=4.0; extra == "dev"
|
ppbase-0.1.0/README.md
ADDED
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
# PPBase
|
|
2
|
+
|
|
3
|
+
A Python reimplementation of [PocketBase](https://pocketbase.io/) backed by PostgreSQL.
|
|
4
|
+
|
|
5
|
+
PPBase gives you an instant REST API with dynamic collections, admin authentication, a built-in admin dashboard, and PocketBase-compatible endpoints -- all running on PostgreSQL instead of SQLite.
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
### 1. Prerequisites
|
|
10
|
+
|
|
11
|
+
- Python 3.11+
|
|
12
|
+
- Docker (for PostgreSQL)
|
|
13
|
+
|
|
14
|
+
### 2. Install
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
git clone <repo-url> ppbase && cd ppbase
|
|
18
|
+
python3 -m venv .venv
|
|
19
|
+
source .venv/bin/activate
|
|
20
|
+
pip install -e ".[dev]"
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### 3. Start PostgreSQL
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
python -m ppbase db start
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
This creates a Docker container (`ppbase-pg`) running PostgreSQL 17 on port 5433.
|
|
30
|
+
|
|
31
|
+
### 4. Start the server
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
python -m ppbase serve
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The server starts at **http://localhost:8090**. Admin UI is at **http://localhost:8090/_/**.
|
|
38
|
+
|
|
39
|
+
### 5. Create an admin account
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
python -m ppbase create-admin --email admin@example.com --password yourpassword
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## CLI Reference
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# Server
|
|
49
|
+
python -m ppbase serve # foreground
|
|
50
|
+
python -m ppbase serve -d # daemon (background)
|
|
51
|
+
python -m ppbase stop # stop daemon
|
|
52
|
+
python -m ppbase restart # restart daemon
|
|
53
|
+
python -m ppbase status # check if running
|
|
54
|
+
|
|
55
|
+
# Database
|
|
56
|
+
python -m ppbase db start # start PostgreSQL container
|
|
57
|
+
python -m ppbase db stop # stop container
|
|
58
|
+
python -m ppbase db restart # restart container
|
|
59
|
+
python -m ppbase db status # check container status
|
|
60
|
+
|
|
61
|
+
# Admin
|
|
62
|
+
python -m ppbase create-admin --email <email> --password <pass>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
A shell script (`ppctl.sh`) is also available:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
./ppctl.sh start | stop | restart | status
|
|
69
|
+
./ppctl.sh db-start | db-stop | db-restart | db-status
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## API Endpoints
|
|
73
|
+
|
|
74
|
+
PPBase implements the PocketBase REST API. All endpoints are under `/api/`.
|
|
75
|
+
|
|
76
|
+
| Method | Endpoint | Description |
|
|
77
|
+
|--------|----------|-------------|
|
|
78
|
+
| `POST` | `/api/admins/auth-with-password` | Admin login |
|
|
79
|
+
| `GET` | `/api/collections` | List collections |
|
|
80
|
+
| `POST` | `/api/collections` | Create collection |
|
|
81
|
+
| `GET` | `/api/collections/:id` | Get collection |
|
|
82
|
+
| `PATCH` | `/api/collections/:id` | Update collection |
|
|
83
|
+
| `DELETE` | `/api/collections/:id` | Delete collection |
|
|
84
|
+
| `GET` | `/api/collections/:col/records` | List records |
|
|
85
|
+
| `POST` | `/api/collections/:col/records` | Create record |
|
|
86
|
+
| `GET` | `/api/collections/:col/records/:id` | Get record |
|
|
87
|
+
| `PATCH` | `/api/collections/:col/records/:id` | Update record |
|
|
88
|
+
| `DELETE` | `/api/collections/:col/records/:id` | Delete record |
|
|
89
|
+
| `GET` | `/api/health` | Health check |
|
|
90
|
+
| `GET` | `/api/settings` | Get settings |
|
|
91
|
+
| `PATCH` | `/api/settings` | Update settings |
|
|
92
|
+
|
|
93
|
+
### Filtering & Sorting
|
|
94
|
+
|
|
95
|
+
Records support PocketBase filter syntax:
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
GET /api/collections/posts/records?filter=title~"hello" && views>5&sort=-created&page=1&perPage=20
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Expand Relations
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
GET /api/collections/posts/records?expand=author,category
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Collection Types
|
|
108
|
+
|
|
109
|
+
- **Base** -- Standard data collections with custom fields
|
|
110
|
+
- **Auth** -- Collections with built-in email/password authentication fields
|
|
111
|
+
- **View** -- Read-only collections backed by a SQL SELECT query
|
|
112
|
+
|
|
113
|
+
## Field Types
|
|
114
|
+
|
|
115
|
+
PPBase supports 14 field types, each mapped to a physical PostgreSQL column:
|
|
116
|
+
|
|
117
|
+
| Type | PostgreSQL | Notes |
|
|
118
|
+
|------|-----------|-------|
|
|
119
|
+
| `text` | `TEXT` | Min/max length, regex pattern |
|
|
120
|
+
| `number` | `DOUBLE PRECISION` / `INTEGER` | Min/max, integer-only option |
|
|
121
|
+
| `bool` | `BOOLEAN` | |
|
|
122
|
+
| `email` | `VARCHAR(255)` | Domain allowlist/blocklist |
|
|
123
|
+
| `url` | `TEXT` | Domain allowlist/blocklist |
|
|
124
|
+
| `date` | `TIMESTAMPTZ` | Min/max date |
|
|
125
|
+
| `select` | `TEXT` / `TEXT[]` | Predefined values, single or multi |
|
|
126
|
+
| `file` | `TEXT` / `TEXT[]` | Max size, MIME types, single or multi |
|
|
127
|
+
| `relation` | `VARCHAR(15)` / `VARCHAR(15)[]` | Links to another collection |
|
|
128
|
+
| `json` | `JSONB` | |
|
|
129
|
+
| `editor` | `TEXT` | Rich text / HTML |
|
|
130
|
+
| `autodate` | `TIMESTAMPTZ` | Auto-set on create/update |
|
|
131
|
+
| `password` | `TEXT` | Stored as bcrypt hash |
|
|
132
|
+
| `geo_point` | `JSONB` | `{lon, lat}` |
|
|
133
|
+
|
|
134
|
+
## Admin Dashboard
|
|
135
|
+
|
|
136
|
+
The built-in admin UI at `/_/` provides:
|
|
137
|
+
|
|
138
|
+
- Collection management (create, edit, delete)
|
|
139
|
+
- Schema editor with full field options
|
|
140
|
+
- Record CRUD with field-type-aware forms
|
|
141
|
+
- SQL editor with syntax highlighting and autocomplete for view collections
|
|
142
|
+
- View collection support (read-only SQL queries)
|
|
143
|
+
|
|
144
|
+
## Architecture
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
HTTP Request -> FastAPI
|
|
148
|
+
-> api/router.py -> api/{endpoint}.py
|
|
149
|
+
-> services/{service}.py (business logic)
|
|
150
|
+
-> db/system_tables.py (ORM for _collections, _admins)
|
|
151
|
+
-> db/schema_manager.py (DDL for dynamic tables)
|
|
152
|
+
-> sqlalchemy.text() (parameterized SQL for records)
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
- **Hybrid SQLAlchemy**: ORM for system tables, Core for dynamic collection tables
|
|
156
|
+
- **Physical columns**: Each field type maps to a real PostgreSQL column (not JSONB)
|
|
157
|
+
- **Filter parser**: Lark EBNF grammar translates PocketBase filter syntax to parameterized SQL
|
|
158
|
+
- **No migration system**: `_collections` table is the source of truth; DDL is applied directly
|
|
159
|
+
|
|
160
|
+
## Configuration
|
|
161
|
+
|
|
162
|
+
All settings use the `PPBASE_` environment variable prefix:
|
|
163
|
+
|
|
164
|
+
| Variable | Default | Description |
|
|
165
|
+
|----------|---------|-------------|
|
|
166
|
+
| `PPBASE_DATABASE_URL` | `postgresql+asyncpg://ppbase:ppbase@localhost:5433/ppbase` | PostgreSQL connection |
|
|
167
|
+
| `PPBASE_PORT` | `8090` | Server port |
|
|
168
|
+
| `PPBASE_HOST` | `0.0.0.0` | Bind address |
|
|
169
|
+
|
|
170
|
+
## Development
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
# Install with dev dependencies
|
|
174
|
+
pip install -e ".[dev]"
|
|
175
|
+
|
|
176
|
+
# Run tests
|
|
177
|
+
pytest tests/ -v
|
|
178
|
+
|
|
179
|
+
# Run a specific test
|
|
180
|
+
pytest tests/test_specific.py::test_name -v
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Flask-like Extension API
|
|
184
|
+
|
|
185
|
+
PPBase can be used as a Python-extensible app with global decorators.
|
|
186
|
+
|
|
187
|
+
### Single-file usage
|
|
188
|
+
|
|
189
|
+
```python
|
|
190
|
+
from ppbase import pb
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
@pb.get("/hello/{name}")
|
|
194
|
+
async def hello(name: str):
|
|
195
|
+
return {"message": f"Hello {name}"}
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
@pb.on_record_create_request("posts")
|
|
199
|
+
async def normalize_post(e):
|
|
200
|
+
if "title" in e.data and "slug" not in e.data:
|
|
201
|
+
e.data["slug"] = str(e.data["title"]).strip().lower().replace(" ", "-")
|
|
202
|
+
return await e.next()
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
pb.start(host="127.0.0.1", port=8090)
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Access records and current user in custom code
|
|
209
|
+
|
|
210
|
+
Use repository-style helpers in routes and hooks:
|
|
211
|
+
|
|
212
|
+
```python
|
|
213
|
+
from ppbase import pb
|
|
214
|
+
|
|
215
|
+
@pb.get("/api/me")
|
|
216
|
+
async def me(auth: dict = pb.require_record_auth()):
|
|
217
|
+
user = await pb.records(auth["collectionName"]).get(auth["id"])
|
|
218
|
+
return {"user": user}
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
@pb.on_record_update_request("users")
|
|
222
|
+
async def before_user_update(e):
|
|
223
|
+
e.require_auth_record() # raises 401/403 with PocketBase-style body
|
|
224
|
+
e.require_same_auth_record(e.record_id or "")
|
|
225
|
+
if not e.is_superuser():
|
|
226
|
+
e.data.setdefault("updatedByHook", True)
|
|
227
|
+
current = await e.get_current_user(fields="id,email")
|
|
228
|
+
if current:
|
|
229
|
+
e.data.setdefault("updatedBy", current["id"]) # mutate payload before default handler
|
|
230
|
+
return await e.next()
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Multi-file usage
|
|
234
|
+
|
|
235
|
+
- Side-effects style: import modules that register decorators on `pb`.
|
|
236
|
+
- Register function style: expose `register(pb)` and call it manually.
|
|
237
|
+
|
|
238
|
+
```python
|
|
239
|
+
from ppbase import pb
|
|
240
|
+
import my_hooks_side_effects
|
|
241
|
+
from my_hooks_register import register
|
|
242
|
+
|
|
243
|
+
register(pb)
|
|
244
|
+
pb.start()
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### CLI hooks loading
|
|
248
|
+
|
|
249
|
+
You can load hook modules when starting the server:
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
python -m ppbase serve --hooks myapp.hooks:register
|
|
253
|
+
python -m ppbase serve --hooks myapp.hooks:register --hooks myapp.more_hooks:setup
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
The hook target format is strict: `module:function`. The function receives `pb`.
|
|
257
|
+
|
|
258
|
+
## Tech Stack
|
|
259
|
+
|
|
260
|
+
- **FastAPI** -- async web framework
|
|
261
|
+
- **SQLAlchemy 2.0** -- async ORM + Core
|
|
262
|
+
- **asyncpg** -- PostgreSQL async driver
|
|
263
|
+
- **Pydantic** -- request/response validation
|
|
264
|
+
- **PyJWT** -- admin authentication tokens
|
|
265
|
+
- **Lark** -- PocketBase filter syntax parser
|
|
266
|
+
- **PostgreSQL 17** -- database (via Docker)
|
|
267
|
+
|
|
268
|
+
## License
|
|
269
|
+
|
|
270
|
+
MIT
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""PPBase -- a Python reimplementation of PocketBase using PostgreSQL."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
__version__ = "0.1.0"
|
|
6
|
+
|
|
7
|
+
from ppbase.ext.flask_like_pb import FlaskLikePB
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class PPBase(FlaskLikePB):
|
|
11
|
+
"""Main PPBase facade."""
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# Process-wide Flask-like singleton facade.
|
|
15
|
+
pb = PPBase()
|
|
16
|
+
|
|
17
|
+
__all__ = ["PPBase", "pb", "__version__"]
|