1

I have built a CRUD API for working with a database. The Retrieve(or Read) function for the table class, assessment_results is currently giving me issues. Background regarding the design: the API also has a convenience file that inherits from the main file (object.py) for purposes of accepting string values.

What it needs to do: check for an ID and/or check for two arguments (should the ID not be in use). If one or the other(s) if appropriate, retrieve it along with its particulars. Following the docs on Python, I introduced the argument * to allow optional position arguments. I also had helped from this great tutorial. (I am a newbie at designing and building dbs and using python.)

I believe the retrieve method is working, but there must be a flaw in the design or the method for create_category_rating(...) as the Traceback is returning now a ValueError. I read here on Stacks (a similar issue) that I might need to assign a value to args, but it seems like I am through the API.

Code as Follows:

object.py

(retrieve method and create_category_rating method):

def retrieve_assessment_results(self, something_unique, *args):
    if isinstance(something_unique, int):
        return self.session.query(Assessment_Results).\
        filter(Assessment_Results.id == something_unique).one()
    elif isinstance(something_unique, basestring) and isinstance(args, basestring):
        return self.session.query(Assessment_Results).\
        filter(Assessment_Results.owner == something_unique).\
        filter(Assessment_Results.assessment == args).one()
    elif isinstance(something_unique, Assessment_Results) and isinstance(args, Assessment_Results):
        return something_unique, args
    else:
        raise ValueError('Value being passed is an object')

def create_category_rating(self, category_rating_int, category, assessment_results):
    new_catrating = Category_Rating(category_rating_int, category, assessment_results)
    self.session.add(new_catrating)
    print(new_catrating)
    self.session.commit()
    return(new_catrating)

convenience.py (inherits from object.py)

def create_category_rating(self, category_rating_int, category_name, username, name):
    category = self.retrieve_category(category_name)
    owner = self.retrieve_user(username)  
    assessment = self.retrieve_assessment(name)  
    assessment_results = self.retrieve_assessment_results(owner, assessment)
    return super(ConvenienceAPI, self).create_category_rating(category_rating_int, category, assessment_results)

test.py

api = ConvenienceAPI()
api.create_category_rating(2, 'Decision-Making', 'baseball', 'Becoming a Leader')


Current Issue: StatementError As per suggested, changed conditionals (needed to unpack and assign the tuple given by *args).

New API:

def retrieve_assessment_results(self, *args):
    id, assessment, owner = None, None, None
    if len(args) == 1:
        id, = args[0]
    elif len(args) == 2:
        assessment, owner = args
    else:
        raise ValueError('Value being passed is an object')
    if id is not None:
        return self.session.query(Assessment_Results).\
        filter(Assessment_Results.id == id).one()
    elif assessment is not None:
        return self.session.query(Assessment_Results).\
        filter(Assessment_Results.assessment == assessment).one()
    elif owner is not None:
        return self.session.query(Assessment_Results).\
        filter(Assessment_Results.owner == owner).one()

TRACEBACK:

Traceback (most recent call last):
  File "/usr/local/lib/python2.7/site-packages/nose/case.py", line 197, in runTest
    self.test(*self.arg)
  File "/Users/ack/code/venv/NotssDB/notssdb/test/test.py", line 111, in test1
    api.create_category_rating(2, 'Decision-Making', 'baseball', 'Becoming a Leader')
  File "/Users/ack/code/venv/NotssDB/notssdb/api/convenience.py", line 41, in create_category_rating
    assessment_results = self.retrieve_assessment_results(owner, assessment)
  File "/Users/ack/code/venv/NotssDB/notssdb/api/object.py", line 323, in retrieve_assessment_results
    filter(Assessment_Results.assessment == assessment).one()
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 2472, in one
    ret = list(self)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 2515, in __iter__
    return self._execute_and_instances(context)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 2530, in _execute_and_instances
    result = conn.execute(querycontext.statement, self._params)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 914, in execute
    return meth(self, multiparams, params)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/sql/elements.py", line 323, in _execute_on_connection
    return connection._execute_clauseelement(self, multiparams, params)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1010, in _execute_clauseelement
    compiled_sql, distilled_params
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1078, in _execute_context
    None, None)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1339, in _handle_dbapi_exception
    exc_info
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/util/compat.py", line 199, in raise_from_cause
    reraise(type(exception), exception, tb=exc_tb)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1073, in _execute_context
    context = constructor(dialect, self, conn, *args)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/engine/default.py", line 544, in _init_compiled
    grp, m in enumerate(parameters)]
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/sql/compiler.py", line 498, in construct_params
    pd[self.bind_names[bindparam]] = bindparam.effective_value
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/sql/elements.py", line 1162, in effective_value
    return self.callable()
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/relationships.py", line 1386, in _go
    value = fn(*arg, **kw)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/mapper.py", line 2422, in _get_state_attr_by_column
    return state.manager[prop.key].impl.get(state, dict_, passive=passive)
