Giter VIP home page Giter VIP logo

pysnow's Introduction

 ______   __  __    ______    __   __    ______    __     __
/\  == \ /\ \_\ \  /\  ___\  /\ "-.\ \  /\  __ \  /\ \  _ \ \
\ \  _-/ \ \____ \ \ \___  \ \ \ \-.  \ \ \ \/\ \ \ \ \/ ".\ \
 \ \_\    \/\_____\ \/\_____\ \ \_\\"\_\ \ \_____\ \ \__/".~\_\
  \/_/     \/_____/  \/_____/  \/_/ \/_/  \/_____/  \/_/   \/_/
		- ServiceNow API Client Library

image image image image image

Documentation

The documentation is available at https://pysnow.readthedocs.io

Development status

The development status of pysnow is stable; maintenence will be performed, but no new features added.

New features goes into rbw/aiosnow: a modern, asynchronous library for interacting with ServiceNow.

Author

Robert Wikman <[email protected]>

Credits

Thank you @contributors, and Jetbrains for IDE licenses.

pysnow's People

Contributors

akasurde avatar denverj avatar dependabot[bot] avatar fopinappb avatar jcpunk avatar jdugan1024 avatar mvanderlee avatar punkrokk avatar rbw avatar ryancurrah avatar tirkarthi avatar washcycle avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pysnow's Issues

How to solve pysnow.exceptions.MultipleResults

Hi,

I have a PySnow script that searches for users based on their e-mail address:

def get_caller(email):
    incident = c.resource(api_path='/table/sys_user')
    incidents = incident.get(query={"email": email})
    try:
        response = incidents.one()
    except pysnow.exceptions.MultipleResults:
        response = incidents[0]
    except pysnow.exceptions.NoResults:
        response = find_caller_by_old_email(email)
    return response

However for some users there are two active records with the same e-mail in the ServiceNow database.
two active B-id's

While this is something that shouldn't happen, it's nevertheless something I have to deal with. Else I get the following error:

(....)
  File "/Users/hermanvanderveer/anaconda3/lib/python3.6/site-packages/pysnow/response.py", line 45, in __getitem__
    return self.one().get(key)
  File "/Users/hermanvanderveer/anaconda3/lib/python3.6/site-packages/pysnow/response.py", line 213, in one
    raise MultipleResults("Expected single-record result, got multiple")
pysnow.exceptions.MultipleResults: Expected single-record result, got multiple

I've tried several options to fix this. incidents[0] didn't work, nor did incidents.first() which throws an error like first() only works when stream=true.

Also I would prefer if I could get the user with the highest B-number or latest creation date or something. How can I fix this?

Paramters - Fields

Quick question about sysparm_fields. I'm trying to limit the number of fields in the response with parameters.fields(), but it does not seem to be passing the request properly. I'm still getting back all fields in the custom table. If I submit the same fields using curl, I get only the fields passed back.

con.parameters.fields
'short_description,account,number'

Is there another method to pass the sysparm_fields list?

Edit: after trying several different things, 2 minutes after posting the question I'm able to run it successfully with .get(query={'query': 'query'}, fields=['short_description', 'number', 'account']).

ConnectionResetError WinError 10054 with Django 2.1/Python3/Windows server

When attempting the run the following code within PyCharm running on Windows 7 using python 3.6.4 I'm getting the following:

import pysnow
import requests

def get_incidents():
s = requests.Session()
s.auth = requests.auth.HTTPBasicAuth('my_sweet_user', 'my_killer_password')
# Create client object
c = pysnow.Client(instance='my_epic_instance', session=s)
incident = c.resource(api_path='/table/incident').get(query={'number': 'INC5069114'})
return incident.all()

print(get_incidents())

The Error:

ConnectionResetError: [WinError 10054] An existing connection was forcibly closed by the remote host

This same code runs on the same version of python on linux, but will result in this error with or without the Session.

Any thoughts?

Full Trace Attached
full_python3_django2_pysnow_trace.txt

