Skip to content

Commit

Permalink
Merge pull request #73 from rbw0/branch-0.6.3
Browse files Browse the repository at this point in the history
- Fixes an issue with OAuthClient and prepared requests
- Documentation updates
  • Loading branch information
rbw authored Dec 18, 2017
2 parents 09a751d + 936a207 commit 5ddc800
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 58 deletions.
2 changes: 1 addition & 1 deletion pysnow/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@
from .resource import Resource

__author__ = "Robert Wikman <[email protected]>"
__version__ = "0.6.2"
__version__ = "0.6.3"
25 changes: 19 additions & 6 deletions pysnow/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -86,15 +88,22 @@ 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()
s.auth = HTTPBasicAuth(self._user, self._password)
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

Expand All @@ -103,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. "
Expand All @@ -124,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
"""
Expand All @@ -144,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)
Expand All @@ -155,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)
Expand Down
33 changes: 22 additions & 11 deletions pysnow/legacy_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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))

Expand All @@ -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))
Expand All @@ -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)
Expand All @@ -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()
Expand All @@ -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()
Expand All @@ -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):
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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' % (
Expand All @@ -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):
Expand Down
37 changes: 22 additions & 15 deletions pysnow/oauth_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,23 +48,27 @@ 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 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
"""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:
Expand All @@ -82,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
"""
Expand All @@ -99,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
"""
Expand All @@ -115,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
"""
Expand Down
3 changes: 2 additions & 1 deletion pysnow/query_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
27 changes: 14 additions & 13 deletions pysnow/request.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-

import json
import requests

from .response import Response
from .exceptions import InvalidUsage
Expand All @@ -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
"""
Expand All @@ -29,14 +28,11 @@ 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
"""

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)
Expand All @@ -49,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
Expand All @@ -69,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()
Expand All @@ -79,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):
Expand All @@ -94,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()
Expand All @@ -109,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:
Expand Down
Loading

0 comments on commit 5ddc800

Please sign in to comment.