Skip to content

Commit

Permalink
Feat/cs 40545 metadata class implemetation (#15)
Browse files Browse the repository at this point in the history
* Metadata class implementation

* Deleted sast-scan.yml file

* Fixed PR comments

* Code optimisation and handling custom error exception

* Removed uids

* Feat/cs 40549 roles class implementation (#16)

* Created roles class with unit testcases, mock test cases and api test cases

* Updated coverage report github workflow file

* Added coverage install command

* Added pytest install command

* Updated stack class unit test file

* Added html coverage

* Added coverage reports and visualizations

* Removed visualisation

* Generating coverage report in svg format

* Added coverage-badge  install command

* Fixed PR comments and code optimisation

* Added coverage reports graphical visualisation in github page

* Created readme file

* changed variable name

* Updated readme file

* Update README.md

* Added auditlog class and license file (#17)

* Added auditlog class and license file

* Added test case for invalid inputs

* commented the idiom

It Allows You to Execute Code When the File Runs as a Script, but Not When It’s Imported as a Module

---------

Co-authored-by: Shailesh Mishra <[email protected]>

---------

Co-authored-by: Shailesh Mishra <[email protected]>
  • Loading branch information
sunil-lakshman and ishaileshmishra authored Aug 23, 2023
1 parent dae66d7 commit 92e2a31
Show file tree
Hide file tree
Showing 38 changed files with 2,884 additions and 61 deletions.
Binary file modified .DS_Store
Binary file not shown.
79 changes: 41 additions & 38 deletions .github/workflows/unit-test.yml
Original file line number Diff line number Diff line change
@@ -1,45 +1,48 @@
name: Pytest Workflow
name: Coverage Report

on:
push:
branches:
- main
pull_request:
branches:
- main
on: [push] # You can adjust the trigger events as needed

jobs:
coverage-report:
strategy:
matrix:
python-version:
- 3.9
coverage:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install build dependencies
run: pip install --upgrade setuptools
- name: Install dot env
run: pip install python-dotenv
- name: Install requests
run: pip install requests
- name: Change to test directory
run: cd tests/unit
- uses: lpenz/ghaction-pytest-cov@v1
- uses: AndreMiras/coveralls-python-action@v20201129
- name: Checkout code
uses: actions/checkout@v2

- name: Set up Python
uses: actions/setup-python@v2
with:
parallel: true
flag-name: python-${{ matrix.python-version }}
github-token: ${{ secrets.GITHUB_TOKEN }}


coverage-finish:
needs: coverage-report
runs-on: ubuntu-latest
steps:
- uses: AndreMiras/coveralls-python-action@v20201129
python-version: 3.11 # Choose the appropriate Python version

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt # If you have a requirements file
pip install coverage
pip install pytest
pip install coverage-badge
- name: Run tests and coverage
run: |
coverage run -m pytest tests/unit/
coverage report --include="tests/unit/*" -m > coverage_report.txt
coverage xml --include="tests/unit/*" -o coverage.xml
coverage html --include="tests/unit/*"
coverage-badge -o coverage.svg
- name: Upload coverage artifact
uses: actions/upload-artifact@v2
with:
parallel-finished: true
name: coverage-report
path: |
coverage_report.txt
coverage.xml
htmlcov
coverage.svg
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v3
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

59 changes: 59 additions & 0 deletions .talismanrc
Original file line number Diff line number Diff line change
Expand Up @@ -150,3 +150,62 @@ fileignoreconfig:
- filename: contentstack_management/workflows/workflows.py
checksum: 85e3a2ee0ced2fd1787f74f15388a674130ec2b2fe433f19ca96c2cc968508a5
version: ""

fileignoreconfig:
- filename: tests/resources/mock_metadata/create.json
checksum: 4d8942e449701b1599dca9485ef7a6d6e65d44d71ebabd04335147132c93a807
- filename: tests/resources/mock_metadata/update.json
checksum: 8bb19547a9ecbbac023db0dde82c6d69a4893953c6b6c0118839e40810f9a61d
- filename: tests/mock/metadata/test_metadata_mock.py
checksum: fc239da7691c242e8bbf0fa3db04cb4d024c841b1a8e227177294ec055566b05
- filename: tests/resources/mock_metadata/fetch.json
checksum: 305bb32cd8dc0d3bbe4dc1708e3a6b2e770f92504c807b1c2747511e567d58b1
- filename: tests/resources/mock_metadata/find.json
checksum: b69fe03ca10170c7d00cca0d0784e8bb334307a9872f9a57f0ec75cc6def302a
- filename: tests/unit/metadata/test_metadata_unit.py
checksum: 990c7e67627204c671da5eb2043630b635cfaa9d2f9ef4c46cddd2fd3ebedb19
- filename: tests/api/metadata/test_metadata_api.py
checksum: 72e6676565b99227b0e87ef9569fdd8298143ab4601259b46d05b7cc09f1e912
- filename: contentstack_management/metadata/metadata.py
checksum: aa059e6dee28d87be47e7aa2cb92fd39fcd0f2f89366d27236ddf8ecc51e8f7b
version: ""

fileignoreconfig:
- filename: tests/resources/mock_roles/fetch.json
checksum: 9207921c9508fe82e59bf6101d1fa99b2b9a62b6b864f36d90f5819a15fdbaa0
- filename: tests/resources/mock_roles/create.json
checksum: d59d280188a9d57a596fbcd7746b718ef5cf2bc9ad187537f9caa730bc2c03af
- filename: tests/resources/mock_roles/find.json
checksum: 70b7016d8dcf96474c298cf3052d91d83cb3b154d16ebb3e167cb85cefa3a760
- filename: tests/resources/mock_roles/update.json
checksum: f83955fa82e9e8f84aaccc0b7f866116e07d9115deb3ffac3f1406e9c1800745
- filename: tests/api/roles/test_roles_api.py
checksum: 36d5ccd16ee1785b2ca774303bd3d4d24ab15846bb1b67037b26e152b117b4b2
- filename: tests/mock/roles/test_roles_mock.py
checksum: a6ca0282a3df204bf783b8bf73dbdac02e256177df2b000f95ba9d528f2322b4
- filename: tests/unit/roles/test_roles_unit.py
checksum: 3294f71a285ba9e2e61a6d75884498618a7934b76993b1c0ff385937bb5ed74f
- filename: contentstack_management/roles/roles.py
checksum: 373a75c8df71801a8b39cfa992bc9296b7ff5398bf4de4f990f6fe1977841a3c
version: ""

fileignoreconfig:
- filename: tests/unit/stack/test_stack.py
checksum: 882d1d8d76848a5192c0d042948a04e4edbabac3b47ee725689181ff4ec3393b
version: ""
fileignoreconfig:
- filename: README.md
checksum: 769bf6032aa18764c5924a0f71b911a1b66258a0b04f1e0aef4650c486b0a050
version: ""
fileignoreconfig:
- filename: README.md
checksum: 45ea945d901c8a47144e8eb7106e49b1d121400cf47cbc7e5134f62a236b8da5
version: ""
fileignoreconfig:
- filename: tests/mock/auditlogs/test_auditlogs_mock.py
checksum: 6be6e351200624863cbfc443d3215242f03b0b06adc06649d119bee80b7608a3
- filename: tests/api/auditlogs/test_auditlogs_api.py
checksum: ff37d395fe03a822775e73a1c867cfcbbe14a75e37e4cb8a6d09f19fd790da7e
- filename: tests/unit/auditlogs/test_auditlog_unit.py
checksum: 1b8b24cc7f7921d209b983a99c0305d5fb27c1fe8e3fc74f1d525a7327eba830
version: ""
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2012 - 2023 Contentstack. All rights reserved.

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 NON INFRINGEMENT. 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.
107 changes: 106 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,106 @@
# contentstack-management-python
[![Contentstack](https://www.contentstack.com/docs/static/images/contentstack.png)](https://www.contentstack.com/)

## Contentstack Management Python SDK

Contentstack is a headless CMS with an API-first approach. It is a CMS that developers can use to build powerful cross-platform applications in their favorite languages. All you have to do is build your application frontend, and Contentstack will take care of the rest. [Read More](https://www.contentstack.com/).

This SDK uses the [Content Management API](https://www.contentstack.com/docs/developers/apis/content-management-api/) (CMA). The CMA is used to manage the content of your Contentstack account. This includes creating, updating, deleting, and fetching content of your account. To use the CMA, you will need to authenticate your users with a [Management Token](https://www.contentstack.com/docs/developers/create-tokens/about-management-tokens) or an [Authtoken](https://www.contentstack.com/docs/developers/apis/content-management-api/#how-to-get-authtoken). Read more about it in [Authentication](https://www.contentstack.com/docs/developers/apis/content-management-api/#authentication).

Note: By using CMA, you can execute GET requests for fetching content. However, we strongly recommend that you always use the [Content Delivery API](https://www.contentstack.com/docs/developers/apis/content-delivery-api/) to deliver content to your web or mobile properties.

### Prerequisite

You will need python 3 installed on your machine. You can install it
from [here](https://www.python.org/ftp/python/3.7.4/python-3.7.4-macosx10.9.pkg).

### Installation
#### Install contentstack pip

```python
pip install contentstack_management
```
To import the SDK, use the following command:
```python
from contentstack_management import contentstack

client = contentstack.ContentstackClient()
```

### Authentication
To use this SDK, you need to authenticate your users by using the Authtoken, credentials, or Management Token (stack-level token).
### Authtoken

An **Authtoken** is a read-write token used to make authorized CMA requests, and it is a **user-specific** token.
```python
client = contentstack.ContentstackClient(authtoken= 'authtoken')
```
### Login
To Login to Contentstack by using credentials, you can use the following lines of code:
```python
client.login(email="email", password="password")

```

### Management Token
**Management Tokens** are **stack-level** tokens, with no users attached to them.

```python
result = client.stack(api_key = 'api_key', management_token= 'management_token' ).content_type('content_type_uid')
.fetch().json()
print(result)
```
### Contentstack Management Python SDK: 5-minute Quickstart
#### Initializing Your SDK:
To use the Python CMA SDK, you need to first initialize it. To do this, use the following code:

```python
from contentstack_management import contentstack

client = contentstack.ContentstackClient(authtoken= 'authtoken')
```
#### Fetch Stack Detail
Use the following lines of code to fetch your stack detail using this SDK:
```python
result = client.stack(api_key= 'api_key').fetch().json()
print(result)
```

#### Create Entry
To create an entry in a specific content type of a stack, use the following lines of code:

```python
entry = {
title: 'Sample Entry',
url: '/sampleEntry'
}

result = client.stack(api_key= 'api_key').content_types('content_type_uid').entry().create(entry)
print(result.json())
```

#### Create Asset
The following lines of code can be used to upload assets to your stack:

```python
asset = {
upload: 'path/to/file',
title: 'Asset Title'
}
asset = client().stack(api_key='api_key').assets()
result = asset.upload(asset)
```

### Helpful Links

- [Contentstack Website](https://www.contentstack.com/)
- [Official Documentation](https://contentstack.com/docs)
- [Content Management API Docs](https://www.contentstack.com/docs/developers/apis/content-management-api)

### The MIT License (MIT)
Copyright © 2012-2023 [Contentstack](https://www.contentstack.com/). All Rights Reserved

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.
4 changes: 2 additions & 2 deletions contentstack_management/_api_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def get(self, path, params=None, headers=None):
# self.headers = headers or {}
return self._call_request('GET', url, headers=headers, params=params)

def put(self, path, data=None, params=None, json_data=None, headers=None):
def put(self, path, data=None, params=None, json_data=None, headers=None, files=None):
"""
The function sends a PUT request to a specified URL with optional data, parameters, JSON data,
and headers.
Expand All @@ -102,7 +102,7 @@ def put(self, path, data=None, params=None, json_data=None, headers=None):

url = f"{self.endpoint}{path}"
# headers = headers or {}
return self._call_request('PUT', url, headers=headers, params=params, data=data, json_data=json_data)
return self._call_request('PUT', url, headers=headers, params=params, data=data, json_data=json_data, files=files)

def post(self, path, data=None, json_data=None, headers=None, params=None, files=None):
"""
Expand Down
10 changes: 9 additions & 1 deletion contentstack_management/_errors.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,10 @@
class Error(Exception):
class ArgumentException(Exception):

pass
def __init__(self, f, *args):
super().__init__(args)
self.f = f

def __str__(self):
return self.f

65 changes: 65 additions & 0 deletions contentstack_management/auditlogs/auditlog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
"""This class takes a base URL as an argument when it's initialized,
which is the endpoint for the RESTFUL API that we'll be interacting with.
The create(), read(), update(), and delete() methods each correspond to
the CRUD operations that can be performed on the API """

import json
from ..common import Parameter
from urllib.parse import quote
from .._errors import ArgumentException

class Auditlog(Parameter):
"""
This class takes a base URL as an argument when it's initialized,
which is the endpoint for the RESTFUL API that
we'll be interacting with. The create(), read(), update(), and delete()
methods each correspond to the CRUD
operations that can be performed on the API """

def __init__(self, client, log_item_uid: str):
self.client = client
self.log_item_uid = log_item_uid
super().__init__(self.client)

self.path = "audit-logs"

def find(self):
"""
The "Get audit log" request is used to retrieve the audit log of a stack.
:return: Json, with auditlog details.
-------------------------------
[Example:]
>>> from contentstack_management import contentstack
>>> client = contentstack.client(authtoken='your_authtoken')
>>> result = client.stack("api_key").auditlog().find().json()
-------------------------------
"""
return self.client.get(self.path, headers = self.client.headers)



def fetch(self):
"""
The "Get audit log item" request is used to retrieve a specific item from the audit log of a stack.
:return: Json, with auditlog details.
-------------------------------
[Example:]
>>> from contentstack_management import contentstack
>>> client = contentstack.client(authtoken='your_authtoken')
>>> result = client.stack('api_key').auditlog('log_item_uid').fetch().json()
-------------------------------
"""
self.validate_uid()
url = f"{self.path}/{self.log_item_uid}"
return self.client.get(url, headers = self.client.headers)

def validate_uid(self):
if self.log_item_uid is None or '':
raise ArgumentException('Log item Uid is required')


Loading

0 comments on commit 92e2a31

Please sign in to comment.