Handling HTTP response 202

ServiceNow can reply with empty response with HTTP 202 status code.
Since the response is empty call to self._response.json() in Response._get_buffered_response raises an exception.

[Feature] include 'link' attrib?

I use this mostly for CMDB queries. It would be helpful if, when the returned item has 'sys_id' and 'link' is not defined for the object, the 'link' attrib is populated with a link back to the raw object via the API.

I'm not familiar with ObjectBuilder, so I'm not sure I could build this...

`sysparm_limit` parameter in version London should be > 0

It seems that the sysparm_limit parameter should be >0 in version London. The current default value (0), yields the following error (copied response from browser):

<?xml version="1.0" encoding="UTF-8"?>
<response>
    <error>
        <detail>sysparm_limit value must be a positive integer</detail>
        <message>Invalid value given for sysparm_limit</message>
    </error>
    <status>failure</status>
</response>

The returned HTTP status is 400.

Older versions (tested with Istanbul) using the same query returns HTTP 200 and if there are any matches for the given query, the results.

ModuleNotFoundError: No module named 'pysnow.legacy'

After installing 0.6.0, I am receiving the error:

>>> import pysnow
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "lib/python3.6/site-packages/pysnow/__init__.py", line 4, in <module>
    from .client import Client
  File "lib/python3.6/site-packages/pysnow/client.py", line 9, in <module>
    from .legacy.request import LegacyRequest
ModuleNotFoundError: No module named 'pysnow.legacy'
>>>

more detailed error messages on POST operations

Currently the code seems to perform a POST operation, and only check the HTTP response code. In Request::_get_content, moving up the content_json retrieval and checking for the existence of error, we can get more detailed errors as well, pointing out data formatting errors and column requirements and so on.

These kind of things are probably second nature for others with extensive experience, but for a beginner like me it was not apparent what I was doing wrong, until I checked the API Explorer and realized there were more detailed errors available in the response.

Maybe some additional error checking is necessary, for existence of content_json['error']['message'] and detail, I'm not sure though...

246a247,248
>         content_json = response.json()
> 
255,257c257,262
<             raise UnexpectedResponse("Unexpected HTTP response code. Expected: 201, got %d" % response.status_code)
< 
<         content_json = response.json()

> 	    if 'error' in content_json:
>                 raise UnexpectedResponse("Unexpected HTTP response code. Expected: 201, got %d. \nError: %s\nDetails: %s" % (response.status_code,
> 															     content_json['error']['message'],
> 															     content_json['error']['detail']))
> 	    else:
>                 raise UnexpectedResponse("Unexpected HTTP response code. Expected: 201, got %d." % response.status_code)

Cannot chain `.field()` in QueryBuilder

I have the following data structure:

{
    "provided_by": {
        "link": "https://corp.service-now.com/api/now/table/cmdb_ci/3f3db990db3bebc40ecc79bb8c9619f9",
        "value": "3f3db990db3bebc40ecc79bb8c9619f9"
    },
}

I'm trying to build a query that finds the object whose provided_by has a value for the value field. For instance:

provider_val = '3f3db990db3bebc40ecc79bb8c9619f9'
qb = (pysnow.QueryBuilder()
      .field('provided_by').field('value').equals(provider_val)
      )

This returns all of the entries without filtering them. I've also tried the following:

provider_val = '3f3db990db3bebc40ecc79bb8c9619f9'
qb = (pysnow.QueryBuilder()
      .field('provided_by').contains(provider_val)
      )

This actually returns nothing.

Is there any ways to filter against that value key in the provided_by field?

Response.all() does not return an empty iterator if the table is empty

Python 3.6.3
Querying an empty table with all() does not return an empty iterator. You can run this against the free dev instance:

>>> data = client.resource(api_path='/table/cmdb_ci_storage_server').get(query={}).all()
>>> print([d for d in data])
[{}]

In some cases two empty dictionaries are returned.

update() and insert() returns

These methods currently returns a dictionary contained in a list, a list always 1 in length, which makes it useless.
Small change, but it causes API breakage.
Perhaps deprecate somehow.

sysparams not passed when making call to a table.

I have a function
def connect_to_instance(self, instance_name, username, password): c = pysnow.Client(instance=instance_name, user=username, password=password) c.parameters.add_custom({'sysparm_display_value': 'True', 'sysparm_exclude_reference_link': 'True'}) return c

My querybuilder query:
(pysnow.QueryBuilder().field('assignment_group').equals(['https://my_instance.service-now.com/api/now/table/sys_user_group/my_group_value', 'my_group_value']).AND().field('state').not_equals('100'))

I get results back from service now, foreign key relationships are followed and I get the values I expect.

But when I try to query with the foreign key values and not the values from the actual change table:
(pysnow.QueryBuilder().field('assignment_group').equals('MY-SWEET-GROUP').AND().field('state').equals('Closed'))
I get no results back.

Is there another place I need to set the client parameters?

Ability to upload attachments using the Attachment API

Would you be open to a Pull Request with an additional function in the Client class that uploads attachments?

curl "https://dev00000.service-now.com/api/now/attachment/file?table_name=change_request&table_sys_id=414d1d584f072200745e3b728110c735&file_name=screenshot.png" \
--request POST \
--header "Accept:application/json" \
--user 'admin':'admin'
--header "Content-Type: "
-F "[email protected]" 

Table API GET pagination support

Feature Request: Table API GET pagination support

When working with a large set of data, you eventually want to paginate the responses of the REST calls with a limit and offset. This request is to add some additional functionality to to the library to make this easier.

ServiceNow's Table API GET response headers do include a link to the next set of results, in addition the "X-Total-Count" header will contain the amount of rows returned. See https://developer.servicenow.com/app.do#!/rest_api_doc?id=c_TableAPI

Possible ideas include adding a link_next() method to the Response class or a paginate flag to the Resource object which would then handle all the pagination for you.

For now I am using a generator function (with v0.6.5):

def paginate_get(resource, limit, *args, **kwargs):
    offset = 0
    kwargs['limit'] = limit
    results = list(resource.get(*args, **kwargs).all())

    while len(results) > 0:
        for item in results:
            yield item

        # Increment offset and get the next page
        offset += limit
        results = list(resource.get(*args, **kwargs, offset=offset).all())

Used like so:

for record in paginate_get(client.resource(api_path='/table/cmdb_ci_server'), limit=10, query={}):
    print(record)

If there is a better way to do this already, I would not mind seeing it and having an example added to the documentation. Thanks.

Using ServiceNow Incident Response in an If Statement

Could someone possibly give me an example of use with an if statement specifically using the assignment_group field? For context here is what I am trying to do:

incident = c.resource(api_path='/table/incident')

'#` Query for incidents with state 1
'response = incident.get(query={'number':'INC0454225'})

' #Iterate through response
' for record in response.all():
' if (record['assignment_group'] == ' ASSIGNMENT GROUP NAME OR VALUE'):
' print('Assignment Group matches')

' else:
' print('assignment group does not match')

As you can see above I am trying to just compare the assignmnet_group value which when I print the whole incident to the screen teh specific assignment group value looks like this:

'assignment_group': { 'display_value': 'APPS-Apps TEAM - ITAPPS ''- Service Accounts', 'link': 'https://somecompany.service-now.com/api/now/table/sys_user_group/skdhjghs83kd823jsl3802jjf'},

Can you give me an example or tell me how this should work properly when using pysnow? So that I can compare the assignment group display value == 'SOME GROUP NAME I TYPE IN' and if its true just print to the screen?

Unauthorized access

import pysnow

# Create client object
c = pysnow.Client(instance='********', user='*******', password='*********')

# Define a resource, here we'll use the incident table API
incident = c.resource(api_path='/table/incident')

# Query for incident with number INC012345
response = incident.get(query={'number': 'INC0683731'})

