From aaf4daa6e79f7d11bdb1ed7bae695df8cb02137c Mon Sep 17 00:00:00 2001 From: MarcTheDev Date: Sun, 3 Mar 2024 19:33:24 +0100 Subject: [PATCH] initial commit --- LICENSE | 21 +++++ pyproject.toml | 28 ++++++ src/marcsync/__init__.py | 36 +++++++ src/marcsync/collection.py | 186 +++++++++++++++++++++++++++++++++++++ src/marcsync/entry.py | 62 +++++++++++++ 5 files changed, 333 insertions(+) create mode 100644 LICENSE create mode 100644 pyproject.toml create mode 100644 src/marcsync/__init__.py create mode 100644 src/marcsync/collection.py create mode 100644 src/marcsync/entry.py diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..94f7d2f --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Marcel Lorbeer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..6547e62 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,28 @@ +[project] +name = "marcsync" +version = "0.1.12" +authors = [ + { name = "MarcTheDev", email = "marcthedev@marcsync.dev" } +] +description = "A simple client for interacting with the MarcSync API" +requires-python = ">=3.6" +classifiers = [ + "Development Status :: 3 - Alpha", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3 :: Only", + "Topic :: Software Development :: Libraries", + "Topic :: Software Development :: Libraries :: Python Modules", + "Typing :: Typed", + "Operating System :: OS Independent" +] + +[project.urls] +Homepage = "https://marcsync.dev" +Issues = "https://github.com/marcsync/marcsync-python-client/issues" \ No newline at end of file diff --git a/src/marcsync/__init__.py b/src/marcsync/__init__.py new file mode 100644 index 0000000..87b94dd --- /dev/null +++ b/src/marcsync/__init__.py @@ -0,0 +1,36 @@ +import requests + +from marcsync.collection import Collection + + +class MarcSync: + + def __init__(self, access_token: str): + self.accessToken = access_token + + def get_collection(self, collection_name: str): + return Collection(self.accessToken, collection_name) + + def fetch_collection(self, collection_name: str): + result = requests.get("https://api.marcsync.dev/v0/collection/" + collection_name, + headers={"Authorization": self.accessToken}) + if result.status_code == 401: + raise Exception("Invalid access token") + if result.status_code == 404: + raise Exception("Collection not found") + if result.status_code == 429: + raise Exception("Rate limit exceeded") + + return Collection(self.accessToken, collection_name) + + def create_collection(self, collection_name: str): + result = requests.post("https://api.marcsync.dev/v0/collection/" + collection_name, + headers={"Authorization": self.accessToken}) + if result.status_code == 401: + raise Exception("Invalid access token") + if result.status_code == 400: + raise Exception("Collection already exists") + if result.status_code == 429: + raise Exception("Rate limit exceeded") + + return Collection(self.accessToken, collection_name) diff --git a/src/marcsync/collection.py b/src/marcsync/collection.py new file mode 100644 index 0000000..70c1c00 --- /dev/null +++ b/src/marcsync/collection.py @@ -0,0 +1,186 @@ +import requests + +from marcsync.entry import Entry + + +class Collection: + + def __init__(self, access_token: str, collection_name: str): + self.accessToken = access_token + self.collectionName = collection_name + + def drop(self): + result = requests.delete("https://api.marcsync.dev/v0/collection/" + self.collectionName, + headers={"Authorization": self.accessToken}) + if result.status_code == 401: + raise Exception("Invalid access token") + if result.status_code == 400: + raise Exception("Collection not found") + if result.status_code == 429: + raise Exception("Rate limit exceeded") + + if result.status_code != 200: + raise Exception("Unknown error while dropping collection") + + def set_name(self, name: str): + result = requests.put("https://api.marcsync.dev/v0/collection/" + self.collectionName, + headers={"Authorization": self.accessToken}, + json={"collectionName": name}) + if result.status_code == 401: + raise Exception("Invalid access token") + if result.status_code == 400: + raise Exception("Collection not found") + if result.status_code == 429: + raise Exception("Rate limit exceeded") + + if result.status_code != 200: + raise Exception("Unknown error while renaming collection") + + self.collectionName = name + + def get_name(self): + return self.collectionName + + def exists(self): + result = requests.get("https://api.marcsync.dev/v0/collection/" + self.collectionName, + headers={"Authorization": self.accessToken}) + if result.status_code == 401: + raise Exception("Invalid access token") + if result.status_code == 404: + return False + if result.status_code == 429: + raise Exception("Rate limit exceeded") + + if result.status_code != 200: + raise Exception("Unknown error while checking collection") + + return True + + def create_entry(self, data: dict): + + if "_id" in data: + raise Exception("Cannot set _id while creating entry") + + result = requests.post("https://api.marcsync.dev/v0/entries/" + self.collectionName, + headers={"Authorization": self.accessToken}, + json={"data": data}) + if result.status_code == 401: + raise Exception("Invalid access token") + if result.status_code == 400: + raise Exception("Collection not found") + if result.status_code == 429: + raise Exception("Rate limit exceeded") + + if result.status_code != 200: + raise Exception("Unknown error while creating entry") + + data["_id"] = result.json().get("objectId") + return Entry(self.accessToken, self.collectionName, data) + + def get_entry_by_id(self, entry_id: str): + result = requests.get("https://api.marcsync.dev/v1/entries/" + self.collectionName, + headers={"Authorization": self.accessToken}, + json={"filters": {"_id": entry_id}}) + if result.status_code == 401: + raise Exception("Invalid access token") + if result.status_code == 400: + raise Exception("Collection not found") + if result.status_code == 404: + raise Exception("Entry not found") + if result.status_code == 429: + raise Exception("Rate limit exceeded") + + if result.status_code != 200: + raise Exception("Unknown error while fetching entry") + + if len(result.json().get("entries")) == 0: + raise Exception("Entry not found") + + return Entry(self.accessToken, self.collectionName, result.json().get("entries")[0]) + + def get_entries(self, filters: dict = {}): + result = requests.get("https://api.marcsync.dev/v1/entries/" + self.collectionName, + headers={"Authorization": self.accessToken}, + json={"filters": filters}) + if result.status_code == 401: + raise Exception("Invalid access token") + if result.status_code == 400: + raise Exception("Collection not found") + if result.status_code == 429: + raise Exception("Rate limit exceeded") + + if result.status_code != 200: + raise Exception("Unknown error while fetching entries") + + return [Entry(self.accessToken, self.collectionName, entry) for entry in result.json().get("entries")] + + def delete_entry_by_id(self, entry_id: str): + result = requests.delete("https://api.marcsync.dev/v1/entries/" + self.collectionName, + headers={"Authorization": self.accessToken}, + json={"filters": {"_id": entry_id}}) + if result.status_code == 401: + raise Exception("Invalid access token") + if result.status_code == 400: + raise Exception("Collection not found") + if result.status_code == 404: + raise Exception("Entry not found") + if result.status_code == 429: + raise Exception("Rate limit exceeded") + + if result.status_code != 200: + raise Exception("Unknown error while deleting entry") + + def delete_entries(self, filters: dict = {}): + result = requests.delete("https://api.marcsync.dev/v0/entries/" + self.collectionName, + headers={"Authorization": self.accessToken}, + json={"filters": filters}) + if result.status_code == 401: + raise Exception("Invalid access token") + if result.status_code == 400: + raise Exception("Collection not found") + if result.status_code == 429: + raise Exception("Rate limit exceeded") + + if result.status_code != 200: + raise Exception("Unknown error while deleting entries") + + def update_entry_by_id(self, entry_id: str, data: dict): + + if "_id" in data: + raise Exception("Cannot update _id") + + result = requests.put("https://api.marcsync.dev/v1/entries/" + self.collectionName, + headers={"Authorization": self.accessToken}, + json={"filters": {"_id": entry_id}, "data": data}) + if result.status_code == 401: + raise Exception("Invalid access token") + if result.status_code == 400: + raise Exception("Collection not found") + if result.status_code == 404: + raise Exception("Entry not found") + if result.status_code == 429: + raise Exception("Rate limit exceeded") + + if result.status_code != 200: + raise Exception("Unknown error while updating entry") + + def update_entries(self, data: dict, filters): + + if len(filters) == 0: + raise Exception("Filters are required for updating entries.") + + if "_id" in data: + raise Exception("Cannot update _id") + + result = requests.put("https://api.marcsync.dev/v1/entries/" + self.collectionName, + headers={"Authorization": self.accessToken}, + json={"filters": filters, "data": data}) + if result.status_code == 401: + raise Exception("Invalid access token") + if result.status_code == 400: + raise Exception("Collection not found") + if result.status_code == 429: + raise Exception("Rate limit exceeded") + + if result.status_code != 200: + raise Exception("Unknown error while updating entries") diff --git a/src/marcsync/entry.py b/src/marcsync/entry.py new file mode 100644 index 0000000..e7cfee6 --- /dev/null +++ b/src/marcsync/entry.py @@ -0,0 +1,62 @@ +import requests + + +class Entry: + def __init__(self, access_token: str, collection_name: str, data: dict): + self.accessToken = access_token + self.collectionName = collection_name + self.data = data + + def get_values(self): + return self.data.items() + + def get_value(self, key: str): + return self.data.get(key) + + def get_collection_name(self): + return self.collectionName + + def update_value(self, key: str, value: str): + + if key == "_id": + raise Exception("Cannot update _id") + + result = requests.put("https://api.marcsync.dev/v1/entries/" + self.collectionName, + headers={"Authorization": self.accessToken}, + json={"filters": {"_id": self.data.get("_id")}, "data": {key: value}}) + if result.status_code == 401: + raise Exception("Invalid access token") + if result.status_code == 400: + raise Exception("Entry not found") + if result.status_code == 429: + raise Exception("Rate limit exceeded") + + self.data[key] = value + + def update_values(self, values: dict): + + if "_id" in values: + raise Exception("Cannot update _id") + + result = requests.put("https://api.marcsync.dev/v1/entries/" + self.collectionName, + headers={"Authorization": self.accessToken}, + json={"filters": {"_id": self.data.get("_id")}, "data": values}) + if result.status_code == 401: + raise Exception("Invalid access token") + if result.status_code == 400: + raise Exception("Entry not found") + if result.status_code == 429: + raise Exception("Rate limit exceeded") + + self.data.update(values) + + def delete(self): + result = requests.delete("https://api.marcsync.dev/v1/entries/" + self.collectionName, + headers={"Authorization": self.accessToken}, + json={"filters": {"_id": self.data.get("_id")}}) + if result.status_code == 401: + raise Exception("Invalid access token") + if result.status_code == 400: + raise Exception("Entry not found") + if result.status_code == 429: + raise Exception("Rate limit exceeded")