StatementError: (exceptions.KeyError) 'assessment_id' [SQL: u'SELECT assessment_results.id AS assessment_results_id, assessment_results.created_on AS assessment_results_created_on, assessment_results.owner_id AS assessment_results_owner_id, assessment_results.assessment_id AS assessment_results_assessment_id \nFROM assessment_results \nWHERE ? = assessment_results.assessment_id'] [parameters: [immutabledict({})]]
Community
  • 1
  • 1
thesayhey
  • 938
  • 3
  • 17
  • 38
  • I don't see why you think this has anything to do with `args`. You have told your function to raise that error explicitly if it doesn't recognise what `something_unique` is. Since that value in turn comes from `retrieve_user`, you're going to at least need to post that method. – Daniel Roseman Sep 30 '15 at 20:41
  • No, the traceback you have posted clearly shows that the error is happening inside `retrieve_assessment`, so I don't understand how you can say it is working properly. That is the code you should be posting, sorry. – Daniel Roseman Sep 30 '15 at 20:49
  • So ... what is it complaining about? Insert print statements at the top of retrieve_assessment to see the arguments passed in. Trace the if conditions similarly. That much **should** show the error. – Prune Sep 30 '15 at 20:50
  • @Prune sorry... wrong traceback was added on top... see above now – thesayhey Sep 30 '15 at 20:54
  • I think my comment still applies -- but to a different method now. **You** own the code that's throwing the error, so you have phenomenal cosmic powers to diagnose the problem. "print" is a blunt instrument, but it helps when inserted appropriately. – Prune Sep 30 '15 at 20:57
  • I printed, magic that came forward: ```Decision-Making baseball Becoming a Leader Becoming a Leader``` – thesayhey Sep 30 '15 at 20:58
  • 1
    ... and the critical information: what are the types? I'm looking for something like /// print type(something_unique) ... for a in args print type(a) /// You could also do an explicit check for basestring, with /// print type(a), isinstance(a, basestring) /// – Prune Sep 30 '15 at 21:02
  • @Prune the print out (thank you for the suggestion! I will use it in the future for debugging): ```Decision-Making baseball Becoming a Leader Becoming a Leader False``` – thesayhey Sep 30 '15 at 21:07
  • ... and what happens when you extend those checks to the other conditions in your if ... elif series? – Prune Sep 30 '15 at 21:13
  • same traceback even after I tried your suggestion. – thesayhey Sep 30 '15 at 21:14
  • If you are trying all my suggestions, you'll have more output to post for us. Trace the arguments and their types, check the individual isinstance calls, and make sure that you properly loop through all the args in sequence. If that doesn't work, please post the new output, including all of those traces. You might stick an identifying string in each print, so it's easy to tell which is which. I often used lines such as /// print "CHECK A", type(...) /// continuing with CHECK B, etc. – Prune Sep 30 '15 at 21:17
  • @Prune new output above – thesayhey Sep 30 '15 at 21:55
  • From the lack of exception message, I take it that (1) you altered the 'if' conditions to check each individual arg, rather than the tuple, and (2) it worked. Is that the correct status now? – Prune Sep 30 '15 at 22:03
  • @Prune same error, I introduced the answer you suggested below. I will add exactly what I did above. – thesayhey Sep 30 '15 at 22:08
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/91121/discussion-between-prune-and-thesayhey). – Prune Oct 01 '15 at 16:52

1 Answers1

0

I think I may have spotted the problem:

elif isinstance(something_unique, basestring) and isinstance(args, basestring):

"args" is not a basestring: you need to check each individual argument to see whether it's a basestring.

... and reduce(lambda x, y: x and isinstance(y, basestring), [a for a in args], True)
Prune
  • 76,765
  • 14
  • 60
  • 81