I have an order_by clause in an ORM query:
def ordering():
return sqlalchemy.sql.expression.case(
(User.id == current_user_id(), 1),
else_=2
)
...
query = User.query.order_by(ordering)
But when I try to use this, I get this error:
sqlalchemy.exc.InvalidRequestError: Can't invoke Python callable current_user_id() inside of lambda expression argument at <code object user_ordering at 0x7fefae4efd40, file "/web/eta/routes/user.py", line 24>; lambda SQL constructs should not invoke functions from closure variables to produce literal values since the lambda SQL system normally extracts bound values without actually invoking the lambda or any functions within it. Call the function outside of the lambda and assign to a local variable that is used in the lambda as a closure variable, or set track_bound_values=False if the return value of this function is used in some other way other than a SQL bound value.
I really do want the value to be evaluated every time the query is run. So I've tried track_bound_values:
query = User.query.order_by(sqlalchemy.lambda_stmt(ordering, track_bound_values=False))
But this seems to make no difference - I still see the same error. Is there a way of always using the current value of a function in an ordering expression like this?
Or, alternatively, is there a better way of making sure a particular value is always returned first?
Related
I'm looking for a function that will let me execute code passed as a string, but also return a value upon completion. I have found Python's exec and eval, each of which manage to do a part of what I want:
exec lets me execute some lines of code which I pass as a string: print to the console; set or change variables; write to files etc.
eval lets me evaluate a single expression and returns the value of this expression.
However, the functionality I want is to combine these: with a single function call, I want to execute some arbitrary code, and then return a value, which might be dependent on the code executed.
To contextualise, I want to modify the in-built Pickle __reduce__ method so that I can execute some code in the background while the object un-pickles. However, at the end of that code execution, I still want to return the original object that was pickled.
Pickle's __reduce__ has to return a function which is used to reassemble the object on un-pickling, so I want a use of eval and exec that lets me combine their usage into a single function call.
As an example, my code might look something like this:
def __reduce__(self):
code = """with open("flag.txt", "w") as f:\n\tf.write("A flag I have left!")\ndict()"""
return exec, (code, ), None, None, iter(self.items())
The odd return formatting is a quirk of Pickle. The oddly formatted code string should do this:
with open("flag.txt", "w") as f:
f.write("A flag I have left")
dict() # I'm trying to get the intepreter to 'evaluate' this final line
However, this doesn't work, as exec just does nothing with this final line, and returns None. If I swap, and use eval instead, then I get an error too, as eval can't do anything with the lines above.
I ave tried using the in-built compile method, but this doesn't actually seem to help because eval still won't evaluate compiled execution code.
I also see that this problem has popped up elsewhere on SO (here and here) but I'm unsatisfied with the answers provided, because they involve defining new functions, which are then useless in the context of getting Pickle to execute them on un-pickling, where the interpreter is naive of their definition.
Is there any way to neatly combine these expressions to achieve arbitrary execution as well as returning a value?
The best solution I could find to this problem is one based on some code from Yannic Kilcher.
You can combine the functions like this:
eval("exec(exec_code) or to_return")
eval will always try to return the value of the expression you have passed. If you pass a conditional expression, like the one above, then it will try and evaluate each part in turn to find the value of the whole conditional. As such, it will run your exec code, achieving what you need there, and then, finding that it evaluates to None, will return whatever the value of to_return is, because of the or. Therefore, if you make to_return your dictionary object constructor, then your code will run the exec statement first upon un-pickling, and then return a dictionary object as intended.
Please forgive my noob status, but I have come across a construct I don't really understand and hope someone can explain it for me.
class Base(object):
def mogrify(self, column):
return self.mogrifiers.get(column.lower().strip()) or (lambda x: x)
...
class MyClass(some.package.Base):
def mogrifiers(self):
return {
'column1': (lambda x: datetime.datetime.fromtimestamp(int(x)))
}
...
class MyOtherClass(object):
def convert_columns:
...
new_row[colkey] = self.myclass.mogrify(colkey)(value)
This all works, but I'm trying to write a unit test and mock out MyClass.
As far as I can tell, mogrifiers returns a dictionary of all the columns and any transformations that are required.
The code I am testing calls mogrify (inherited from the Base class) with a specific column name in a string.
This tries to extract the column from the dictionary and returns the lambda function ? or if it doesn't exist in the dictionary, it returns a lambda that just gives the string back ?
So that just leaves me with the (value) bit in the code I'm trying to test. It's no clear what it does.
If I don't want to test the underlying conversion/transformation my mock could just return the simple lambda.
So I've done that, but it throws an exception on the call to mogrify saying:
E TypeError: 'str' object is not callable
Can anyone provide some clues what I'm missing here?
As far as I can tell, mogrifiers returns a dictionary of all the
columns and any transformations that are required.
That is correct, though as you've shown it it will create a fresh dictionary each time which seems unnecessary.
The code I am testing calls mogrify (inherited from the Base class)
with a specific column name in a string.
This tries to extract the column from the dictionary and returns the
lambda function ? or if it doesn't exist in the dictionary, it returns
a lambada that just gives the string back ?
Yes, that is also correct (except that a lambada is a dance, but I think you meant lambda again).
So that just leaves me with the (value) bit in the code I'm trying to
test. It's no clear what it does.
The call self.myclass.mogrify(colkey) returns a callable, the (value) simply calls it. It may be clearer if I rewrite like this:
fn = self.myclass.mogrify(colkey)
new_row[colkey] = fn(value)
splitting it into two lines will also make it clearer whether the problem is with the call self.myclass.mogrify(colkey) or fn(value). If as seems likely it is the fn(value) call it means your mocked mogrify is returning a str instead of returning a callable; it could however be that you got the mock wrong and the mocked mogrify method is actually a string.
I would suggest you rewrite as shown and also insert a print between the two lines and see what is actually being returned.
I am trying to construct a dispatch the following way:
def run_nn(type=None):
print type, 'nn'
return
def run_svm(type=None):
print type, 'svm'
return
action = {'nn' : run_nn( type=None),
'svm' : run_svm(type=None),}
I want the function to be executed only when called with something like:
action.get('nn',type='foo')
With expectation it to print:
foo nn
But it breaks giving:
TypeError: get() takes no keyword arguments
What's the right way to do it?
Furthermore, two functions run_nn() and run_svm() were executed without even being called. I don't want that. How can I avoid it?
You're calling the functions while building the dictionary. You should instead put the function objects in the dict without calling them. And afterwards, get the appropriate function from the dict and call it with the keyword argument.
What you want is:
action = {'nn' : run_nn,
'svm' : run_svm,}
...
action.get('nn')(type='foo') # get function object from dict and then call it.
I'll suggest you use action['nn'] over action.get('nn') since you're not specifying any default callable in the get method; the get method returns None when you don't specify one. A KeyError is much more intuitive than a TypeError NoneType object is not callable in this scenario.
On another note, you can drop those return statements as you aren't actually returning anything. Your function will still return without them.
BTW, I have the feeling your function(s) want to change behavior depending on type (although your type is counter-intuitive as it is always a string). In any case, you may have a look at functools.singledispatch. That'll transform your function(s) into a single-dispatch generic function with the possibility to create several overloaded implementations.
Finally, although type does make for a good argument name, you will run into problems when you need to use the builtin type in your function.
Trying to figure out how to set a object attribute using a lambda function.
i got a case where i need to set the attribute with a UI callBack, that requires a function object.
was trying something like this but it dosnt work, and gives me a syntax error.
pm.button(command=lambda *args: uvOpts.grid = True)
this solves the syntax error (you cannot have a second "=" in pm.button) and works if uvOpts is in the scope.
pm.button(command=lambda *args: setattr(uvOpts, 'grid', True))
to set the object's attribute I'm using setattr, in order to avoid the use of a = symbol in lambda function definition.
I would like to add that if you need to make uvOpts visible inside the lambda scope you may eventually need to make it global, at least at module level (e.g. read the answers in Using global variables in a function other than the one that created them).
I have a tuple like the following:
self.tagnames = (('string', self.do_anything()),)
It should execute a specific function if a string matches to another.
However, when I initialize self.tagnames, it seems to execute the function already.
How can I fix my issue without executing the function on startup?
self.tagnames = (('string', self.do_anything),)
The () is a function call. If you want to defer the call until later, and just include the function reference without the parens like so.
self.tagnames = (('string', self.do_anything),)
You invoke a function by using parens with an argument list:
len is a function, len(s) is invoking that function on the argument s. Simply using the function's name gets you the function. Leave off the parenthesized argument list, and you are no longer invoking the function.
You should just remove the parenthesis:
self.tagnames = (('string', self.do_anything),)
Clearly self.do_anything() calls the method immediately, instead self.do_anything returns what in Python is called a "bound method", i.e. it's a callable object to which you can pass just the parameters (if any) and that will result in calling the method on the specific instance.