Skip to content

Commit c862b9c

Browse files
mshaileshr@gmail.commshaileshr@gmail.com
authored andcommitted
asset.py & assetquery.py completed with testcases and linting fixed
1 parent ee44833 commit c862b9c

File tree

6 files changed

+204
-18
lines changed

6 files changed

+204
-18
lines changed

contentstack/__init__.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44
from .https_connection import HTTPSConnection
55
from .stack import Stack
66
from .utility import Utils
7-
# from contentstack import assetquery, entry, asset, contenttype, https_connection, stack, utility
8-
7+
# from contentstack import *
98

109
__author__ = 'Contentstack'
1110
__status__ = 'debug'

contentstack/assetquery.py

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,24 @@
77
# ************* Module assetquery **************
88
# Your code has been rated at 10/10 by pylint
99

10-
from urllib import parse
10+
import json
11+
from contentstack.utility import Utils
12+
from contentstack.basequery import BaseQuery
1113

1214

13-
class AssetQuery:
15+
class AssetQuery(BaseQuery):
1416
"""
1517
This call fetches the list of all the assets of a particular stack.
1618
"""
1719

1820
def __init__(self, http_instance):
21+
super().__init__()
1922
self.http_instance = http_instance
2023
self.__query_params = {}
21-
self.base_url = '{}/assets'.format(self.http_instance.endpoint)
22-
if 'environment' in self.http_instance.headers:
23-
self.__query_params['environment'] = self.http_instance.headers['environment']
24-
# self.http_instance.headers.pop('environment')
24+
self.base_url = "{}/assets".format(self.http_instance.endpoint)
25+
if "environment" in self.http_instance.headers:
26+
env = self.http_instance.headers["environment"]
27+
self.base_url = "{}?{}".format(self.base_url, "environment={}".format(env))
2528

2629
def environment(self, environment):
2730
"""
@@ -38,7 +41,7 @@ def environment(self, environment):
3841
>>> result = stack.asset_query().environment('production').find()
3942
------------------------------
4043
"""
41-
self.__query_params['environment'] = environment
44+
self.__query_params["environment"] = environment
4245
return self
4346

4447
def version(self, version):
@@ -58,7 +61,7 @@ def version(self, version):
5861
>>> result = stack.asset_query().version(3).find()
5962
------------------------------
6063
"""
61-
self.__query_params['version'] = version
64+
self.__query_params["version"] = version
6265
return self
6366

6467
def include_dimension(self):
@@ -75,7 +78,7 @@ def include_dimension(self):
7578
>>> result = stack.asset_query().include_dimension().find()
7679
------------------------------
7780
"""
78-
self.__query_params['include_dimension'] = 'true'
81+
self.__query_params["include_dimension"] = "true"
7982
return self
8083

8184
def relative_url(self):
@@ -91,7 +94,7 @@ def relative_url(self):
9194
>>> result = stack.asset_query().relative_url().find()
9295
------------------------------
9396
"""
94-
self.__query_params['relative_urls'] = 'true'
97+
self.__query_params["relative_urls"] = "true"
9598
return self
9699

97100
def include_count(self):
@@ -107,7 +110,7 @@ def include_count(self):
107110
>>> result = stack.asset_query().include_count().find()
108111
------------------------------
109112
"""
110-
self.__query_params['include_count'] = 'true'
113+
self.__query_params["include_count"] = "true"
111114
return self
112115

