Compare commits
4 Commits
master
...
revert-9-0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bda1d2846d | ||
|
|
428d18c387 | ||
|
|
00c9365b5f | ||
|
|
10496553ed |
39
.github/workflows/python-publish.yml
vendored
39
.github/workflows/python-publish.yml
vendored
@ -1,39 +0,0 @@
|
|||||||
# This workflow will upload a Python Package using Twine when a release is created
|
|
||||||
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries
|
|
||||||
|
|
||||||
# This workflow uses actions that are not certified by GitHub.
|
|
||||||
# They are provided by a third-party and are governed by
|
|
||||||
# separate terms of service, privacy policy, and support
|
|
||||||
# documentation.
|
|
||||||
|
|
||||||
name: Upload Python Package
|
|
||||||
|
|
||||||
on:
|
|
||||||
release:
|
|
||||||
types: [published]
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
deploy:
|
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: Set up Python
|
|
||||||
uses: actions/setup-python@v3
|
|
||||||
with:
|
|
||||||
python-version: '3.x'
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
python -m pip install --upgrade pip
|
|
||||||
pip install build
|
|
||||||
- name: Build package
|
|
||||||
run: python -m build
|
|
||||||
- name: Publish package
|
|
||||||
uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29
|
|
||||||
with:
|
|
||||||
user: __token__
|
|
||||||
password: ${{ secrets.PYPI_API_TOKEN }}
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2023 vaphes
|
Copyright (c) [year] [fullname]
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
66
README.md
66
README.md
@ -10,10 +10,10 @@ This is in early development, and at first is just a translation of <a href="htt
|
|||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Install PocketBase using PIP:
|
Install PocketBase using pip:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
python3 -m pip install pocketbase
|
$ pip install pocketbase
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
@ -21,66 +21,26 @@ python3 -m pip install pocketbase
|
|||||||
The rule of thumb here is just to use it as you would <a href="https://github.com/pocketbase/js-sdk">the javascript lib</a>, but in a pythonic way of course!
|
The rule of thumb here is just to use it as you would <a href="https://github.com/pocketbase/js-sdk">the javascript lib</a>, but in a pythonic way of course!
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from pocketbase import PocketBase # Client also works the same
|
from pocketbase import PocketBase # Client also works the same
|
||||||
from pocketbase.client import FileUpload
|
|
||||||
|
|
||||||
client = PocketBase('http://127.0.0.1:8090')
|
client = PocketBase('http://127.0.0.1:8090')
|
||||||
|
|
||||||
# authenticate as regular user
|
...
|
||||||
user_data = client.collection("users").auth_with_password(
|
|
||||||
"user@example.com", "0123456789")
|
|
||||||
|
|
||||||
# or as admin
|
|
||||||
admin_data = client.admins.auth_with_password("test@example.com", "0123456789")
|
|
||||||
|
|
||||||
# list and filter "example" collection records
|
# list and filter "example" collection records
|
||||||
result = client.collection("example").get_list(
|
result = client.records.get_list(
|
||||||
1, 20, {"filter": 'status = true && created > "2022-08-01 10:00:00"'})
|
"example", 1, 20, {"filter": 'status = true && created > "2022-08-01 10:00:00"'}
|
||||||
|
)
|
||||||
|
|
||||||
# create record and upload file to image field
|
# authenticate as regular user
|
||||||
result = client.collection("example").create(
|
user_data = client.users.auth_via_email("test@example.com", "123456")
|
||||||
{
|
|
||||||
"status": "true",
|
# or as admin
|
||||||
"image": FileUpload(("image.png", open("image.png", "rb"))),
|
admin_data = client.admins.auth_via_email("test@example.com", "123456")
|
||||||
})
|
|
||||||
|
|
||||||
# and much more...
|
# and much more...
|
||||||
```
|
```
|
||||||
> More detailed API docs and copy-paste examples could be found in the [API documentation for each service](https://pocketbase.io/docs/api-authentication). Just remember to 'pythonize it' 🙃.
|
> More detailed API docs and copy-paste examples could be found in the [API documentation for each service](https://pocketbase.io/docs/api-authentication). Just remember to 'pythonize it' 🙃.
|
||||||
|
|
||||||
## Development
|
|
||||||
|
|
||||||
These are the requirements for local development:
|
<p align="center"><i>The PocketBase Python SDK is <a href="https://github.com/vaphes/pocketbase/blob/master/LICENCE.txt">MIT licensed</a> code.</p>
|
||||||
|
|
||||||
* Python 3.7+
|
|
||||||
* Poetry (https://python-poetry.org/)
|
|
||||||
|
|
||||||
You can install locally:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
poetry install
|
|
||||||
```
|
|
||||||
|
|
||||||
Or can build and generate a package:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
poetry build
|
|
||||||
```
|
|
||||||
|
|
||||||
But if you are using only PIP, use this command:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
python3 -m pip install -e .
|
|
||||||
```
|
|
||||||
|
|
||||||
## Tests
|
|
||||||
|
|
||||||
To execute the tests use this command:
|
|
||||||
|
|
||||||
```
|
|
||||||
poetry run pytest
|
|
||||||
```
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
The PocketBase Python SDK is <a href="https://github.com/vaphes/pocketbase/blob/master/LICENCE.txt">MIT licensed</a> code.
|
|
||||||
@ -1,9 +1,9 @@
|
|||||||
__title__ = "pocketbase"
|
__title__ = "pocketbase"
|
||||||
__description__ = "PocketBase client SDK for python."
|
__description__ = "PocketBase client SDK for python."
|
||||||
__version__ = "0.8.1"
|
__version__ = "0.2.2"
|
||||||
|
|
||||||
|
|
||||||
from .client import Client
|
from .client import Client, ClientResponseError
|
||||||
|
|
||||||
|
|
||||||
class PocketBase(Client):
|
class PocketBase(Client):
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
from pocketbase.stores.base_auth_store import BaseAuthStore
|
||||||
|
from pocketbase.models import FileUpload
|
||||||
|
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
from urllib.parse import quote, urlencode
|
from urllib.parse import quote, urlencode
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
|
|
||||||
from pocketbase.models import FileUpload
|
from pocketbase.utils import ClientResponseError
|
||||||
from pocketbase.models.record import Record
|
from pocketbase.models.record import Record
|
||||||
from pocketbase.services.admin_service import AdminService
|
from pocketbase.services.admin_service import AdminService
|
||||||
from pocketbase.services.collection_service import CollectionService
|
from pocketbase.services.collection_service import CollectionService
|
||||||
@ -14,7 +16,6 @@ from pocketbase.services.realtime_service import RealtimeService
|
|||||||
from pocketbase.services.record_service import RecordService
|
from pocketbase.services.record_service import RecordService
|
||||||
from pocketbase.services.settings_service import SettingsService
|
from pocketbase.services.settings_service import SettingsService
|
||||||
from pocketbase.stores.base_auth_store import BaseAuthStore
|
from pocketbase.stores.base_auth_store import BaseAuthStore
|
||||||
from pocketbase.utils import ClientResponseError
|
|
||||||
|
|
||||||
|
|
||||||
class Client:
|
class Client:
|
||||||
@ -35,12 +36,10 @@ class Client:
|
|||||||
base_url: str = "/",
|
base_url: str = "/",
|
||||||
lang: str = "en-US",
|
lang: str = "en-US",
|
||||||
auth_store: BaseAuthStore | None = None,
|
auth_store: BaseAuthStore | None = None,
|
||||||
timeout: float = 120,
|
|
||||||
) -> None:
|
) -> None:
|
||||||
self.base_url = base_url
|
self.base_url = base_url
|
||||||
self.lang = lang
|
self.lang = lang
|
||||||
self.auth_store = auth_store or BaseAuthStore() # LocalAuthStore()
|
self.auth_store = auth_store or BaseAuthStore() # LocalAuthStore()
|
||||||
self.timeout = timeout
|
|
||||||
# services
|
# services
|
||||||
self.admins = AdminService(self)
|
self.admins = AdminService(self)
|
||||||
self.collections = CollectionService(self)
|
self.collections = CollectionService(self)
|
||||||
@ -64,7 +63,9 @@ class Client:
|
|||||||
"headers" not in config or "Authorization" not in config["headers"]
|
"headers" not in config or "Authorization" not in config["headers"]
|
||||||
):
|
):
|
||||||
config["headers"] = config.get("headers", {})
|
config["headers"] = config.get("headers", {})
|
||||||
config["headers"].update({"Authorization": self.auth_store.token})
|
config["headers"].update(
|
||||||
|
{"Authorization": self.auth_store.token}
|
||||||
|
)
|
||||||
# build url + path
|
# build url + path
|
||||||
url = self.build_url(path)
|
url = self.build_url(path)
|
||||||
# send the request
|
# send the request
|
||||||
@ -96,7 +97,7 @@ class Client:
|
|||||||
json=body,
|
json=body,
|
||||||
data=data,
|
data=data,
|
||||||
files=files,
|
files=files,
|
||||||
timeout=self.timeout,
|
timeout=120,
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise ClientResponseError(
|
raise ClientResponseError(
|
||||||
@ -118,16 +119,16 @@ class Client:
|
|||||||
|
|
||||||
def get_file_url(self, record: Record, filename: str, query_params: dict):
|
def get_file_url(self, record: Record, filename: str, query_params: dict):
|
||||||
parts = [
|
parts = [
|
||||||
"api",
|
'api',
|
||||||
"files",
|
'files',
|
||||||
quote(record.collection_id or record.collection_name),
|
quote(record.collection_id or record.collection_name),
|
||||||
quote(record.id),
|
quote(record.id),
|
||||||
quote(filename),
|
quote(filename),
|
||||||
]
|
]
|
||||||
result = self.build_url("/".join(parts))
|
result = self.build_url('/'.join(parts))
|
||||||
if len(query_params) != 0:
|
if len(query_params) != 0:
|
||||||
params: str = urlencode(query_params)
|
params: str = urlencode(query_params)
|
||||||
result += "&" if "?" in result else "?"
|
result += '&' if '?' in result else '?'
|
||||||
result += params
|
result += params
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|||||||
@ -37,10 +37,10 @@ class Collection(BaseModel):
|
|||||||
self.schema.append(SchemaField(**field))
|
self.schema.append(SchemaField(**field))
|
||||||
|
|
||||||
def is_base(self):
|
def is_base(self):
|
||||||
return self.type == "base"
|
return self.type == 'base'
|
||||||
|
|
||||||
def is_auth(self):
|
def is_auth(self):
|
||||||
return self.type == "auth"
|
return self.type == 'auth'
|
||||||
|
|
||||||
def is_single(self):
|
def is_single(self):
|
||||||
return self.type == "single"
|
return self.type == 'single'
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
from httpx._types import FileTypes
|
from httpx._types import FileTypes
|
||||||
from typing import Sequence, Union
|
from typing import Sequence, Union
|
||||||
|
|
||||||
FileUploadTypes = Union[FileTypes, Sequence[FileTypes]]
|
FileUploadTypes = Union[FileTypes, Sequence[FileTypes]]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -2,21 +2,24 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from pocketbase.models.utils.base_model import BaseModel
|
from pocketbase.models.utils.base_model import BaseModel
|
||||||
from pocketbase.utils import camel_to_snake
|
from pocketbase.utils import camel_to_snake
|
||||||
from dataclasses import dataclass, field
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Record(BaseModel):
|
class Record(BaseModel):
|
||||||
collection_id: str
|
collection_id: str
|
||||||
collection_name: str = ""
|
collection_name: str
|
||||||
expand: dict = field(default_factory=dict)
|
expand: dict
|
||||||
|
|
||||||
def load(self, data: dict) -> None:
|
def load(self, data: dict) -> None:
|
||||||
super().load(data)
|
super().load(data)
|
||||||
self.expand = {}
|
|
||||||
for key, value in data.items():
|
for key, value in data.items():
|
||||||
key = camel_to_snake(key).replace("@", "")
|
key = camel_to_snake(key).replace("@", "")
|
||||||
setattr(self, key, value)
|
setattr(self, key, value)
|
||||||
self.load_expanded()
|
self.collection_id = data.get("@collectionId", "")
|
||||||
|
self.collection_name = data.get("@collectionName", "")
|
||||||
|
expand = data.get("@expand", {})
|
||||||
|
if expand:
|
||||||
|
self.expand = expand
|
||||||
|
self.load_expanded()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def parse_expanded(cls, data: dict):
|
def parse_expanded(cls, data: dict):
|
||||||
|
|||||||
@ -30,10 +30,7 @@ class AdminService(CrudService):
|
|||||||
"""
|
"""
|
||||||
item = super(AdminService).update(id, body_params)
|
item = super(AdminService).update(id, body_params)
|
||||||
try:
|
try:
|
||||||
if (
|
if self.client.auth_store.model.collection_id is not None and item.id == self.client.auth_store.model.id:
|
||||||
self.client.auth_store.model.collection_id is not None
|
|
||||||
and item.id == self.client.auth_store.model.id
|
|
||||||
):
|
|
||||||
self.client.auth_store.save(self.client.auth_store.token, item)
|
self.client.auth_store.save(self.client.auth_store.token, item)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
@ -46,10 +43,7 @@ class AdminService(CrudService):
|
|||||||
"""
|
"""
|
||||||
item = super(AdminService).delete(id, body_params)
|
item = super(AdminService).delete(id, body_params)
|
||||||
try:
|
try:
|
||||||
if (
|
if self.client.auth_store.model.collection_id is not None and item.id == self.client.auth_store.model.id:
|
||||||
self.client.auth_store.model.collection_id is not None
|
|
||||||
and item.id == self.client.auth_store.model.id
|
|
||||||
):
|
|
||||||
self.client.auth_store.save(self.client.auth_store.token, item)
|
self.client.auth_store.save(self.client.auth_store.token, item)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|||||||
@ -76,7 +76,9 @@ class RealtimeService(BaseService):
|
|||||||
found = False
|
found = False
|
||||||
for sub in self.subscriptions:
|
for sub in self.subscriptions:
|
||||||
found = True
|
found = True
|
||||||
self.event_source.remove_event_listener(sub, self.subscriptions[sub])
|
self.event_source.remove_event_listener(
|
||||||
|
sub, self.subscriptions[sub]
|
||||||
|
)
|
||||||
self.subscriptions.pop(sub)
|
self.subscriptions.pop(sub)
|
||||||
if not found:
|
if not found:
|
||||||
return
|
return
|
||||||
@ -139,13 +141,15 @@ class RealtimeService(BaseService):
|
|||||||
def _connect(self) -> None:
|
def _connect(self) -> None:
|
||||||
self._disconnect()
|
self._disconnect()
|
||||||
self.event_source = SSEClient(self.client.build_url("/api/realtime"))
|
self.event_source = SSEClient(self.client.build_url("/api/realtime"))
|
||||||
self.event_source.add_event_listener("PB_CONNECT", self._connect_handler)
|
self.event_source.add_event_listener(
|
||||||
|
"PB_CONNECT", self._connect_handler)
|
||||||
|
|
||||||
def _disconnect(self) -> None:
|
def _disconnect(self) -> None:
|
||||||
self._remove_subscription_listeners()
|
self._remove_subscription_listeners()
|
||||||
self.client_id = ""
|
self.client_id = ""
|
||||||
if not self.event_source:
|
if not self.event_source:
|
||||||
return
|
return
|
||||||
self.event_source.remove_event_listener("PB_CONNECT", self._connect_handler)
|
self.event_source.remove_event_listener(
|
||||||
|
"PB_CONNECT", self._connect_handler)
|
||||||
self.event_source.close()
|
self.event_source.close()
|
||||||
self.event_source = None
|
self.event_source = None
|
||||||
|
|||||||
@ -74,16 +74,14 @@ class RecordService(CrudService):
|
|||||||
|
|
||||||
def subscribeOne(self, record_id: str, callback: Callable[[MessageData], None]):
|
def subscribeOne(self, record_id: str, callback: Callable[[MessageData], None]):
|
||||||
"""Subscribe to the realtime changes of a single record in the collection."""
|
"""Subscribe to the realtime changes of a single record in the collection."""
|
||||||
return self.client.realtime.subscribe(
|
return self.client.realtime.subscribe(self.collection_id_or_name + '/' + record_id, callback)
|
||||||
self.collection_id_or_name + "/" + record_id, callback
|
|
||||||
)
|
|
||||||
|
|
||||||
def unsubscribe(self, *record_ids: List[str]):
|
def unsubscribe(self, *record_ids: List[str]):
|
||||||
"""Subscribe to the realtime changes of a single record in the collection."""
|
"""Subscribe to the realtime changes of a single record in the collection."""
|
||||||
if record_ids and len(record_ids) == 0:
|
if record_ids and len(record_ids) == 0:
|
||||||
subs = []
|
subs = []
|
||||||
for id in record_ids:
|
for id in record_ids:
|
||||||
subs.append(self.collection_id_or_name + "/" + id)
|
subs.append(self.collection_id_or_name + '/' + id)
|
||||||
return self.client.realtime.unsubscribe(*subs)
|
return self.client.realtime.unsubscribe(*subs)
|
||||||
return self.client.realtime.subscribe_by_prefix(self.collection_id_or_name)
|
return self.client.realtime.subscribe_by_prefix(self.collection_id_or_name)
|
||||||
|
|
||||||
@ -94,10 +92,7 @@ class RecordService(CrudService):
|
|||||||
"""
|
"""
|
||||||
item = super().update(id, body_params) # super(Record).update
|
item = super().update(id, body_params) # super(Record).update
|
||||||
try:
|
try:
|
||||||
if (
|
if self.client.auth_store.model.collection_id is not None and item.id == self.client.auth_store.model.id:
|
||||||
self.client.auth_store.model.collection_id is not None
|
|
||||||
and item.id == self.client.auth_store.model.id
|
|
||||||
):
|
|
||||||
self.client.auth_store.save(self.client.auth_store.token, item)
|
self.client.auth_store.save(self.client.auth_store.token, item)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
@ -110,11 +105,7 @@ class RecordService(CrudService):
|
|||||||
"""
|
"""
|
||||||
success = super().delete(id, body_params) # super(Record).delete
|
success = super().delete(id, body_params) # super(Record).delete
|
||||||
try:
|
try:
|
||||||
if (
|
if success and self.client.auth_store.model.collection_id is not None and id == self.client.auth_store.model.id:
|
||||||
success
|
|
||||||
and self.client.auth_store.model.collection_id is not None
|
|
||||||
and id == self.client.auth_store.model.id
|
|
||||||
):
|
|
||||||
self.client.auth_store.clear()
|
self.client.auth_store.clear()
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
@ -138,25 +129,18 @@ class RecordService(CrudService):
|
|||||||
email_password = response_data.pop("emailPassword", False)
|
email_password = response_data.pop("emailPassword", False)
|
||||||
|
|
||||||
def apply_pythonic_keys(ap):
|
def apply_pythonic_keys(ap):
|
||||||
pythonic_keys_ap = {
|
pythonic_keys_ap = {camel_to_snake(key).replace(
|
||||||
camel_to_snake(key).replace("@", ""): value for key, value in ap.items()
|
"@", ""): value for key, value in ap.items()}
|
||||||
}
|
|
||||||
return pythonic_keys_ap
|
return pythonic_keys_ap
|
||||||
|
|
||||||
auth_providers = [
|
auth_providers = [
|
||||||
AuthProviderInfo(**auth_provider)
|
AuthProviderInfo(**auth_provider)
|
||||||
for auth_provider in map(
|
for auth_provider in map(apply_pythonic_keys, response_data.get("authProviders", []))
|
||||||
apply_pythonic_keys, response_data.get("authProviders", [])
|
|
||||||
)
|
|
||||||
]
|
]
|
||||||
return AuthMethodsList(username_password, email_password, auth_providers)
|
return AuthMethodsList(username_password, email_password, auth_providers)
|
||||||
|
|
||||||
def auth_with_password(
|
def auth_with_password(
|
||||||
self,
|
self, username_or_email: str, password: str, body_params: dict = {}, query_params: dict = {}
|
||||||
username_or_email: str,
|
|
||||||
password: str,
|
|
||||||
body_params: dict = {},
|
|
||||||
query_params: dict = {},
|
|
||||||
) -> RecordAuthResponse:
|
) -> RecordAuthResponse:
|
||||||
"""
|
"""
|
||||||
Authenticate a single auth collection record via its username/email and password.
|
Authenticate a single auth collection record via its username/email and password.
|
||||||
@ -166,7 +150,8 @@ class RecordService(CrudService):
|
|||||||
- the authentication token
|
- the authentication token
|
||||||
- the authenticated record model
|
- the authenticated record model
|
||||||
"""
|
"""
|
||||||
body_params.update({"identity": username_or_email, "password": password})
|
body_params.update(
|
||||||
|
{"identity": username_or_email, "password": password})
|
||||||
response_data = self.client.send(
|
response_data = self.client.send(
|
||||||
self.base_collection_path() + "/auth-with-password",
|
self.base_collection_path() + "/auth-with-password",
|
||||||
{
|
{
|
||||||
@ -197,17 +182,15 @@ class RecordService(CrudService):
|
|||||||
- the authenticated record model
|
- the authenticated record model
|
||||||
- the OAuth2 account data (eg. name, email, avatar, etc.)
|
- the OAuth2 account data (eg. name, email, avatar, etc.)
|
||||||
"""
|
"""
|
||||||
body_params.update(
|
body_params.update({
|
||||||
{
|
'provider': provider,
|
||||||
"provider": provider,
|
'code': code,
|
||||||
"code": code,
|
'codeVerifier': code_verifier,
|
||||||
"codeVerifier": code_verifier,
|
'redirectUrl': redirct_url,
|
||||||
"redirectUrl": redirct_url,
|
'createData': create_data,
|
||||||
"createData": create_data,
|
})
|
||||||
}
|
|
||||||
)
|
|
||||||
response_data = self.client.send(
|
response_data = self.client.send(
|
||||||
self.base_collection_path() + "/auth-with-oauth2",
|
self.base_collection_path() + "/auth-with-password",
|
||||||
{
|
{
|
||||||
"method": "POST",
|
"method": "POST",
|
||||||
"params": query_params,
|
"params": query_params,
|
||||||
@ -228,7 +211,11 @@ class RecordService(CrudService):
|
|||||||
return self.auth_response(
|
return self.auth_response(
|
||||||
self.client.send(
|
self.client.send(
|
||||||
self.base_collection_path() + "/auth-refresh",
|
self.base_collection_path() + "/auth-refresh",
|
||||||
{"method": "POST", "params": query_params, "body": body_params},
|
{
|
||||||
|
"method": "POST",
|
||||||
|
"params": query_params,
|
||||||
|
"body": body_params
|
||||||
|
},
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -53,24 +53,27 @@ class BaseCrudService(BaseService, ABC):
|
|||||||
def _get_one(self, base_path: str, id: str, query_params: dict = {}) -> BaseModel:
|
def _get_one(self, base_path: str, id: str, query_params: dict = {}) -> BaseModel:
|
||||||
return self.decode(
|
return self.decode(
|
||||||
self.client.send(
|
self.client.send(
|
||||||
f"{base_path}/{quote(id)}", {"method": "GET", "params": query_params}
|
f"{base_path}/{quote(id)}",
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"params": query_params
|
||||||
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
def _get_first_list_item(self, base_path: str, filter: str, query_params={}):
|
def _get_first_list_item(self, base_path: str, filter: str, query_params={}):
|
||||||
query_params.update(
|
query_params.update({
|
||||||
{
|
'filter': filter,
|
||||||
"filter": filter,
|
'$cancelKey': 'one_by_filter_' + base_path + '_' + filter,
|
||||||
"$cancelKey": "one_by_filter_" + base_path + "_" + filter,
|
})
|
||||||
}
|
|
||||||
)
|
|
||||||
result = self._get_list(base_path, 1, 1, query_params)
|
result = self._get_list(base_path, 1, 1, query_params)
|
||||||
try:
|
try:
|
||||||
if len(result.items) == 0:
|
if len(result.items) == 0:
|
||||||
raise
|
raise
|
||||||
except:
|
except:
|
||||||
raise ClientResponseError(
|
raise ClientResponseError(
|
||||||
"The requested resource wasn't found.", status=404
|
"The requested resource wasn't found.",
|
||||||
|
status=404
|
||||||
)
|
)
|
||||||
|
|
||||||
def _create(
|
def _create(
|
||||||
@ -95,6 +98,7 @@ class BaseCrudService(BaseService, ABC):
|
|||||||
|
|
||||||
def _delete(self, base_path: str, id: str, query_params: dict = {}) -> bool:
|
def _delete(self, base_path: str, id: str, query_params: dict = {}) -> bool:
|
||||||
self.client.send(
|
self.client.send(
|
||||||
f"{base_path}/{quote(id)}", {"method": "DELETE", "params": query_params}
|
f"{base_path}/{quote(id)}", {"method": "DELETE",
|
||||||
|
"params": query_params}
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
|
|||||||
@ -29,7 +29,7 @@ dynamic = ["readme", "version"]
|
|||||||
|
|
||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "pocketbase"
|
name = "pocketbase"
|
||||||
version = "0.8.1"
|
version = "0.2.2"
|
||||||
description = "PocketBase SDK for python."
|
description = "PocketBase SDK for python."
|
||||||
authors = ["Vithor Jaeger <vaphes@gmail.com>"]
|
authors = ["Vithor Jaeger <vaphes@gmail.com>"]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|||||||
@ -5,7 +5,7 @@ from pocketbase.utils import camel_to_snake, to_datetime
|
|||||||
|
|
||||||
|
|
||||||
def test_version():
|
def test_version():
|
||||||
assert __version__ == "0.8.1"
|
assert __version__ == "0.2.2"
|
||||||
|
|
||||||
|
|
||||||
def test_utils():
|
def test_utils():
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user