├── .gitignore ├── requirements.txt ├── resources ├── main.py ├── code.tar.gz └── nature.jpg ├── docker-compose.yml ├── Dockerfile ├── LICENSE ├── .github └── ISSUE_TEMPLATE │ ├── documentation.yaml │ ├── feature.yaml │ └── bug.yaml ├── README.md └── playground.py /.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | .idea 3 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | appwrite == 6.0.0 -------------------------------------------------------------------------------- /resources/main.py: -------------------------------------------------------------------------------- 1 | def main(context): 2 | return context.res.json({"message": "Hello World"}) 3 | -------------------------------------------------------------------------------- /resources/code.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appwrite/playground-for-python/HEAD/resources/code.tar.gz -------------------------------------------------------------------------------- /resources/nature.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appwrite/playground-for-python/HEAD/resources/nature.jpg -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.9' 2 | 3 | services: 4 | playground-for-python: 5 | build: . 6 | volumes: 7 | - "./:/app" 8 | working_dir: /app 9 | command: "python /app/playground.py" -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.10-alpine 2 | WORKDIR /app 3 | RUN apk update && apk add git 4 | COPY requirements.txt requirements.txt 5 | RUN pip3 install -r requirements.txt 6 | COPY . . 7 | CMD python playground.py 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Appwrite 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/documentation.yaml: -------------------------------------------------------------------------------- 1 | name: "📚 Documentation" 2 | description: "Report an issue related to documentation" 3 | title: "📚 Documentation: " 4 | labels: [documentation] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Thanks for taking the time to make our documentation better 🙏 10 | - type: textarea 11 | id: issue-description 12 | validations: 13 | required: true 14 | attributes: 15 | label: "💭 Description" 16 | description: "A clear and concise description of what the issue is." 17 | placeholder: "Documentation should not ..." 18 | - type: checkboxes 19 | id: no-duplicate-issues 20 | attributes: 21 | label: "👀 Have you spent some time to check if this issue has been raised before?" 22 | description: "Have you Googled for a similar issue or checked our older issues for a similar bug?" 23 | options: 24 | - label: "I checked and didn't find similar issue" 25 | required: true 26 | - type: checkboxes 27 | id: read-code-of-conduct 28 | attributes: 29 | label: "🏢 Have you read the Code of Conduct?" 30 | options: 31 | - label: "I have read the [Code of Conduct](https://github.com/appwrite/appwrite/blob/HEAD/CODE_OF_CONDUCT.md)" 32 | required: true -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature.yaml: -------------------------------------------------------------------------------- 1 | name: 🚀 Feature 2 | description: "Submit a proposal for a new feature" 3 | title: "🚀 Feature: " 4 | labels: [feature] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Thanks for taking the time to fill out our feature request form 🙏 10 | - type: textarea 11 | id: feature-description 12 | validations: 13 | required: true 14 | attributes: 15 | label: "🔖 Feature description" 16 | description: "A clear and concise description of what the feature is." 17 | placeholder: "You should add ..." 18 | - type: textarea 19 | id: pitch 20 | validations: 21 | required: true 22 | attributes: 23 | label: "🎤 Pitch" 24 | description: "Please explain why this feature should be implemented and how it would be used. Add examples, if applicable." 25 | placeholder: "In my use-case, ..." 26 | - type: checkboxes 27 | id: no-duplicate-issues 28 | attributes: 29 | label: "👀 Have you spent some time to check if this issue has been raised before?" 30 | description: "Have you Googled for a similar issue or checked our older issues for a similar bug?" 31 | options: 32 | - label: "I checked and didn't find similar issue" 33 | required: true 34 | - type: checkboxes 35 | id: read-code-of-conduct 36 | attributes: 37 | label: "🏢 Have you read the Code of Conduct?" 38 | options: 39 | - label: "I have read the [Code of Conduct](https://github.com/appwrite/appwrite/blob/HEAD/CODE_OF_CONDUCT.md)" 40 | required: true -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Appwrite's Python Playground 🎮 2 | 3 | Appwrite playground is a simple way to explore the Appwrite API & Appwrite Python SDK. Use the source code of this repository to learn how to use the different Appwrite Python SDK features. 4 | 5 | **Work in progress** 6 | 7 | ## System Requirements 8 | * A system with Python 3+ or Docker installed. 9 | * An Appwrite instance. 10 | * An Appwrite project created in the console. 11 | * An Appwrite API key created in the console. 12 | 13 | ### Installation 14 | 1. Clone this repository. 15 | 2. `cd` into the repository. 16 | 3. Open the playground.py file found in the root of the cloned repository. 17 | 4. Copy Project ID, endpoint and API key from Appwrite console into `playground.py` 18 | 5. Run the playground: 19 | Python: 20 | - Install dependencies using pip `pip install -r requirements.txt` 21 | - Execute the command `python playground.py` 22 | Docker: 23 | - Execute the command `docker compose up` 24 | 6. You will see the JSON response in the console. 25 | 26 | ### API's Covered 27 | 28 | - Database 29 | * Create Collection 30 | * List Collections 31 | * Add Document 32 | * List Documents 33 | * Delete Document 34 | * Delete Collection 35 | 36 | - Storage 37 | * Create Bucket 38 | * List Buckets 39 | * Upload File 40 | * List Files 41 | * Delete File 42 | * Delete Bucket 43 | 44 | - Users 45 | * Create User 46 | * List Users 47 | * Delete User 48 | 49 | - Functions 50 | * Create Function 51 | * List Functions 52 | * Delete Function 53 | 54 | ## Contributing 55 | 56 | All code contributions - including those of people having commit access - must go through a pull request and approved by a core developer before being merged. This is to ensure proper review of all the code. 57 | 58 | We truly ❤️ pull requests! If you wish to help, you can learn more about how you can contribute to this project in the [contribution guide](https://github.com/appwrite/appwrite/blob/master/CONTRIBUTING.md). 59 | 60 | ## Security 61 | 62 | For security issues, kindly email us [security@appwrite.io](mailto:security@appwrite.io) instead of posting a public issue in GitHub. 63 | 64 | ## Follow Us 65 | 66 | Join our growing community around the world! Follow us on [Twitter](https://twitter.com/appwrite), [Facebook Page](https://www.facebook.com/appwrite.io), [Facebook Group](https://www.facebook.com/groups/appwrite.developers/) or join our [Discord Server](https://appwrite.io/discord) for more help, ideas and discussions. 67 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug.yaml: -------------------------------------------------------------------------------- 1 | name: "🐛 Bug Report" 2 | description: "Submit a bug report to help us improve" 3 | title: "🐛 Bug Report: " 4 | labels: [bug] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Thanks for taking the time to fill out our bug report form 🙏 10 | - type: textarea 11 | id: steps-to-reproduce 12 | validations: 13 | required: true 14 | attributes: 15 | label: "👟 Reproduction steps" 16 | description: "How do you trigger this bug? Please walk us through it step by step." 17 | placeholder: "When I ..." 18 | - type: textarea 19 | id: expected-behavior 20 | validations: 21 | required: true 22 | attributes: 23 | label: "👍 Expected behavior" 24 | description: "What did you think would happen?" 25 | placeholder: "It should ..." 26 | - type: textarea 27 | id: actual-behavior 28 | validations: 29 | required: true 30 | attributes: 31 | label: "👎 Actual Behavior" 32 | description: "What did actually happen? Add screenshots, if applicable." 33 | placeholder: "It actually ..." 34 | - type: dropdown 35 | id: appwrite-version 36 | attributes: 37 | label: "🎲 Appwrite version" 38 | description: "What version of Appwrite are you running?" 39 | options: 40 | - Version 0.10.x 41 | - Version 0.9.x 42 | - Version 0.8.x 43 | - Version 0.7.x 44 | - Version 0.6.x 45 | - Different version (specify in environment) 46 | validations: 47 | required: true 48 | - type: dropdown 49 | id: operating-system 50 | attributes: 51 | label: "💻 Operating system" 52 | description: "What OS is your server / device running on?" 53 | options: 54 | - Linux 55 | - MacOS 56 | - Windows 57 | - Something else 58 | validations: 59 | required: true 60 | - type: textarea 61 | id: enviromnemt 62 | validations: 63 | required: false 64 | attributes: 65 | label: "🧱 Your Environment" 66 | description: "Is your environment customized in any way?" 67 | placeholder: "I use Cloudflare for ..." 68 | - type: checkboxes 69 | id: no-duplicate-issues 70 | attributes: 71 | label: "👀 Have you spent some time to check if this issue has been raised before?" 72 | description: "Have you Googled for a similar issue or checked our older issues for a similar bug?" 73 | options: 74 | - label: "I checked and didn't find similar issue" 75 | required: true 76 | - type: checkboxes 77 | id: read-code-of-conduct 78 | attributes: 79 | label: "🏢 Have you read the Code of Conduct?" 80 | options: 81 | - label: "I have read the [Code of Conduct](https://github.com/appwrite/appwrite/blob/HEAD/CODE_OF_CONDUCT.md)" 82 | required: true -------------------------------------------------------------------------------- /playground.py: -------------------------------------------------------------------------------- 1 | from time import sleep 2 | from random import randrange 3 | from sys import maxsize 4 | 5 | from appwrite.client import Client 6 | from appwrite.services.users import Users 7 | from appwrite.services.databases import Databases 8 | from appwrite.services.storage import Storage 9 | from appwrite.services.account import Account 10 | from appwrite.services.functions import Functions 11 | from appwrite.input_file import InputFile 12 | from appwrite.permission import Permission 13 | from appwrite.role import Role 14 | from appwrite.id import ID 15 | 16 | 17 | # Helper method to print green colored output. 18 | def p(info): 19 | print("\033[32;1m" + str(info) + "\033[0m") 20 | 21 | 22 | # Read the docs at https://appwrite.io/docs to get more information 23 | # about API keys and Project IDs 24 | client = Client() 25 | client.set_endpoint("http://YOUR_HOST/v1") 26 | client.set_project("YOUR_PROJECT_ID") 27 | client.set_key("YOU_API_KEY") 28 | client.set_self_signed() 29 | # client.set_jwt('JWT') # Use this to authenticate with JWT instead of API_KEY 30 | 31 | databases = Databases(client) 32 | storage = Storage(client) 33 | functions = Functions(client) 34 | users = Users(client) 35 | 36 | database_id = None 37 | collection_id = None 38 | document_id = None 39 | user_id = None 40 | bucket_id = None 41 | file_id = None 42 | document_id = None 43 | function_id = None 44 | deployment_id = None 45 | execution_id = None 46 | 47 | 48 | def create_database(): 49 | global database_id 50 | 51 | p("Running Create Database API") 52 | response = databases.create( 53 | database_id=ID.unique(), 54 | name="Movies", 55 | ) 56 | database_id = response["$id"] 57 | print(response) 58 | 59 | 60 | def create_collection(): 61 | global collection_id 62 | 63 | p("Running Create Collection API") 64 | response = databases.create_collection( 65 | database_id, 66 | collection_id=ID.unique(), 67 | name="Movies", 68 | document_security=True, 69 | permissions=[ 70 | Permission.read(Role.any()), 71 | Permission.create(Role.users()), 72 | Permission.update(Role.users()), 73 | Permission.delete(Role.users()), 74 | ], 75 | ) 76 | 77 | collection_id = response["$id"] 78 | print(response) 79 | 80 | response = databases.create_string_attribute( 81 | database_id, 82 | collection_id, 83 | key="name", 84 | size=255, 85 | required=True, 86 | ) 87 | print(response) 88 | 89 | response = databases.create_integer_attribute( 90 | database_id, collection_id, key="release_year", required=True, min=0, max=9999 91 | ) 92 | print(response) 93 | 94 | response = databases.create_float_attribute( 95 | database_id, collection_id, key="rating", required=True, min=0.0, max=99.99 96 | ) 97 | print(response) 98 | 99 | response = databases.create_boolean_attribute( 100 | database_id, collection_id, key="kids", required=True 101 | ) 102 | print(response) 103 | 104 | response = databases.create_email_attribute( 105 | database_id, collection_id, key="email", required=False 106 | ) 107 | print(response) 108 | 109 | # Wait for attributes to be created 110 | sleep(2) 111 | 112 | response = databases.create_index( 113 | database_id, 114 | collection_id, 115 | key="name_email_idx", 116 | type="fulltext", 117 | attributes=["name", "email"], 118 | ) 119 | print(response) 120 | 121 | 122 | def list_collections(): 123 | p("Running List Collection API") 124 | response = databases.list_collections(database_id) 125 | print(response) 126 | 127 | 128 | def get_account(): 129 | account = Account(client) 130 | p("Running Get Account API") 131 | response = account.get() 132 | print(response) 133 | 134 | 135 | def add_doc(): 136 | global document_id 137 | 138 | p("Running Add Document API") 139 | response = databases.create_document( 140 | database_id, 141 | collection_id, 142 | document_id=ID.unique(), 143 | data={ 144 | "name": "Spider Man", 145 | "release_year": 1920, 146 | "rating": 98.5, 147 | "kids": False, 148 | }, 149 | permissions=[ 150 | Permission.read(Role.users()), 151 | Permission.update(Role.users()), 152 | Permission.delete(Role.users()), 153 | ], 154 | ) 155 | document_id = response["$id"] 156 | print(response) 157 | 158 | 159 | def list_doc(): 160 | p("Running List Document API") 161 | response = databases.list_documents(database_id, collection_id) 162 | print(response) 163 | 164 | 165 | def delete_doc(): 166 | p("Running Delete Database API") 167 | response = databases.delete_document(database_id, collection_id, document_id) 168 | print(response) 169 | 170 | 171 | def delete_collection(): 172 | p("Running Delete Collection API") 173 | response = databases.delete_collection(database_id, collection_id) 174 | print(response) 175 | 176 | 177 | def delete_database(): 178 | p("Running Delete Database API") 179 | response = databases.delete(database_id) 180 | print(response) 181 | 182 | 183 | def create_bucket(): 184 | global bucket_id 185 | 186 | p("Running Create Bucket API") 187 | response = storage.create_bucket( 188 | bucket_id=ID.unique(), 189 | name="awesome bucket", 190 | file_security=True, 191 | permissions=[ 192 | Permission.read(Role.any()), 193 | Permission.create(Role.users()), 194 | Permission.update(Role.users()), 195 | Permission.delete(Role.users()), 196 | ], 197 | ) 198 | bucket_id = response["$id"] 199 | print(response) 200 | 201 | 202 | def list_buckets(): 203 | p("Running List Buckets API") 204 | response = storage.list_buckets() 205 | print(response) 206 | 207 | 208 | def upload_file(): 209 | global file_id 210 | 211 | p("Running Upload File API") 212 | response = storage.create_file( 213 | bucket_id, 214 | file_id=ID.unique(), 215 | file=InputFile.from_path("./resources/nature.jpg"), 216 | ) 217 | file_id = response["$id"] 218 | print(response) 219 | 220 | 221 | def list_files(): 222 | p("Running List Files API") 223 | response = storage.list_files(bucket_id) 224 | print(response) 225 | 226 | 227 | def delete_file(): 228 | p("Running Delete File API") 229 | response = storage.delete_file(bucket_id, file_id) 230 | print(response) 231 | 232 | 233 | def delete_bucket(): 234 | p("Running Delete Bucket API") 235 | response = storage.delete_bucket(bucket_id) 236 | print(response) 237 | 238 | 239 | def create_user(): 240 | global user_id 241 | 242 | name = str(randrange(1, maxsize)) 243 | p("Running Create User API") 244 | response = users.create( 245 | user_id=ID.unique(), email=f"{name}@test.com", password=f"{name}@123", name=name 246 | ) 247 | user_id = response["$id"] 248 | print(response) 249 | 250 | 251 | def list_user(): 252 | p("Running List User API") 253 | response = users.list() 254 | print(response) 255 | 256 | 257 | def delete_user(): 258 | p("Running Delete User API") 259 | response = users.delete(user_id) 260 | print(response) 261 | 262 | 263 | def create_function(): 264 | global function_id 265 | 266 | p("Running Create Function API") 267 | response = functions.create( 268 | function_id=ID.unique(), 269 | name="Test Function", 270 | execute=[Role.any()], 271 | runtime="python-3.9", 272 | ) 273 | function_id = response["$id"] 274 | print(response) 275 | 276 | 277 | def list_function(): 278 | p("Running List Function API") 279 | response = functions.list() 280 | print(response) 281 | 282 | 283 | def delete_function(): 284 | p("Running Delete Function API") 285 | response = functions.delete(function_id) 286 | print(response) 287 | 288 | 289 | def create_deployment(): 290 | global function_id 291 | global deployment_id 292 | 293 | p("Running Create Deployment API") 294 | response = functions.create_deployment( 295 | function_id, 296 | code=InputFile.from_path("./resources/code.tar.gz"), 297 | activate=True, 298 | entrypoint="main.py", 299 | ) 300 | 301 | deployment_id = response["$id"] 302 | print(response) 303 | 304 | 305 | def list_deployments(): 306 | global function_id 307 | 308 | p("Running List Deployments API") 309 | response = functions.list_deployments(function_id) 310 | print(response) 311 | 312 | 313 | def delete_deployment(): 314 | global function_id 315 | global deployment_id 316 | 317 | p("Running Delete Deployment API") 318 | response = functions.delete_deployment(function_id, deployment_id) 319 | print(response) 320 | 321 | 322 | def create_execution(): 323 | global function_id 324 | global execution_id 325 | 326 | p("Running Create Execution API") 327 | response = functions.create_execution(function_id) 328 | 329 | execution_id = response["$id"] 330 | 331 | print(response) 332 | 333 | 334 | def list_executions(): 335 | global function_id 336 | 337 | p("Running List Executions API") 338 | response = functions.list_executions(function_id) 339 | print(response) 340 | 341 | 342 | def delete_execution(): 343 | global function_id 344 | global execution_id 345 | 346 | p("Running Delete Execution API") 347 | response = functions.delete_execution(function_id, execution_id) 348 | print(response) 349 | 350 | 351 | def run_all_tasks(): 352 | 353 | # Databases 354 | create_database() 355 | create_collection() 356 | list_collections() 357 | add_doc() 358 | list_doc() 359 | delete_doc() 360 | delete_collection() 361 | delete_database() 362 | 363 | # Storage 364 | create_bucket() 365 | list_buckets() 366 | upload_file() 367 | list_files() 368 | delete_file() 369 | delete_bucket() 370 | 371 | # Users 372 | # get_account() # Use this only with JWT 373 | create_user() 374 | list_user() 375 | delete_user() 376 | 377 | # Functions 378 | create_function() 379 | list_function() 380 | create_deployment() 381 | list_deployments() 382 | create_execution() 383 | list_executions() 384 | delete_execution() 385 | delete_deployment() 386 | delete_function() 387 | 388 | 389 | if __name__ == "__main__": 390 | run_all_tasks() 391 | p("Successfully ran playground!") 392 | --------------------------------------------------------------------------------