# Print out the matching record
print(response.one())

raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 401 Client Error: Unauthorized for url: https://cablevision.service-now.com/api/now/table/incident?sysparm_query=number%3DINC0683731&sysparm_limit=10000&sysparm_offset=0&sysparm_display_value=False&sysparm_suppress_pagination_header=False&sysparm_exclude_reference_link=False&sysparm_view=&sysparm_fields=

QB equals() for lists containing integers fails

>>> from pysnow import QueryBuilder as qb
>>> qb().field('test').equals([1, 2, 3])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/pysnow/query.py", line 70, in equals
    return self._add_condition('IN', ",".join(value), types=[str])
TypeError: sequence item 0: expected string, int found
  • Enable QB equals() list to ServiceNow string-type-query conversion to support integers

IN operator in querybuilder causes an exception

Traceback (most recent call last):
  File "exporter.py", line 169, in <module>
    query = s.query(table='sc_catalog', query=QueryBuilder().field('sys_id').equals(catalogID))
  File "/home/sam/git/github/servicenow-servicecatalog-exporter/.venv/local/lib/python2.7/site-packages/pysnow/query.py", line 70, in equals
    return self._add_condition('IN', ",".join(value), types=[str])
  File "/home/sam/git/github/servicenow-servicecatalog-exporter/.venv/local/lib/python2.7/site-packages/pysnow/query.py", line 148, in _add_condition
    raise QueryTypeError("Invalid type passed to %s() , expected: %s" % (caller, types))

Here's the code which raised the exception:
https://github.com/samrocketman/servicenow-servicecatalog-exporter/blob/82f1981fc10e6d1a7d872864fb20a6321bca8073/exporter.py

No base exception?

Hi, any reason why you don't have a base class exception, that everything else in pysnow inherits from?

SSL issues

Hello

current behavior
When I am disabling the SSL it works fine

s = requests.Session()
s.proxies.update({'https': 'https://proxy_login:proxy_password@proxy:8080'})
s.auth = requests.auth.HTTPBasicAuth(user, pwd)
s.verify = False

# Create client object
c = pysnow.Client(instance=instance, session=s)

response = incident.get(query={'number': id_number})

however I want to make sure there is no security breach but when removing
s.verify = False
I got the below message:

requests.exceptions.SSLError: HTTPSConnectionPool(host='servicesitqualif.service-now.com', port=443): Max retries exceeded with url: /api/now/table/incident?sysparm_query=number%3DICD003279020&sysparm_limit=10000&sysparm_offset=0&sysparm_display_value=False&sysparm_suppress_pagination_header=False&sysparm_exclude_reference_link=False&sysparm_view=&sysparm_fields= (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1056)')))

expected behavior behavior
Be able to instantiate the client and without disabling SSL

requests lib verify option not available

In our development environment, our SSL certs are not valid. I do not see a way in pysnow to pass along verify=False. I would recommend passing kwargs through to the requests init. Any reason why there is no customization around that?

Date/time comparisons broken for me since #136

Hi Robert,

I just upgraded to the tag that contains the gs.dateGenerate changes (#136), and now my lookups are broken.

I've tested many combinations of sysparm_display_value, etc, but what I see is:

  • API account is in Australia/Sydney TZ
  • Returned dates/times change accordingly based on sysparm_display_value
  • Your code converts to UTC if a TZ is detected, assuming then that the query wants it in UTC
  • Manually querying with Postman, it seems that the date/time sent using gs.dateGenerate always results in SN interpreting that as the accounts' TZ, not UTC

So for example, I use a QueryBuilder, using "local" time, and pysnow converts that to UTC and I get more results than I should.

I've spent hours scouring SN doco, and haven't found anything definitive around what SN expects in those glide things; even using sysparm_input_display_value makes no difference.

Even the doco on dateGenerate is vague-ish:

Generates a date and time for the specified date in GMT.

Yes, so that converts to GMT, but it seems their backend will still search assuming local TZ, or account TZ.

Unauthorized Client 401

I'm trying to run the code given to fetch data:

import pysnow

# Create client object
c = pysnow.Client(instance='TheBigCompanyInstance', user='MyActiveDirectoryUser', password='MyCoolPassword')

# Define a resource, here we'll use the incident table API
incident = c.resource(api_path='/table/task')

# Query for incidents with state 1
response = incident.get(query={'state': 1}, stream=True)

# Iterate over the result and print out `sys_id` of the matching records.
for record in response.all():
    print(record['sys_id'])

I get an Error:

HTTPError: 401 Client Error: Unauthorized for url: https://TheBigCompanyInstance.service-now.com/api/now/table/task?sysparm_query=state%3D1&sysparm_limit=10000&sysparm_offset=0&sysparm_display_value=False&sysparm_suppress_pagination_header=False&sysparm_exclude_reference_link=False&sysparm_view=&sysparm_fields=

When I take this particular link in my Browser, I can get the response. But not in my Python code.

Is using an Active Directory user an issue to connect to ServiceNow with pysnow?
My company is using an SSO to connect to the multiple intern website, I'm not familiar with this technology, could it be a way to investigate?

datetime comparisons don't work

The datetime comparisons result in opened_at>2019-11-11 00:00:00. This doesn't actually work. No error is thrown, but ServiceNow ignores the query.
It should be opened_at>javascript:gs.dateGenerate("2019-11-11 00:00:00")

This is implemented in the Criterion handling in PR #135 but not in the QueryBuilder itself.

can't get less than all values with sysparm_limit

I am trying to get only a subset of a table, I saw that Client() has a default_payload and you can specify a sysparm_limit, but when I set it, when doing:

s = sn.Client('mysn', user, pwd, default_payload={"sysparm_limit": "2"})
request = s.query(table='mytable', query={})
response = request.get_all(fields=['sys_id', 'value'])
for each in response:
  print each

I get all the results, but paged through my sysparm_limit. I would prefer (or at least have the option to) to see only N results total.

update() not recognizing argument?

table.all()
[{'sys_id': '<>', 'u_security_incident': {'link': 'https://<>.service-now.com/api/now/table/sn_si_incident/<>', 'value': '<>'}, 'sys_updated_by': 'mp', 'u_url': 'URL here', 'sys_created_on': '2019-05-16 23:56:28', 'sys_mod_count': '1', 'sys_updated_on': '2019-05-17 00:35:22', 'sys_tags': '', 'u_detection_type': 'ERA', 'sys_created_by': 'admin', 'u_detection_category': 'C2'}]. ***some info redacted

det_update = {'u_detection_category': 'C2', 'u_detection_type': 'ERA', 'u_url': 'URL here'}

updated_table = table.update(payload=det_update)

updated_table.update()
Traceback (most recent call last):
File "", line 1, in
TypeError: update() missing 1 required positional argument: 'payload'

Not sure if I'm doing something incorrect or update() is not recognizing the passed parameter.

How to Query and Update Journal Tables - WorkNotes

I need the ability to query and update the sys journal tables. I would like the ability to query the journal table to retrieve a list of work notes and/or comments associated with an incident ticket. I also would like the ability to post an updated work note to an incident ticket. Perhaps these capabilities are already available - but its not clear to me how to go about doing it. Any help is greatly appreciated!

Thanks in advance!
David

Date query using querybuilder not working

Querying a table using the a string for a date as the querybuilder creates does not seem to be working. The query below copied from the GUI returns 10 records.

active=true^start_date>javascript:gs.dateGenerate('2018-04-19','18:59:00')^end_date<javascript:gs.dateGenerate('2018-04-19','20:00:00')

The following identical query as created by the pysnow query builder returns no records at all.

active=true^start_date>2018-04-19 18:59:00^end_date<2018-04-19 20:00:00

API calls fail after using attachments due to custom request updating header content type

pysnow.attachment.upload() passes Content-Type header

        if multipart:
            headers["Content-Type"] = "multipart/form-data"
            path_append = '/upload'
        else:
            headers["Content-Type"] = "text/plain"
            path_append = '/file'

        return resource.request(method='POST', data=data, headers=headers, path_append=path_append)

that creates a custom request in pysnow.resource.request()

    def request(self, method, path_append=None, headers=None, **kwargs):
        """Create a custom request
        :param method: HTTP method to use
        :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 self._request.custom(method, path_append=path_append, headers=headers, **kwargs)

which affects headers in all future API calls with the same client

        if headers:
            self._session.headers.update(headers)

and results in 415 responses due to invalid media type:

  File "/usr/lib/python2.7/site-packages/pysnow/response.py", line 45, in __getitem__
    return self.one().get(key)
  File "/usr/lib/python2.7/site-packages/pysnow/response.py", line 208, in one
    result, count = self._get_buffered_response()
  File "/usr/lib/python2.7/site-packages/pysnow/response.py", line 133, in _get_buffered_response
    response = self._get_response()
  File "/usr/lib/python2.7/site-packages/pysnow/response.py", line 115, in _get_response
    response.raise_for_status()
  File "/usr/lib/python2.7/site-packages/requests/models.py", line 940, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 415 Client Error: Unsupported Media Type for url: XXXXXX

@rbw : would appreciate any thoughts outside of instantiating a wholly new pysnow.Client instance just to clear the attachment headers for making subsequent calls.

Updating and deleting records not working

I am using this library to build a quick CRUD app and am unable to update/delete a record.

I am able to connect and get single/multiple records. When I update/delete it does nothing and then returns the original record. I am using your examples as well.

Example tables I have tried incident, problem, and cmdb_ci_server. None work. Any Ideas?

Using a dev instance from https://developer.servicenow.com/ on version Jakarta. Tried with python2.8 & python3.6

Example fetch_one_or_none() fails because

In pysnow 0.7.4 (installed with pip), testing the fetch_one_or_none() example locally as read in the fetching data doc it fails with:

if not self._stream:
>       raise InvalidUsage('first() is only available when stream=True')
E       pysnow.exceptions.InvalidUsage: first() is only available when stream=True

It works by adding the param stream=True to the line:
response = incident.get(query={'state': 3}, stream=True)

By default stream=False in the response.get() method. Shouldn't it be True by default?

Using generator method to stream all records not working on large data sets

Hi, I don't think this is an issue with the pysnow package per say but was curious if other had encountered this and what if any their workarounds were.

I'm trying to grab all rows and columns from the incident table and dump the data to a csv that I can then load into a Postgres database with a copy from command.

The error seems to truncate the data so I'm not getting a complete extract. I have noticed that if I limit the columns it seems to work a little better. For example, if I extract half of the columns in one run and the other half in another it works fine leading me to think it's something to do with the amount of data and not necessarily the content itself. Adding a try except block around the writer.writerows line doesn't seem to help isolate the problem either and still results in an incomplete extract.

Does anyone have any ideas around how to correct this ijson issue?

Example Code (1st loop through only)

    offset = 0
    limit = 10000

    response = incident.get(offset=offset, limit=limit, stream=True)

    # Iterate over the result and write out each row to csv
    with open('servicenow_incidents.csv', 'w', newline='', encoding='utf-8') as mycsv:
        writer = csv.DictWriter(mycsv, fieldnames=fields, dialect='excel', quoting=csv.QUOTE_MINIMAL)
        writer.writeheader()
        writer.writerows(record for record in response.all())

Stacktrace

ijson.backends.python.UnexpectedSymbol: Unexpected symbol ']' at 19253199

OAuth Client resource calls fail if the token is expired

Re-using a resource will cause the first call on an expired token to fail, instead of refreshing the token.
Creating a new resource for every call will automatically refresh the token as expected so as a workaround, one can simply create the resource for every call.

Steps to reproduce:

  1. Create OAuth client
  2. Set token access lifetime to 10 seconds in ServiceNOW
  3. Create a resource for a table
  4. Do a get() call, wait for longer than 10 seconds then do another get call
  5. The call will fail with oauthlib.oauth2.rfc6749.errors.MissingTokenError: (missing_token) Missing access token parameter.
  6. Using:
    pysnow==0.7.4
    requests==2.19.1
    requests-oauthlib==1.0.0
    

Code Example

Setup an oauth client per the example in the docs

incident_resource = s.resource(api_path='/table/incident')
record = incident_resource.get(query={}).first()
time.sleep(15)
# This will fail because the token is expired
record = incident_resource.get(query={}).first()
time.sleep(15)
record = s.resource(api_path='/table/incident').get(query={}).first()
time.sleep(15)
# This works fine and the token will be refreshed
record = s.resource(api_path='/table/incident').get(query={}).first()

Exception

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "\lib\site-packages\pysnow\resource.py", line 104, in get
    return self._request.get(query, limit, offset, fields, stream)
  File "\lib\site-packages\pysnow\request.py", line 75, in get
    return self._get_response('GET', stream=stream)
  File "\lib\site-packages\pysnow\request.py", line 44, in _get_response
    response = self._session.request(method, self._url, stream=use_stream, params=params, **kwargs)
  File "\lib\site-packages\requests_oauthlib\oauth2_session.py", line 343, in request
    self.auto_refresh_url, auth=auth, **kwargs
  File "\lib\site-packages\requests_oauthlib\oauth2_session.py", line 309, in refresh_token
    self.token = self._client.parse_request_body_response(r.text, scope=self.scope)
  File "\lib\site-packages\oauthlib\oauth2\rfc6749\clients\base.py", line 411, in parse_request_body_response
    self.token = parse_token_response(body, scope=scope)
  File "\lib\site-packages\oauthlib\oauth2\rfc6749\parameters.py", line 379, in parse_token_response
    validate_token_parameters(params)
  File "\lib\site-packages\oauthlib\oauth2\rfc6749\parameters.py", line 389, in validate_token_parameters
    raise MissingTokenError(description="Missing access token parameter.")
oauthlib.oauth2.rfc6749.errors.MissingTokenError: (missing_token) Missing access token parameter.

Querying cmn_location.do

I'm trying to query a location table in service now - this table is named 'cmn_location.do'

A normal ServiceNow URL looks like this:
https://xxxxxxxxx.service-now.com/cmn_location.do?sysparm_query=streetLIKE36600+VanDyke+Avenue&sysparm_limit=10000&sysparm_offset=0&sysparm_display_value=all&sysparm_suppress_pagination_header=False&sysparm_exclude_reference_link=False&sysparm_view=&sysparm_fields=

Notice the base path?

How do I specify that in this libraries resource setup:

pysnow_cmn_location = pysnow_conn.resource(api_path='cmn_location.do', base_path=None)

The above doesnt work

I get the following error message:

pysnow.exceptions.InvalidUsage: Path validation failed - Expected: '/[/component], got: cmn_location.do

I've tried several different variations of the base_path but can't seem to get it working - I've different versions by removing base_path altogether like shown below with and without '/' in front of cmn_location.do and nothing works

pysnow_cmn_location = pysnow_conn.resource(api_path='/cmn_location.do')

Any suggestions or help is much appreciated! Thank you!

Images added to tickets not viewable

Currently I'm adding images to Snow just like any other attachment:

def post_call(new_record):
    incident = c.resource(api_path='/table/new_call')
    result = incident.create(payload=new_record)
    sys_id = result.one().get('sys_id')
    att_list = new_record['attachment_list']
    for att in att_list:
        incident.attachments.upload(sys_id=sys_id, file_path=att)

However when I try to view an image that's added like this it just shows the raw image data:
view image results
If I download the image first it works just fine.

I assume this is because the images are not marked as images by PySnow. I looked through the PySnow documentation and I couldn't find anything regarding a setting, so thought it might be a bug.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.