113116
def find(self):
@@ -116,7 +119,6 @@ def find(self):
116119
It also returns the content of each asset in JSON format.
117120
Learn more about Assets
118121
[https://www.contentstack.com/docs/content-managers/work-with-assets].
119-
120122
:return: json result, List of asset object
121123
122124
-----------------------------
@@ -127,5 +129,7 @@ def find(self):
127129
>>> result = stack.asset_query().find()
128130
129131
"""
130-
url = '{}?{}'.format(self.base_url, parse.urlencode(self.__query_params))
132+
if self.parameters is not None and len(self.parameters) > 0:
133+
self.__query_params["query"] = json.dumps(self.parameters)
134+
url = Utils.get_complete_url(self.base_url, self.__query_params)
131135
return self.http_instance.get(url)

contentstack/basequery.py

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
"""
2+
Missing docstring
3+
Common Query for Entry and Assets
4+
"""
5+
import enum
6+
7+
8+
# ************* Module assetquery **************
9+
# Your code has been rated at 10.00/10
10+
11+
class QueryOperation(enum.Enum):
12+
"""
13+
QueryOperation is enum that Provides Options to perform operation to query the result.
14+
15+
Available Options for QueryOperation are below.
16+
EQUALS, NOT_EQUALS, INCLUDES, EXCLUDES, IS_LESS_THAN, IS_LESS_THAN_OR_EQUAL
17+
IS_GREATER_THAN, IS_GREATER_THAN_OR_EQUAL, EXISTS, MATCHES
18+
19+
Arguments:
20+
enum {QueryOperation} -- Type of operation to perform
21+
"""
22+
EQUALS = ""
23+
NOT_EQUALS = '$ne'
24+
INCLUDES = '$in'
25+
EXCLUDES = '$nin'
26+
IS_LESS_THAN = '$lt'
27+
IS_LESS_THAN_OR_EQUAL = '$lte'
28+
IS_GREATER_THAN = '$gt'
29+
IS_GREATER_THAN_OR_EQUAL = '$gte'
30+
EXISTS = '$exists'
31+
MATCHES = '$regex'
32+
33+
34+
def _get_operation_value(fields):
35+
value = fields[0] if isinstance(fields, list) and len(fields) == 1 else fields
36+
return value
37+
38+
39+
class BaseQuery:
40+
"""
41+
Common Query class works for Entry As well as Asset
42+
"""
43+
44+
def __init__(self):
45+
self.parameters = {}
46+
self.__query_params = {}
47+
48+
def where(self, field_uid: str, query_operation: QueryOperation, fields=None):
49+
"""
50+
Get entries containing the field values matching the condition in the query.
51+
Arguments:
52+
field_uid {str} -- [accept field uid for the operation]
53+
query_operation {QueryOperation} -- [Type of operation to perform]
54+
fields {list} - list of string
55+
"""
56+
if None not in (field_uid, query_operation):
57+
result = _get_operation_value(fields) if query_operation.name == "EQUALS" \
58+
else {query_operation.value: fields}
59+
self.parameters[field_uid] = result
60+
return self
61+
62+
def skip(self, skip_count: int):
63+
"""
64+
The number of objects to skip before returning any.
65+
skip_count No of objects to skip from returned objects
66+
:param skip_count:
67+
:return: self
68+
"""
69+
self.__query_params["skip"] = str(skip_count)
70+
return self
71+
72+
def limit(self, limit_count: int):
73+
"""
74+
A limit on the number of objects to return.
75+
:param limit_count:
76+
:return: self
77+
"""
78+
self.__query_params["skip"] = str(limit_count)
79+
return self
80+
81+
def order_by_ascending(self, key: str):
82+
"""
83+
you can sort them in the ascending order with respect to the
84+
value of a specific field in the response body.
85+
86+
:param key: key on which ascending order to be implemented
87+
:return: self
88+
"""
89+
self.__query_params["asc"] = str(key)
90+
return self
91+
92+
def order_by_descending(self, key: str):
93+
"""
94+
you can sort them in the descending order with respect to the value
95+
of a specific field in the response body.
96+
:param key: key on which descending order to be implemented
97+
:return: self - Class instance, So that method chaining can be performed
98+
"""
99+
self.__query_params["desc"] = str(key)
100+
return self
101+
102+
def param(self, key: str, value):
103+
"""
104+
Adds Parameters to the to the request
105+
106+
Arguments:
107+
key {str} -- Key of the parameter
108+
value {[any]} -- Value of the parameter
109+
110+
Raises:
111+
KeyError: When None found in key or value
112+
113+
Returns:
114+
[self] -- instance of the class
115+
116+
-----------------------------------
117+
118+
[Example]
119+
>>> import contentstack
120+
>>> stack = contentstack.Stack('api_key', 'access_token', 'environment')
121+
>>> content_type = stack.content_type('content_type_uid')
122+
>>> query = content_type.query()
123+
>>> query = query.param("key", "value")
124+
>>> result = query.find()
125+
126+
-----------------------------------
127+
"""
128+
if None in (key, value):
129+
raise KeyError('Invalid key or value')
130+
self.__query_params[key] = str(value)
131+
return self
132+
133+
def add_params(self, param: dict):
134+
"""
135+
Adds Parameters to the to the request
136+
137+
Arguments:
138+
param {dict} -- paramters
139+
140+
Returns:
141+
[self] -- Class instance, So that method chaining can be performed
142+
"""
143+
self.__query_params.update(param)
144+
return self
145+
146+
def query(self, key: str, value):
147+
"""
148+
Adds key value pairs to the to the query parameters
149+
150+
Arguments:
151+
key {[str]} -- key of the query param
152+
value {[type]} -- value of query param
153+
154+
Raises:
155+
KeyError: when key or value found None
156+
157+
Returns:
158+
[self] -- Class instance, So that method chaining can be performed]
159+
"""
160+
if None in (key, value):
161+
raise KeyError('Invalid key or value')
162+
self.parameters[key] = str(value)
163+
return self

contentstack/contenttype.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ def find(self, params=None):
8787
"""
8888
This method is useful to fetch ContentType of the of the stack.
8989
:param params: dictionary of params
90-
:return:dict -- contentType response
90+
:return:dict -- contenttype response
9191
------------------------------
9292
Example:
9393

contentstack/https_connection.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
# Your code has been rated at 10.00/10 by pylint
1111

1212
from json import JSONDecodeError
13+
import json
14+
import urllib.parse as urlparse
1315
import platform
1416
import requests
1517
from requests.exceptions import Timeout, HTTPError
@@ -73,3 +75,11 @@ def get(self, url):
7375
def update_connection_timeout(self, timeout: int):
7476
"""Facilitate to update timeout for the https request"""
7577
self.default_timeout = timeout
78+
79+
def get_complete_url(self, base_url: str, params:dict):
80+
if 'query' in params:
81+
params["query"] = json.dumps(params["query"])
82+
query = urlparse.urlencode(params)
83+
url = '{}&{}'.format(base_url, query)
84+
return url
85+

contentstack/utility.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,15 @@
1010

1111

1212
import logging
13+
import json
14+
import urllib.parse as urlparse
1315

1416

1517
class Utils:
1618
"""
1719
Utility for the contentstack
1820
"""
21+
1922
@staticmethod
2023
def config_logging():
2124
""" Setting up logging """
@@ -36,7 +39,14 @@ def log(message):
3639
logging.debug(message)
3740

3841
@staticmethod
39-
def do_urlencode(params):
42+
def do_url_encode(params):
4043
from urllib import parse
4144
return parse.urlencode(params)
42-
45+
46+
@staticmethod
47+
def get_complete_url(base_url: str, params: dict):
48+
if 'query' in params:
49+
params["query"] = json.dumps(params["query"])
50+
query = urlparse.urlencode(params)
51+
url = '{}&{}'.format(base_url, query)
52+
return url

0 commit comments

Comments
 (0)