From 96bb8b614cdaf3dfc9ffeef714578d0721ed22a9 Mon Sep 17 00:00:00 2001 From: Robert Wikman Date: Thu, 27 Apr 2017 16:35:58 +0200 Subject: [PATCH 01/10] Changed to () to force line joining when chaining in QB usage example --- docs/usage/full/query_builder.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/usage/full/query_builder.rst b/docs/usage/full/query_builder.rst index 572e348..649800f 100644 --- a/docs/usage/full/query_builder.rst +++ b/docs/usage/full/query_builder.rst @@ -17,10 +17,10 @@ See the :meth:`pysnow.Request.get_all` and :meth:`pysnow.QueryBuilder` documenta end = dt.now() - td(days=20) # Query incident records with number starting with 'INC0123', created between 1970-01-01 and 20 days back in time - qb = pysnow.QueryBuilder()\ - .field('number').starts_with('INC0123')\ - .AND()\ - .field('sys_created_on').between(start, end) + qb = (pysnow.QueryBuilder() + .field('number').starts_with('INC0123') + .AND() + .field('sys_created_on').between(start, end)) r = s.query('incident', query=qb) From 44fb08fe2bac71394b4551a74f7cb616193dd519 Mon Sep 17 00:00:00 2001 From: Robert Wikman Date: Thu, 27 Apr 2017 16:45:21 +0200 Subject: [PATCH 02/10] Added custom session usage example --- docs/usage/client.rst | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/docs/usage/client.rst b/docs/usage/client.rst index a113a94..74a1f8f 100644 --- a/docs/usage/client.rst +++ b/docs/usage/client.rst @@ -3,7 +3,7 @@ Connecting This shows some examples of how to connect with pysnow using either username and password or OAuth. -See the :meth:`documentation for `pysnow.Client` ` for more info +See the :meth:`pysnow.Client` documentation for details. Using username and password --------------------------- @@ -18,6 +18,25 @@ Using username and password password='mypassword') +Using a custom session object +----------------------------- + +You can pass a custom session object to `Client`. +In this example regular user / pass authentication is used, but with SSL verification disabled. + +.. code-block:: python + + import pysnow + import requests + + s = requests.Session() + s.verify = False + s.auth = requests.auth.HTTPBasicAuth('myusername', 'mypassword') + + # Create client object + s = pysnow.Client(instance='myinstance', session=s) + + Using OAuth ----------- From 2d0337fdcd55ec46de2101197cfd44fb342cab19 Mon Sep 17 00:00:00 2001 From: Robert Wikman Date: Thu, 27 Apr 2017 16:46:15 +0200 Subject: [PATCH 03/10] Fixed typo --- docs/usage/client.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage/client.rst b/docs/usage/client.rst index 74a1f8f..60f13f6 100644 --- a/docs/usage/client.rst +++ b/docs/usage/client.rst @@ -34,7 +34,7 @@ In this example regular user / pass authentication is used, but with SSL verific s.auth = requests.auth.HTTPBasicAuth('myusername', 'mypassword') # Create client object - s = pysnow.Client(instance='myinstance', session=s) + sn = pysnow.Client(instance='myinstance', session=s) Using OAuth From 6de1d5d3baf1c26ff771e30d0459572ffc85b7d0 Mon Sep 17 00:00:00 2001 From: Robert Wikman Date: Thu, 27 Apr 2017 18:28:59 +0200 Subject: [PATCH 04/10] Reworked exception testing --- tests/test_query.py | 165 +++++++++++++++----------------------------- 1 file changed, 54 insertions(+), 111 deletions(-) diff --git a/tests/test_query.py b/tests/test_query.py index b48ad65..2381780 100644 --- a/tests/test_query.py +++ b/tests/test_query.py @@ -6,83 +6,56 @@ class TestIncident(unittest.TestCase): def test_query_no_expression(self): - try: - q = str(pysnow.QueryBuilder().field('test')) - self.assertFalse(q) - except pysnow.QueryEmpty: - pass + q = pysnow.QueryBuilder().field('test') + self.assertRaises(pysnow.QueryEmpty, q.__str__) def test_query_no_query(self): - try: - q = str(pysnow.QueryBuilder()) - self.assertFalse(q) - except pysnow.QueryEmpty: - pass + q = pysnow.QueryBuilder() + self.assertRaises(pysnow.QueryEmpty, q.__str__) def test_query_unexpected_logical(self): - try: - q = str(pysnow.QueryBuilder().AND()) - self.assertFalse(q) - except pysnow.QueryExpressionError: - pass + q = pysnow.QueryBuilder() + self.assertRaises(pysnow.QueryExpressionError, q.AND) def test_query_expression_no_field(self): - try: - q = str(pysnow.QueryBuilder().equals('test')) - self.assertFalse(q) - except pysnow.QueryMissingField: - pass + q = pysnow.QueryBuilder() + self.assertRaises(pysnow.QueryMissingField, q.equals, 'test') def test_query_no_field_expression(self): - try: - q = str(pysnow.QueryBuilder().field('test').equals('test').AND().field('test')) - self.assertFalse(q) - except pysnow.QueryExpressionError: - pass + q = pysnow.QueryBuilder().field('test').equals('test').AND().field('test') + self.assertRaises(pysnow.QueryExpressionError, q.__str__) def test_query_field_multiple_expressions(self): - try: - q = str(pysnow.QueryBuilder().field('test').equals('test').between(1, 2)) - self.assertFalse(q) - except pysnow.QueryMultipleExpressions: - pass + q = pysnow.QueryBuilder().field('test').equals('test') + self.assertRaises(pysnow.QueryMultipleExpressions, q.between, 1, 2) def test_query_unfinished_logical(self): - try: - q = str(pysnow.QueryBuilder().field('test').equals('test').AND()) - self.assertFalse(q) - except pysnow.QueryMissingField: - pass + q = pysnow.QueryBuilder().field('test').equals('test').AND() + self.assertRaises(pysnow.QueryMissingField, q.__str__) def test_query_logical_and(self): # Make sure AND() operator between expressions works q = pysnow.QueryBuilder().field('test').equals('test').AND().field('test2').equals('test') - self.assertEquals(str(q), 'test=test^test2=test') def test_query_logical_or(self): # Make sure OR() operator between expressions works q = pysnow.QueryBuilder().field('test').equals('test').OR().field('test2').equals('test') - self.assertEquals(str(q), 'test=test^ORtest2=test') def test_query_logical_nq(self): # Make sure NQ() operator between expressions works q = pysnow.QueryBuilder().field('test').equals('test').NQ().field('test2').equals('test') - self.assertEquals(str(q), 'test=test^NQtest2=test') def test_query_cond_between(self): # Make sure between with str arguments fails - try: - q = pysnow.QueryBuilder().field('test').between('test', 'test') - self.assertFalse(q) - except pysnow.QueryTypeError: - pass + q1 = pysnow.QueryBuilder().field('test') + self.assertRaises(pysnow.QueryTypeError, q1.between, 'test', 'test') # Make sure between with int arguments works - q1 = str(pysnow.QueryBuilder().field('test').between(1, 2)) - self.assertEquals(str(q1), 'testBETWEEN1@2') + q2 = str(pysnow.QueryBuilder().field('test').between(1, 2)) + self.assertEquals(str(q2), 'testBETWEEN1@2') start = dt(1970, 1, 1) end = dt(1970, 1, 2) @@ -94,55 +67,39 @@ def test_query_cond_between(self): def test_query_cond_starts_with(self): # Make sure type checking works - try: - q = pysnow.QueryBuilder().field('test').starts_with(1) - self.assertFalse(q) - except pysnow.QueryTypeError: - pass + q1 = pysnow.QueryBuilder().field('test') + self.assertRaises(pysnow.QueryTypeError, q1.starts_with, 1) # Make sure a valid operation works - q = pysnow.QueryBuilder().field('test').starts_with('val') - - self.assertEquals(str(q), 'testSTARTSWITHval') + q2 = pysnow.QueryBuilder().field('test').starts_with('val') + self.assertEquals(str(q2), 'testSTARTSWITHval') def test_query_cond_ends_with(self): # Make sure type checking works - try: - q = pysnow.QueryBuilder().field('test').ends_with(1) - self.assertFalse(q) - except pysnow.QueryTypeError: - pass + q1 = pysnow.QueryBuilder().field('test') + self.assertRaises(pysnow.QueryTypeError, q1.ends_with, 1) # Make sure a valid operation works - q = pysnow.QueryBuilder().field('test').ends_with('val') - - self.assertEquals(str(q), 'testENDSWITHval') + q2 = pysnow.QueryBuilder().field('test').ends_with('val') + self.assertEquals(str(q2), 'testENDSWITHval') def test_query_cond_contains(self): # Make sure type checking works - try: - q = pysnow.QueryBuilder().field('test').contains(1) - self.assertFalse(q) - except pysnow.QueryTypeError: - pass + q1 = pysnow.QueryBuilder().field('test') + self.assertRaises(pysnow.QueryTypeError, q1.contains, 1) # Make sure a valid operation works - q = pysnow.QueryBuilder().field('test').contains('val') - - self.assertEquals(str(q), 'testLIKEval') + q2 = pysnow.QueryBuilder().field('test').contains('val') + self.assertEquals(str(q2), 'testLIKEval') def test_query_cond_not_contains(self): # Make sure type checking works - try: - q = pysnow.QueryBuilder().field('test').not_contains(1) - self.assertFalse(q) - except pysnow.QueryTypeError: - pass + q1 = pysnow.QueryBuilder().field('test') + self.assertRaises(pysnow.QueryTypeError, q1.not_contains, 1) # Make sure a valid operation works - q = pysnow.QueryBuilder().field('test').not_contains('val') - - self.assertEquals(str(q), 'testNOTLIKEval') + q2 = pysnow.QueryBuilder().field('test').not_contains('val') + self.assertEquals(str(q2), 'testNOTLIKEval') def test_query_cond_is_empty(self): # Make sure a valid operation works @@ -152,59 +109,45 @@ def test_query_cond_is_empty(self): def test_query_cond_equals(self): # Make sure type checking works - try: - q = pysnow.QueryBuilder().field('test').equals(dt) - self.assertFalse(q) - except pysnow.QueryTypeError: - pass + q1 = pysnow.QueryBuilder().field('test') + self.assertRaises(pysnow.QueryTypeError, q1.equals, dt) # Make sure a valid operation works - q = pysnow.QueryBuilder().field('test').equals('test') - - self.assertEquals(str(q), 'test=test') + q2 = pysnow.QueryBuilder().field('test').equals('test') + self.assertEquals(str(q2), 'test=test') def test_query_cond_not_equals(self): # Make sure type checking works - try: - q = pysnow.QueryBuilder().field('test').not_equals(dt) - self.assertFalse(q) - except pysnow.QueryTypeError: - pass + q1 = pysnow.QueryBuilder().field('test') + self.assertRaises(pysnow.QueryTypeError, q1.not_equals, dt) # Make sure a valid operation works - q = pysnow.QueryBuilder().field('test').not_equals('test') - - self.assertEquals(str(q), 'test!=test') + q2 = pysnow.QueryBuilder().field('test').not_equals('test') + self.assertEquals(str(q2), 'test!=test') def test_query_cond_greater_than(self): # Make sure type checking works - try: - q = pysnow.QueryBuilder().field('test').greater_than('a') - self.assertFalse(q) - except pysnow.QueryTypeError: - pass + q1 = pysnow.QueryBuilder().field('test') + self.assertRaises(pysnow.QueryTypeError, q1.greater_than, 'a') # Make sure a valid operation works - q = pysnow.QueryBuilder().field('test').greater_than(1) - self.assertEquals(str(q), 'test>1') + q2 = pysnow.QueryBuilder().field('test').greater_than(1) + self.assertEquals(str(q2), 'test>1') - q = pysnow.QueryBuilder().field('test').greater_than(dt(2016, 2, 1)) - self.assertEquals(str(q), 'test>2016-02-01 00:00:00') + q3 = pysnow.QueryBuilder().field('test').greater_than(dt(2016, 2, 1)) + self.assertEquals(str(q3), 'test>2016-02-01 00:00:00') def test_query_cond_less_than(self): # Make sure type checking works - try: - q = pysnow.QueryBuilder().field('test').less_than('a') - self.assertFalse(q) - except pysnow.QueryTypeError: - pass + q1 = pysnow.QueryBuilder().field('test') + self.assertRaises(pysnow.QueryTypeError, q1.less_than, 'a') # Make sure a valid operation works - q = pysnow.QueryBuilder().field('test').less_than(1) - self.assertEquals(str(q), 'test<1') + q2 = pysnow.QueryBuilder().field('test').less_than(1) + self.assertEquals(str(q2), 'test<1') - q = pysnow.QueryBuilder().field('test').less_than(dt(2016, 2, 1)) - self.assertEquals(str(q), 'test<2016-02-01 00:00:00') + q3 = pysnow.QueryBuilder().field('test').less_than(dt(2016, 2, 1)) + self.assertEquals(str(q3), 'test<2016-02-01 00:00:00') def test_complex_query(self): start = dt(2016, 2, 1) From 203954f11d5dbcea1b41e591268ef1239cbf294d Mon Sep 17 00:00:00 2001 From: Robert Wikman Date: Thu, 27 Apr 2017 18:32:21 +0200 Subject: [PATCH 05/10] Bumped --- pysnow/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pysnow/__init__.py b/pysnow/__init__.py index dfc764f..88458a3 100644 --- a/pysnow/__init__.py +++ b/pysnow/__init__.py @@ -6,4 +6,4 @@ from pysnow.exceptions import * __author__ = "Robert Wikman " -__version__ = "0.4.2" +__version__ = "0.4.3" From 22732fbfb819aefee14e0ba33e8241e1ef41d07d Mon Sep 17 00:00:00 2001 From: Robert Wikman Date: Thu, 27 Apr 2017 19:06:57 +0200 Subject: [PATCH 06/10] Updated QB examples --- docs/usage/full/query_builder.rst | 10 ++++++---- docs/usage/query.rst | 21 +++++++++++++++------ 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/docs/usage/full/query_builder.rst b/docs/usage/full/query_builder.rst index 649800f..9890061 100644 --- a/docs/usage/full/query_builder.rst +++ b/docs/usage/full/query_builder.rst @@ -17,10 +17,12 @@ See the :meth:`pysnow.Request.get_all` and :meth:`pysnow.QueryBuilder` documenta end = dt.now() - td(days=20) # Query incident records with number starting with 'INC0123', created between 1970-01-01 and 20 days back in time - qb = (pysnow.QueryBuilder() - .field('number').starts_with('INC0123') - .AND() - .field('sys_created_on').between(start, end)) + qb = ( + pysnow.QueryBuilder() + .field('number').starts_with('INC0123') + .AND() + .field('sys_created_on').between(start, end) + ) r = s.query('incident', query=qb) diff --git a/docs/usage/query.rst b/docs/usage/query.rst index 857f2d1..4a27803 100644 --- a/docs/usage/query.rst +++ b/docs/usage/query.rst @@ -30,18 +30,27 @@ See the :meth:`pysnow.QueryBuilder` documentation for more details. end = dt.now() - td(days=20) # Query incident records with number starting with 'INC0123', created between 1970-01-01 and 20 days back in time - qb = pysnow.QueryBuilder()\ - .field('number').starts_with('INC0123')\ - .AND()\ - .field('sys_created_on').between(start, end) + qb = ( + pysnow.QueryBuilder() + .field('number').starts_with('INC0123') + .AND() + .field('sys_created_on').between(start, end) + ) r = s.query('incident', query=qb) SN Pass-through ^^^^^^^^^^^^^^^ -It's a one-liner. Quite obscure. But hey, it's a one-liner. +The SN pass-through equivalent can get a little obscure. .. code-block:: python + from datetime import datetime as dt + from datetime import timedelta as td + + # Set start and end range + start = dt(1970, 1, 1) + end = dt.now() - td(days=20) + # Query incident records starting with 'INC012' or short_description containing 'test' - r = s.query(table='incident', query='numberSTARTSWITHINC012^ORshort_descriptionLIKEtest') + r = s.query(table='incident', query='numberSTARTSWITHINC0150^sys_created_onBETWEENjavascript:gs.dateGenerate("%s")@javascript:gs.dateGenerate("%s")' % (start, end)) From 1ddc33c8f7c01f92ef41573a103e4d65c56f4e5a Mon Sep 17 00:00:00 2001 From: Robert Wikman Date: Thu, 27 Apr 2017 19:10:34 +0200 Subject: [PATCH 07/10] Fixed QB example indentation --- docs/usage/query.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage/query.rst b/docs/usage/query.rst index 4a27803..87a7422 100644 --- a/docs/usage/query.rst +++ b/docs/usage/query.rst @@ -30,7 +30,7 @@ See the :meth:`pysnow.QueryBuilder` documentation for more details. end = dt.now() - td(days=20) # Query incident records with number starting with 'INC0123', created between 1970-01-01 and 20 days back in time - qb = ( + qb = ( pysnow.QueryBuilder() .field('number').starts_with('INC0123') .AND() From 9e567959f0554e8421ee099395bb91e51953021b Mon Sep 17 00:00:00 2001 From: Robert Wikman Date: Thu, 27 Apr 2017 19:24:09 +0200 Subject: [PATCH 08/10] Updated query examples --- docs/usage/query.rst | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/usage/query.rst b/docs/usage/query.rst index 87a7422..996614a 100644 --- a/docs/usage/query.rst +++ b/docs/usage/query.rst @@ -15,7 +15,8 @@ Simple. And sufficient in many cases. Using the query builder ^^^^^^^^^^^^^^^^^^^^^^^ -Perhaps a bit verbose, but pretty simple and powerful. + +The recommended way to create complex queries. See the :meth:`pysnow.QueryBuilder` documentation for more details. @@ -41,7 +42,12 @@ See the :meth:`pysnow.QueryBuilder` documentation for more details. SN Pass-through ^^^^^^^^^^^^^^^ -The SN pass-through equivalent can get a little obscure. + +It's recommended to use the query builder for complex queries, as it offers a cleaner way to create queries. + +However, you can still use SN pass-through queries should the query builder not satisfy your needs for some reason. + +This is a pass-through equivalent of the QB example above. .. code-block:: python From e054b68d8ebfc3366f1a913f5b68a378bd907fab Mon Sep 17 00:00:00 2001 From: Robert Wikman Date: Thu, 27 Apr 2017 19:24:50 +0200 Subject: [PATCH 09/10] Fixed typo --- docs/usage/query.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage/query.rst b/docs/usage/query.rst index 996614a..ce0333c 100644 --- a/docs/usage/query.rst +++ b/docs/usage/query.rst @@ -58,5 +58,5 @@ This is a pass-through equivalent of the QB example above. start = dt(1970, 1, 1) end = dt.now() - td(days=20) - # Query incident records starting with 'INC012' or short_description containing 'test' + # Query incident records with number starting with 'INC0123', created between 1970-01-01 and 20 days back in time r = s.query(table='incident', query='numberSTARTSWITHINC0150^sys_created_onBETWEENjavascript:gs.dateGenerate("%s")@javascript:gs.dateGenerate("%s")' % (start, end)) From 2a163de75183d61d6c88d7d56372c1426c6af462 Mon Sep 17 00:00:00 2001 From: Robert Wikman Date: Thu, 27 Apr 2017 19:39:58 +0200 Subject: [PATCH 10/10] Fixed QB example indentation --- docs/usage/query.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/usage/query.rst b/docs/usage/query.rst index ce0333c..848c4c4 100644 --- a/docs/usage/query.rst +++ b/docs/usage/query.rst @@ -31,12 +31,12 @@ See the :meth:`pysnow.QueryBuilder` documentation for more details. end = dt.now() - td(days=20) # Query incident records with number starting with 'INC0123', created between 1970-01-01 and 20 days back in time - qb = ( - pysnow.QueryBuilder() - .field('number').starts_with('INC0123') - .AND() - .field('sys_created_on').between(start, end) - ) + qb = ( + pysnow.QueryBuilder() + .field('number').starts_with('INC0123') + .AND() + .field('sys_created_on').between(start, end) + ) r = s.query('incident', query=qb)