Skip to content

Commit 92e2a31

Browse files
Feat/cs 40545 metadata class implemetation (#15)
* 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 <mobile@contentstack.com> --------- Co-authored-by: Shailesh Mishra <mobile@contentstack.com>
1 parent dae66d7 commit 92e2a31

38 files changed

+2884
-61
lines changed

.DS_Store

0 Bytes
Binary file not shown.

.github/workflows/unit-test.yml

Lines changed: 41 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,48 @@
1-
name: Pytest Workflow
1+
name: Coverage Report
22

3-
on:
4-
push:
5-
branches:
6-
- main
7-
pull_request:
8-
branches:
9-
- main
3+
on: [push] # You can adjust the trigger events as needed
104

115
jobs:
12-
coverage-report:
13-
strategy:
14-
matrix:
15-
python-version:
16-
- 3.9
6+
coverage:
177
runs-on: ubuntu-latest
8+
189
steps:
19-
- uses: actions/checkout@v2
20-
- uses: actions/setup-python@v2
21-
with:
22-
python-version: ${{ matrix.python-version }}
23-
- name: Install build dependencies
24-
run: pip install --upgrade setuptools
25-
- name: Install dot env
26-
run: pip install python-dotenv
27-
- name: Install requests
28-
run: pip install requests
29-
- name: Change to test directory
30-
run: cd tests/unit
31-
- uses: lpenz/ghaction-pytest-cov@v1
32-
- uses: AndreMiras/coveralls-python-action@v20201129
10+
- name: Checkout code
11+
uses: actions/checkout@v2
12+
13+
- name: Set up Python
14+
uses: actions/setup-python@v2
3315
with:
34-
parallel: true
35-
flag-name: python-${{ matrix.python-version }}
36-
github-token: ${{ secrets.GITHUB_TOKEN }}
37-
38-
39-
coverage-finish:
40-
needs: coverage-report
41-
runs-on: ubuntu-latest
42-
steps:
43-
- uses: AndreMiras/coveralls-python-action@v20201129
16+
python-version: 3.11 # Choose the appropriate Python version
17+
18+
- name: Install dependencies
19+
run: |
20+
python -m pip install --upgrade pip
21+
pip install -r requirements.txt # If you have a requirements file
22+
pip install coverage
23+
pip install pytest
24+
pip install coverage-badge
25+
26+
27+
- name: Run tests and coverage
28+
run: |
29+
coverage run -m pytest tests/unit/
30+
coverage report --include="tests/unit/*" -m > coverage_report.txt
31+
coverage xml --include="tests/unit/*" -o coverage.xml
32+
coverage html --include="tests/unit/*"
33+
coverage-badge -o coverage.svg
34+
35+
- name: Upload coverage artifact
36+
uses: actions/upload-artifact@v2
4437
with:
45-
parallel-finished: true
38+
name: coverage-report
39+
path: |
40+
coverage_report.txt
41+
coverage.xml
42+
htmlcov
43+
coverage.svg
44+
- name: Upload coverage reports to Codecov
45+
uses: codecov/codecov-action@v3
46+
env:
47+
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
48+

.talismanrc

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,3 +150,62 @@ fileignoreconfig:
150150
- filename: contentstack_management/workflows/workflows.py
151151
checksum: 85e3a2ee0ced2fd1787f74f15388a674130ec2b2fe433f19ca96c2cc968508a5
152152
version: ""
153+
154+
fileignoreconfig:
155+
- filename: tests/resources/mock_metadata/create.json
156+
checksum: 4d8942e449701b1599dca9485ef7a6d6e65d44d71ebabd04335147132c93a807
157+
- filename: tests/resources/mock_metadata/update.json
158+
checksum: 8bb19547a9ecbbac023db0dde82c6d69a4893953c6b6c0118839e40810f9a61d
159+
- filename: tests/mock/metadata/test_metadata_mock.py
160+
checksum: fc239da7691c242e8bbf0fa3db04cb4d024c841b1a8e227177294ec055566b05
161+
- filename: tests/resources/mock_metadata/fetch.json
162+
checksum: 305bb32cd8dc0d3bbe4dc1708e3a6b2e770f92504c807b1c2747511e567d58b1
163+
- filename: tests/resources/mock_metadata/find.json
164+
checksum: b69fe03ca10170c7d00cca0d0784e8bb334307a9872f9a57f0ec75cc6def302a
165+
- filename: tests/unit/metadata/test_metadata_unit.py
166+
checksum: 990c7e67627204c671da5eb2043630b635cfaa9d2f9ef4c46cddd2fd3ebedb19
167+
- filename: tests/api/metadata/test_metadata_api.py
168+
checksum: 72e6676565b99227b0e87ef9569fdd8298143ab4601259b46d05b7cc09f1e912
169+
- filename: contentstack_management/metadata/metadata.py
170+
checksum: aa059e6dee28d87be47e7aa2cb92fd39fcd0f2f89366d27236ddf8ecc51e8f7b
171+
version: ""
172+
173+
fileignoreconfig:
174+
- filename: tests/resources/mock_roles/fetch.json
175+
checksum: 9207921c9508fe82e59bf6101d1fa99b2b9a62b6b864f36d90f5819a15fdbaa0
176+
- filename: tests/resources/mock_roles/create.json
177+
checksum: d59d280188a9d57a596fbcd7746b718ef5cf2bc9ad187537f9caa730bc2c03af
178+
- filename: tests/resources/mock_roles/find.json
179+
checksum: 70b7016d8dcf96474c298cf3052d91d83cb3b154d16ebb3e167cb85cefa3a760
180+
- filename: tests/resources/mock_roles/update.json
181+
checksum: f83955fa82e9e8f84aaccc0b7f866116e07d9115deb3ffac3f1406e9c1800745
182+
- filename: tests/api/roles/test_roles_api.py
183+
checksum: 36d5ccd16ee1785b2ca774303bd3d4d24ab15846bb1b67037b26e152b117b4b2
184+
- filename: tests/mock/roles/test_roles_mock.py
185+
checksum: a6ca0282a3df204bf783b8bf73dbdac02e256177df2b000f95ba9d528f2322b4
186+
- filename: tests/unit/roles/test_roles_unit.py
187+
checksum: 3294f71a285ba9e2e61a6d75884498618a7934b76993b1c0ff385937bb5ed74f
188+
- filename: contentstack_management/roles/roles.py
189+
checksum: 373a75c8df71801a8b39cfa992bc9296b7ff5398bf4de4f990f6fe1977841a3c
190+
version: ""
191+
192+
fileignoreconfig:
193+
- filename: tests/unit/stack/test_stack.py
194+
checksum: 882d1d8d76848a5192c0d042948a04e4edbabac3b47ee725689181ff4ec3393b
195+
version: ""
196+
fileignoreconfig:
197+
- filename: README.md
198+
checksum: 769bf6032aa18764c5924a0f71b911a1b66258a0b04f1e0aef4650c486b0a050
199+
version: ""
200+
fileignoreconfig:
201+
- filename: README.md
202+
checksum: 45ea945d901c8a47144e8eb7106e49b1d121400cf47cbc7e5134f62a236b8da5
203+
version: ""
204+
fileignoreconfig:
205+
- filename: tests/mock/auditlogs/test_auditlogs_mock.py
206+
checksum: 6be6e351200624863cbfc443d3215242f03b0b06adc06649d119bee80b7608a3
207+
- filename: tests/api/auditlogs/test_auditlogs_api.py
208+
checksum: ff37d395fe03a822775e73a1c867cfcbbe14a75e37e4cb8a6d09f19fd790da7e
209+
- filename: tests/unit/auditlogs/test_auditlog_unit.py
210+
checksum: 1b8b24cc7f7921d209b983a99c0305d5fb27c1fe8e3fc74f1d525a7327eba830
211+
version: ""

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2012 - 2023 Contentstack. All rights reserved.
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 NON INFRINGEMENT. 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.

README.md

Lines changed: 106 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,106 @@
1-
# contentstack-management-python
1+
[![Contentstack](https://www.contentstack.com/docs/static/images/contentstack.png)](https://www.contentstack.com/)
2+
3+
## Contentstack Management Python SDK
4+
5+
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/).
6+
7+
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).
8+
9+
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.
10+
11+
### Prerequisite
12+
13+
You will need python 3 installed on your machine. You can install it
14+
from [here](https://www.python.org/ftp/python/3.7.4/python-3.7.4-macosx10.9.pkg).
15+
16+
### Installation
17+
#### Install contentstack pip
18+
19+
```python
20+
pip install contentstack_management
21+
```
22+
To import the SDK, use the following command:
23+
```python
24+
from contentstack_management import contentstack
25+
26+
client = contentstack.ContentstackClient()
27+
```
28+
29+
### Authentication
30+
To use this SDK, you need to authenticate your users by using the Authtoken, credentials, or Management Token (stack-level token).
31+
### Authtoken
32+
33+
An **Authtoken** is a read-write token used to make authorized CMA requests, and it is a **user-specific** token.
34+
```python
35+
client = contentstack.ContentstackClient(authtoken= 'authtoken')
36+
```
37+
### Login
38+
To Login to Contentstack by using credentials, you can use the following lines of code:
39+
```python
40+
client.login(email="email", password="password")
41+
42+
```
43+
44+
### Management Token
45+
**Management Tokens** are **stack-level** tokens, with no users attached to them.
46+
47+
```python
48+
result = client.stack(api_key = 'api_key', management_token= 'management_token' ).content_type('content_type_uid')
49+
.fetch().json()
50+
print(result)
51+
```
52+
### Contentstack Management Python SDK: 5-minute Quickstart
53+
#### Initializing Your SDK:
54+
To use the Python CMA SDK, you need to first initialize it. To do this, use the following code:
55+
56+
```python
57+
from contentstack_management import contentstack
58+
59+
client = contentstack.ContentstackClient(authtoken= 'authtoken')
60+
```
61+
#### Fetch Stack Detail
62+
Use the following lines of code to fetch your stack detail using this SDK:
63+
```python
64+
result = client.stack(api_key= 'api_key').fetch().json()
65+
print(result)
66+
```
67+
68+
#### Create Entry
69+
To create an entry in a specific content type of a stack, use the following lines of code:
70+
71+
```python
72+
entry = {
73+
title: 'Sample Entry',
74+
url: '/sampleEntry'
75+
}
76+
77+
result = client.stack(api_key= 'api_key').content_types('content_type_uid').entry().create(entry)
78+
print(result.json())
79+
```
80+
81+
#### Create Asset
82+
The following lines of code can be used to upload assets to your stack:
83+
84+
```python
85+
asset = {
86+
upload: 'path/to/file',
87+
title: 'Asset Title'
88+
}
89+
asset = client().stack(api_key='api_key').assets()
90+
result = asset.upload(asset)
91+
```
92+
93+
### Helpful Links
94+
95+
- [Contentstack Website](https://www.contentstack.com/)
96+
- [Official Documentation](https://contentstack.com/docs)
97+
- [Content Management API Docs](https://www.contentstack.com/docs/developers/apis/content-management-api)
98+
99+
### The MIT License (MIT)
100+
Copyright © 2012-2023 [Contentstack](https://www.contentstack.com/). All Rights Reserved
101+
102+
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:
103+
104+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
105+
106+
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.

contentstack_management/_api_client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ def get(self, path, params=None, headers=None):
8080
# self.headers = headers or {}
8181
return self._call_request('GET', url, headers=headers, params=params)
8282

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

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

107107
def post(self, path, data=None, json_data=None, headers=None, params=None, files=None):
108108
"""

contentstack_management/_errors.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,10 @@
1-
class Error(Exception):
1+
class ArgumentException(Exception):
2+
23
pass
4+
def __init__(self, f, *args):
5+
super().__init__(args)
6+
self.f = f
7+
8+
def __str__(self):
9+
return self.f
10+
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
"""This class takes a base URL as an argument when it's initialized,
2+
which is the endpoint for the RESTFUL API that we'll be interacting with.
3+
The create(), read(), update(), and delete() methods each correspond to
4+
the CRUD operations that can be performed on the API """
5+
6+
import json
7+
from ..common import Parameter
8+
from urllib.parse import quote
9+
from .._errors import ArgumentException
10+
11+
class Auditlog(Parameter):
12+
"""
13+
This class takes a base URL as an argument when it's initialized,
14+
which is the endpoint for the RESTFUL API that
15+
we'll be interacting with. The create(), read(), update(), and delete()
16+
methods each correspond to the CRUD
17+
operations that can be performed on the API """
18+
19+
def __init__(self, client, log_item_uid: str):
20+
self.client = client
21+
self.log_item_uid = log_item_uid
22+
super().__init__(self.client)
23+
24+
self.path = "audit-logs"
25+
26+
def find(self):
27+
"""
28+
The "Get audit log" request is used to retrieve the audit log of a stack.
29+
:return: Json, with auditlog details.
30+
31+
-------------------------------
32+
[Example:]
33+
34+
>>> from contentstack_management import contentstack
35+
>>> client = contentstack.client(authtoken='your_authtoken')
36+
>>> result = client.stack("api_key").auditlog().find().json()
37+
38+
-------------------------------
39+
"""
40+
return self.client.get(self.path, headers = self.client.headers)
41+
42+
43+
44+
def fetch(self):
45+
"""
46+
The "Get audit log item" request is used to retrieve a specific item from the audit log of a stack.
47+
:return: Json, with auditlog details.
48+
-------------------------------
49+
[Example:]
50+
51+
>>> from contentstack_management import contentstack
52+
>>> client = contentstack.client(authtoken='your_authtoken')
53+
>>> result = client.stack('api_key').auditlog('log_item_uid').fetch().json()
54+
55+
-------------------------------
56+
"""
57+
self.validate_uid()
58+
url = f"{self.path}/{self.log_item_uid}"
59+
return self.client.get(url, headers = self.client.headers)
60+
61+
def validate_uid(self):
62+
if self.log_item_uid is None or '':
63+
raise ArgumentException('Log item Uid is required')
64+
65+

0 commit comments

Comments
 (0)