MattParr / python-atws

Autotask Web Services python module
MIT License
32 stars 10 forks source link

query generator support for Python3 #72

Closed dahifi closed 4 years ago

dahifi commented 4 years ago

From the docs under Query Result Cursor:

# process them like a generator
ticket = ticket.next()

(I presume this is a typo, and is supposed to be tickets.next())

Using the following:

def active_products(): 
    """ Returns atws.wrapper.QueryCursor """ 
    query = atws.Query('Product')
    query.WHERE('Active', query.Equals, True)
    return at.query(query)

products = active_products()
product.next()
>> AttributeError: 'generator' object has no attribute 'next'

Python3 generators do not have 'next', and instead rely on the __next__ attribute. We should be able to call next(ticket), but this fails with TypeError: 'QueryCursor' object is not an iterator.

Calling tickets.__next__() works, as does next(iter(tickets), so I can return a generator using:

def active_products(): 
    """ Returns generator """ 
    query = atws.Query('Product')
    query.WHERE('Active', query.Equals, True)
    return iter(at.query(query))

I can submit a PR to update the docs unless you have other thoughts.

MattParr commented 4 years ago

I believe some small adjustments to the QueryCursor object will fix this. I've made this commit 2530d48 to a branch and I have a test that is passing which indicates this should resolve the usage issues. my test looks like this. does that work for you?

class TestIntegratedQueryCursorFeatures(ConnectedTest):
    def test_011_next_method(self):
        complete = self.api.picklist['Ticket']['Status']['Complete']
        query = atws.Query('Ticket')
        query.WHERE('Status', query.Equals, complete)
        tickets = self.api.query(query)
        ticket = tickets.next()
        self.assertEqual(ticket.Status, complete, 'It may not be related to '
                         'the query cursor next failing if this does not pass '
                         'as it could be the lookup values')

        ticket2 = next(tickets)
        self.assertEqual(ticket2.Status, complete, 'It is unlikely related to '
                         'the query cursor next failing if this does not pass '
                         'as the failure will probably be an exception on the '
                         'next call')

        i=0
        for ticket in tickets:
            i+=1
            self.assertEqual(ticket.Status, complete)
            if i>2:
                break
dahifi commented 4 years ago

TBH Matt, it's been a few weeks since I ran my library, but I appreciate you keeping up with it. It's obvious that the organization that I work for is not forward-thinking enough so I'm anticipating a career-change in May after I finish my degree. Keep up the good work!