From f4a40dbc2cc19571aebea8cbc85ce4ecc19a5ceb Mon Sep 17 00:00:00 2001 From: rbw0 Date: Mon, 18 Dec 2017 13:23:47 +0100 Subject: [PATCH 1/6] Bumped to 0.6.3 --- pysnow/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pysnow/__init__.py b/pysnow/__init__.py index 4806470..26ae20b 100644 --- a/pysnow/__init__.py +++ b/pysnow/__init__.py @@ -7,4 +7,4 @@ from .resource import Resource __author__ = "Robert Wikman " -__version__ = "0.6.2" +__version__ = "0.6.3" From 5c6702beb8835c99d9e6d9263a76df239db04977 Mon Sep 17 00:00:00 2001 From: rbw0 Date: Mon, 18 Dec 2017 13:26:05 +0100 Subject: [PATCH 2/6] No longer user prepared requests (due to incompatibility with requests_oauthlib) --- pysnow/request.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/pysnow/request.py b/pysnow/request.py index d004dc8..ab75b8c 100644 --- a/pysnow/request.py +++ b/pysnow/request.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- import json -import requests from .response import Response from .exceptions import InvalidUsage @@ -10,7 +9,7 @@ class SnowRequest(object): """Creates a new :class:`SnowRequest` object. - :param parameters: :class:`sysparms.Sysparms` object + :param parameters: :class:`params_builder.ParamsBuilder` object :param session: :class:`request.Session` object :param url_builder: :class:`url_builder.URLBuilder` object """ @@ -32,11 +31,7 @@ def _get_response(self, method, **kwargs): :return: :class:`pysnow.Response` object """ - request = requests.Request(method, self._url, **kwargs) - prepped = self._session.prepare_request(request) - response = self._session.send(prepped, - stream=True) - + response = self._session.request(method, self._url, stream=True, **kwargs) response.raw.decode_content = True return Response(response, self._chunk_size) From c41738e0999d300ab21c44cd25747a9f2d42e883 Mon Sep 17 00:00:00 2001 From: rbw0 Date: Mon, 18 Dec 2017 13:27:14 +0100 Subject: [PATCH 3/6] Wrap OAUth2Session object in _get_session --- pysnow/oauth_client.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/pysnow/oauth_client.py b/pysnow/oauth_client.py index ffe4ca5..a6f847a 100644 --- a/pysnow/oauth_client.py +++ b/pysnow/oauth_client.py @@ -51,15 +51,18 @@ def _get_oauth_session(self): :return: OAuth2Session object """ - return OAuth2Session( - client_id=self.client_id, - token=self.token, - token_updater=self.token_updater, - auto_refresh_url=self.token_url, - auto_refresh_kwargs={ - "client_id": self.client_id, - "client_secret": self.client_secret - }) + return self._get_session( + OAuth2Session( + client_id=self.client_id, + token=self.token, + token_updater=self.token_updater, + auto_refresh_url=self.token_url, + auto_refresh_kwargs={ + "client_id": self.client_id, + "client_secret": self.client_secret + } + ) + ) def set_token(self, token): """Sets token after validating From 71a5a0b918886fc4409ad05b374ba31bdd768cfa Mon Sep 17 00:00:00 2001 From: rbw0 Date: Mon, 18 Dec 2017 13:50:19 +0100 Subject: [PATCH 4/6] Set User-Agent in headers --- pysnow/client.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pysnow/client.py b/pysnow/client.py index a96672c..619851a 100644 --- a/pysnow/client.py +++ b/pysnow/client.py @@ -6,6 +6,8 @@ import requests from requests.auth import HTTPBasicAuth +import pysnow + from .legacy_request import LegacyRequest from .exceptions import InvalidUsage from .resource import Resource @@ -94,7 +96,13 @@ def _get_session(self, session): else: s = session - s.headers.update({'content-type': 'application/json', 'accept': 'application/json'}) + s.headers.update( + { + 'content-type': 'application/json', + 'accept': 'application/json', + 'User-Agent': 'pysnow/%s' % pysnow.__version__ + } + ) return s From fed005d69567ad694d4218fa284dfe44c9410070 Mon Sep 17 00:00:00 2001 From: rbw0 Date: Mon, 18 Dec 2017 13:56:54 +0100 Subject: [PATCH 5/6] Code documentation formatting fixes --- pysnow/client.py | 15 ++++++++++----- pysnow/legacy_request.py | 33 ++++++++++++++++++++++----------- pysnow/oauth_client.py | 12 ++++++++---- pysnow/query_builder.py | 3 ++- pysnow/request.py | 18 ++++++++++++------ pysnow/resource.py | 15 ++++++++++----- pysnow/response.py | 19 +++++++++++++------ 7 files changed, 77 insertions(+), 38 deletions(-) diff --git a/pysnow/client.py b/pysnow/client.py index 619851a..8b238ea 100644 --- a/pysnow/client.py +++ b/pysnow/client.py @@ -88,7 +88,8 @@ def _get_session(self, session): """Creates a new session with basic auth, unless one was provided, and sets headers. :param session: (optional) Session to re-use - :return: :class:`requests.Session` object + :return: + - :class:`requests.Session` object """ if not session: s = requests.Session() @@ -111,7 +112,8 @@ def _legacy_request(self, method, table, **kwargs): :param method: HTTP method :param table: Table to operate on - :return: :class:`LegacyRequest` object + :return: + - :class:`LegacyRequest` object """ warnings.warn("`%s` is deprecated and will be removed in a future release. " @@ -132,7 +134,8 @@ def resource(self, api_path=None, base_path='/api/now', chunk_size=None): :param api_path: Path to the API to operate on :param base_path: (optional) Base path override :param chunk_size: Response stream parser chunk size (in bytes) - :return: :class:`Resource` object + :return: + - :class:`Resource` object :raises: - InvalidUsage: If a path fails validation """ @@ -152,7 +155,8 @@ def query(self, table, **kwargs): :param table: table to perform query on :param kwargs: Keyword arguments passed along to `Request` - :return: List of dictionaries containing the matching records + :return: + - List of dictionaries containing the matching records """ return self._legacy_request('GET', table, **kwargs) @@ -163,7 +167,8 @@ def insert(self, table, payload, **kwargs): :param table: table to insert on :param payload: update payload (dict) :param kwargs: Keyword arguments passed along to `Request` - :return: Dictionary containing the created record + :return: + - Dictionary containing the created record """ r = self._legacy_request('POST', table, **kwargs) diff --git a/pysnow/legacy_request.py b/pysnow/legacy_request.py index 30a10c6..4dd3c1e 100644 --- a/pysnow/legacy_request.py +++ b/pysnow/legacy_request.py @@ -44,7 +44,8 @@ def last_response(self): :raise: :NoRequestExecuted: If no request has been executed - :return: last response + :return: + - last response """ if self._last_response is None: raise NoRequestExecuted("%s hasn't been executed" % self) @@ -111,7 +112,8 @@ def get_multiple(self, fields=list(), limit=None, order_by=list(), offset=None): :param limit: Limits the number of records returned :param order_by: Sort response based on certain fields :param offset: A number of records to skip before returning records (for pagination) - :return: Iterable chain object + :return: + - Iterable chain object """ return itertools.chain.from_iterable(self._all_inner(fields, limit, order_by, offset)) @@ -121,7 +123,8 @@ def get_one(self, fields=list()): :param fields: List of fields to return in the result :raise: :MultipleResults: if more than one match is found - :return: Record content + :return: + - Record content """ response = self.session.get(self._get_table_url(), params=self._get_formatted_query(fields, limit=None, order_by=list(), offset=None)) @@ -140,7 +143,8 @@ def insert(self, payload): """Inserts a new record with the payload passed as an argument :param payload: The record to create (dict) - :return: Created record + :return: + - Created record """ response = self.session.post(self._get_table_url(), data=json.dumps(payload)) return self._get_content(response) @@ -151,7 +155,8 @@ def delete(self): :raise: :NoResults: if query returned no results :NotImplementedError: if query returned more than one result (currently not supported) - :return: Delete response content (Generally always {'Success': True}) + :return: + - Delete response content (Generally always {'Success': True}) """ try: result = self.get_one() @@ -173,7 +178,8 @@ def update(self, payload): :raise: :NoResults: if query returned no results :MultipleResults: if query returned more than one result (currently not supported) - :return: The updated record + :return: + - The updated record """ try: result = self.get_one() @@ -199,7 +205,8 @@ def clone(self, reset_fields=list()): :NoResults: if query returned no results :MultipleResults: if query returned more than one result (currently not supported) :UnexpectedResponse: informs the user about what likely went wrong - :return: The cloned record + :return: + - The cloned record """ if not isinstance(reset_fields, list): @@ -245,7 +252,8 @@ def attach(self, file): :raise: :NoResults: if query returned no results :MultipleResults: if query returned more than one result (currently not supported) - :return: The attachment record metadata + :return: + - The attachment record metadata """ try: result = self.get_one() @@ -277,7 +285,8 @@ def _get_content(self, response): :param response: response object :raise: :UnexpectedResponse: if the server responded with an unexpected response - :return: ServiceNow response content + :return: + - ServiceNow response content """ method = response.request.method self.last_response = response @@ -343,7 +352,8 @@ def _get_url(self, resource, item, sys_id=None): :param resource: API resource :param item: API resource item :param sys_id: Record sys_id - :return: url string + :return: + - url string """ url_str = '%(base_url)s/%(base_path)s/%(resource)s/%(item)s' % ( @@ -363,7 +373,8 @@ def _get_url(self, resource, item, sys_id=None): def _get_formatted_query(self, fields, limit, order_by, offset): """ Converts the query to a ServiceNow-interpretable format - :return: ServiceNow query + :return: + - ServiceNow query """ if not isinstance(order_by, list): diff --git a/pysnow/oauth_client.py b/pysnow/oauth_client.py index a6f847a..f4cda5c 100644 --- a/pysnow/oauth_client.py +++ b/pysnow/oauth_client.py @@ -48,7 +48,8 @@ def __init__(self, client_id=None, client_secret=None, token_updater=None, **kwa def _get_oauth_session(self): """Creates a new OAuth session - :return: OAuth2Session object + :return: + - OAuth2Session object """ return self._get_session( @@ -85,7 +86,8 @@ def _legacy_request(self, *args, **kwargs): :param args: args to pass along to _legacy_request() :param kwargs: kwargs to pass along to _legacy_request() - :return: :class:`pysnow.LegacyRequest` object + :return: + - :class:`pysnow.LegacyRequest` object :raises: - MissingToken: If token hasn't been set """ @@ -102,7 +104,8 @@ def resource(self, api_path=None, base_path='/api/now', chunk_size=None): :param api_path: Path to the API to operate on :param base_path: (optional) Base path override :param chunk_size: Response stream parser chunk size (in bytes) - :return: :class:`Resource` object + :return: + - :class:`Resource` object :raises: - InvalidUsage: If a path fails validation """ @@ -118,7 +121,8 @@ def generate_token(self, user, password): :param user: user :param password: password - :return: dictionary containing token data + :return: + - dictionary containing token data :raises: - TokenCreateError: If there was an error generating the new token """ diff --git a/pysnow/query_builder.py b/pysnow/query_builder.py index 33faaf3..44ebc99 100644 --- a/pysnow/query_builder.py +++ b/pysnow/query_builder.py @@ -233,7 +233,8 @@ def __str__(self): - QueryMissingField: if field() hasn't been set - QueryExpressionError: if a expression hasn't been set - :return: String-type query + :return: + - String-type query """ if len(self._query) == 0: diff --git a/pysnow/request.py b/pysnow/request.py index ab75b8c..ba56db9 100644 --- a/pysnow/request.py +++ b/pysnow/request.py @@ -28,7 +28,8 @@ def _get_response(self, method, **kwargs): :param args: args to pass along to _send() :param kwargs: kwargs to pass along to _send() - :return: :class:`pysnow.Response` object + :return: + - :class:`pysnow.Response` object """ response = self._session.request(method, self._url, stream=True, **kwargs) @@ -44,7 +45,8 @@ def get(self, query, limit=None, offset=None, fields=list()): :param fields: List of fields to include in the response created_on in descending order. :param offset: Number of records to skip before returning records - :return: :class:`pysnow.Response` object + :return: + - :class:`pysnow.Response` object """ self._parameters.query = query @@ -64,7 +66,8 @@ def create(self, payload): """Creates a new record :param payload: Dictionary payload - :return: Dictionary of the inserted record + :return: + - Dictionary of the inserted record """ return self._get_response('POST', data=json.dumps(payload)).one() @@ -74,7 +77,8 @@ def update(self, query, payload): :param query: Dictionary, string or :class:`QueryBuilder` object :param payload: Dictionary payload - :return: Dictionary of the updated record + :return: + - Dictionary of the updated record """ if not isinstance(payload, dict): @@ -89,7 +93,8 @@ def delete(self, query): """Deletes a record :param query: Dictionary, string or :class:`QueryBuilder` object - :return: Dictionary containing status of the delete operation + :return: + - Dictionary containing status of the delete operation """ record = self.get(query=query).one() @@ -104,7 +109,8 @@ def custom(self, method, path_append=None, headers=None, **kwargs): :param path_append: (optional) append path to resource.api_path :param headers: (optional) Dictionary of headers to add or override :param kwargs: kwargs to pass along to :class:`requests.Request` - :return: :class:`pysnow.Response` object + :return: + - :class:`pysnow.Response` object """ if headers: diff --git a/pysnow/resource.py b/pysnow/resource.py index 0eb2596..8e75b66 100644 --- a/pysnow/resource.py +++ b/pysnow/resource.py @@ -48,7 +48,8 @@ def get(self, query, limit=None, offset=None, fields=list()): :param limit: (optional) Limits the number of records returned :param fields: (optional) List of fields to include in the response created_on in descending order. :param offset: (optional) Number of records to skip before returning records - :return: :class:`Response` object + :return: + - :class:`Response` object """ return self._request.get(query, limit, offset, fields) @@ -57,7 +58,8 @@ def create(self, payload): """Creates a new record in the API resource :param payload: Dictionary containing key-value fields of the new record - :return: Dictionary of the inserted record + :return: + - Dictionary of the inserted record """ return self._request.create(payload) @@ -67,7 +69,8 @@ def update(self, query, payload): :param query: Dictionary, string or :class:`QueryBuilder` object :param payload: Dictionary containing key-value fields of the record to be updated - :return: Dictionary of the updated record + :return: + - Dictionary of the updated record """ return self._request.update(query, payload) @@ -76,7 +79,8 @@ def delete(self, query): """Deletes matching record :param query: Dictionary, string or :class:`QueryBuilder` object - :return: Dictionary containing information about deletion result + :return: + - Dictionary containing information about deletion result """ return self._request.delete(query) @@ -88,7 +92,8 @@ def custom(self, method, path_append=None, headers=None, **kwargs): :param path_append: (optional) relative to :attr:`api_path` :param headers: (optional) Dictionary of headers to add or override :param kwargs: kwargs to pass along to :class:`requests.Request` - :return: :class:`Response` object + :return: + - :class:`Response` object """ return self._request.custom(method, path_append=path_append, headers=headers, **kwargs) diff --git a/pysnow/response.py b/pysnow/response.py index 4d01312..12ddb74 100644 --- a/pysnow/response.py +++ b/pysnow/response.py @@ -121,7 +121,8 @@ def _get_validated_response(self): def all(self): """Returns a chained generator response containing all matching records - :return: Iterable response + :return: + - Iterable response """ return chain.from_iterable(self._get_validated_response()) @@ -129,7 +130,9 @@ def all(self): def first(self): """Return the first record or raise an exception if the result doesn't contain any data - :return: Dictionary containing the first item in the response content + :return: + - Dictionary containing the first item in the response content + :raise: - NoResults: If no results were found """ @@ -141,11 +144,11 @@ def first(self): return content - def first_or_none(self): """Return the first record or None - :return: Dictionary containing the first item or None + :return: + - Dictionary containing the first item or None """ try: @@ -156,7 +159,9 @@ def first_or_none(self): def one(self): """Return exactly one result or raise an exception. - :return: Dictionary containing the only item in the response content + :return: + - Dictionary containing the only item in the response content + :raise: - MultipleResults: If more than one records are present in the content - NoResults: If no records are present in the content @@ -180,7 +185,9 @@ def one(self): def one_or_none(self): """Return at most one result or raise an exception. - :return: Dictionary containing the matching record or None + :return: + - Dictionary containing the matching record or None + :raise: - MultipleResults: If more than one records are present in the content """ From 936a2071551458002eac468601b5a5a7eeea3567 Mon Sep 17 00:00:00 2001 From: rbw0 Date: Mon, 18 Dec 2017 16:26:46 +0100 Subject: [PATCH 6/6] Documentation fixes --- pysnow/oauth_client.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pysnow/oauth_client.py b/pysnow/oauth_client.py index f4cda5c..7ab054b 100644 --- a/pysnow/oauth_client.py +++ b/pysnow/oauth_client.py @@ -66,9 +66,9 @@ def _get_oauth_session(self): ) def set_token(self, token): - """Sets token after validating + """Validate and set token - :param token: dict containing the information required to create an OAuth2Session + :param token: the token (dict) to set """ if not token: