Trouble with sqlite3 set_authorizer method - python

I'm trying to use the Connection.set_authorizer method to only allow certain DB operations with a connection object. (The documentation is here)
I'm using this code to test:
import sqlite3 as sqlite
def select_authorizer(sqltype, arg1, arg2, dbname):
print("Test")
return sqlite.SQLITE_OK #should allow all operations
conn = sqlite.connect(":memory:")
conn.execute("CREATE TABLE A (name integer PRIMARY KEY AUTOINCREMENT)")
conn.set_authorizer(select_authorizer)
conn.execute("SELECT * FROM A").fetchall() #should still work
This gives me a sqlite3.DatabaseError: not authorized, without ever printing out "Test". I'm guessing I may have set up my authorizer wrong, and it's just failing to even call it. (Though the error message sure doesn't communicate that) But according to the documentation, this setup looks right.
EDIT: Changed sqlite.SQLITE_OKAY to sqlite.SQLITE_OK, but since the method doesn't seem to be called at all, not surprisingly that didn't help.

The authorizer callback takes 5 arguments, but yours only accepts four:
The first argument to the callback signifies what kind of operation is to be authorized. The second and third argument will be arguments or None depending on the first argument. The 4th argument is the name of the database (“main”, “temp”, etc.) if applicable. The 5th argument is the name of the inner-most trigger or view that is responsible for the access attempt or None if this access attempt is directly from input SQL code.
Thus, the signature should be:
def select_authorizer(sqltype, arg1, arg2, dbname, source):
Generally, when testing a callback like that, testing is made easy by using a *args wildcard parameter:
def select_authorizer(*args):
print(args)
return sqlite.SQLITE_OK
The above callback prints out:
(21, None, None, None, None)
(20, 'A', 'name', 'main', None)
when I run your test SELECT.
See the C reference for SQLite set_authorizer and the action codes reference for the various constants used.

Martijn Pieter's answer is correct; I somehow missed that 5th argument when I read that paragraph.
Something I've also found reading through the documentation more closely that would have really helped me figure this out on my own is the line: sqlite.enable_callback_tracebacks(True)
This line will cause sqlite to print a traceback for errors that occur within callback functions.

Related

python dictionary .get() method with default value throws exception even when it should not even be executed

I am having a dictionary that I would like to retrieve some values from using .get() method and if the key is not present, a default function should be executed that returns the correct value but it should only be executed if the key is not present.
I tried removing the default value and it works, so why does the function gets executed even if it won't be used?
The SQL query will return nothing because it only contains values not already in the dict
def get_port():
def default():
cursor.execute("SELECT port FROM table WHERE server=%s LIMIT 1",(server_name,))
return cursor.fetchone()[0]
port = {
'server1': 2222,
'server2': 2223,
'server3': 2224
}
#print(port.get(server_name)) << Works
return port.get(server_name, default())
Error:
return cursor.fetchone()[0] TypeError: 'NoneType' object is not
subscriptable
I expect the default function to only execute if key is not present..
the issue with get with a default value which needs build/evaluation is that the code is executed, even if not needed, which can slow down the code, or in your case trigger unnecessary errors.
An alternative could be:
port.get(server_name) or default()
If get returns None because a key is not found, then or default() is activated. But if get returns something, it short-circuits and default() is not called.
(this could fail if get returned empty string, zero, any "falsy" value but in your case - a server name - I'll suppose that it cannot happen)
Another option (maybe overkill here) would be to use a collections.defaultdict object
port = collections.defaultdict(default)
port.update({
'server1': 2222,
'server2': 2223,
'server3': 2224
})
Then each call to port[server] with an unknown key calls the default function and stores the result in the dictionary. Make port global or persistent and you have a created nice cache: next time the same value is fetched the default is already in the dictionary.
You're calling the function, so it does get executed (default() vs. default). (Even if you didn't call it, i.e. .get(..., default), you'd then just get the function object back, which doesn't suit your purposes.)
If you only want to call it when the key does not exist, you need to be slightly more verbose – and at that point, it's worth refactoring like so:
ports = {
"server1": 2222,
"server2": 2223,
"server3": 2224,
}
def get_port(server_name):
port = ports.get(server_name)
if not port:
cursor.execute(
"SELECT port FROM table WHERE server=%s LIMIT 1",
(server_name,),
)
port = cursor.fetchone()[0]
return port
The previous answer will bring the solution to your current problem/question.
default() is being evaluated at first.
I want to include some more info to help you understand what is happening. The question may look naive, but it touches fundamental aspects of Python (and any programming language actually). Hopefully, that will have some interest to some readers.
The first misunderstood aspect is related to eager evaluation. Python is an eager evaluator. Here is a nice post around the topic.
Then, read about the get() method itself -- it returns a value, which may be a function since functions are first class objects in Python.

Python ast - getting function parameters and processing them

I'm trying to use the ast module in Python to parse input code, but am struggling with a lot of the syntax of how to do so. For instance, I have the following code as a testing environment:
import ast
class NodeVisitor(ast.NodeVisitor):
def visit_Call(self, node):
for each in node.args:
print(ast.literal_eval(each))
self.generic_visit(node)
line = "circuit = QubitCircuit(3, True)"
tree = ast.parse(line)
print("VISITOR")
visitor = NodeVisitor()
visitor.visit(tree)
Output:
VISITOR
3
True
In this instance, and please correct me if I'm wrong, the visit_Call will be used if it's a function call? So I can get each argument, however there's no guarantee it will work like this as there are different arguments available to be provided. I understand that node.args is providing my arguments, but I'm not sure how to do things with them?
I guess what I'm asking is how do I check what the arguments are and do different things with them? I'd like to check, perhaps, that the first argument is an Int, and if so, run processInt(parameter) as an example.
The value each in your loop in the method will be assigned to the AST node for each of the arguments in each function call you visit. There are lots of different types of AST nodes, so by checking which kind you have, you may be able to learn things about the argument being passed in.
Note however that the AST is about syntax, not values. So if the function call was foo(bar), it's just going to tell you that the argument is a variable named bar, not what the value of that variable is (which it does not know). If the function call was foo(bar(baz)), it's going to show you that the argument is another function call. If you only need to handle calls with literals as their arguments, then you're probably going to be OK, you'll just look instances of AST.Num and similar.
If you want to check if the first argument is a number and process it if it is, you can do something like:
def visit_Call(self, node):
first_arg = node.args[0]
if isinstance(first_arg, ast.Num):
processInt(first_arg.n)
else:
pass # Do you want to do something on a bad argument? Raise an exception maybe?

Python: Need the result of functools.partial(function) to be known as something else

My software supports python to automate tasks (Maya). When I undo or redo in this software it prints the last command, unfortunately for Python this is the memory address of the function rather than something actually useful. So the user sees the output Undo: <functools.partial object at 0x000002235DEDDF48> instead of something actually useful like Undo: Set Key on something at frame x
There appears to be no option to make Maya print a useful result from within it's own functionality, so now I want to ask if there's some obscure way cheese it with python to have that instance call itself something useful in a way the software will print while hopefully not interfering with the functionality. I'll try anything at this point!
def testFunc():
pass
test = partial(testFunc)
test results in <functools.partial object at 0x000002235DEA95E8>
If anyone can think of a more accurate title please edit / suggest.
Thanks to kindall giving me a lead in the comments I was able to find an answer. Subclassing partial and defining __repr__() is the key.
By grabbing the *args on __init__() and storing it as self.result we can use it on __repr__() to return the last argument given to *args as the result given by Maya when using Undo/Redo.
class rpartial(partial):
def __init__(self, *args):
self.result = args[-1]
def __repr__(self):
return self.result
rpartial(function, arg1, arg2, undoredo)
The string given to rpartial on the last line for undoredo is what will be printed by Maya when using Undo/Redo.

Callback to method in Python

I'm just starting to learn Python and I have the following problem.
Using a package with method "bind", the following code works:
def callback(data):
print data
channel.bind(callback)
but when I try to wrap this inside a class:
class myclass:
def callback(data):
print data
def register_callback:
channel.bind(self.callback)
the call_back method is never called. I tried both "self.callback" and just "callback". Any ideas?
It is not clear to me how your code works, as (1) you did not post the implementation of channel.bind, and (2) your second example is incorrect in the definition of register_callback (it is using a self argument that is not part of the list of parameters of the method, and it lacks parentheses).
Nevertheless, remember that methods usually require a "self" parameter, which is implicitly passed every time you run self.function(), as this is converted internally to a function call with self as its first parameter: function(self, ...). Since your callback has just one argument data, this is probably the problem.
You cannot declare a method bind that is able to accept either a function or a class method (the same problem happens with every OOP language I know: C++, Pascal...).
There are many ways to do this, but, again, without a self-contained example that can be compiled, it is difficult to give suggestions.
You need to pass the self object as well:
def register_callback(self):
channel.bind(self.callback)
What you're doing is entirely possible, but I'm not sure exactly what your issue is, because your sample code as posted is not even syntactically valid. (The second method has no argument list whatsoever.)
Regardless, you might find the following sample code helpful:
def send_data(callback):
callback('my_data')
def callback(data):
print 'Free function callback called with data:', data
# The follwing prints "Free function callback called with data: my_data"
send_data(callback)
class ClassWithCallback(object):
def callback(self, data):
print 'Object method callback called with data:', data
def apply_callback(self):
send_data(self.callback)
# The following prints "Object method callback called with data: my_data"
ClassWithCallback().apply_callback()
# Indeed, the following does the same
send_data(ClassWithCallback().callback)
In Python it is possible to use free functions (callback in the example above) or bound methods (self.callback in the example above) in more or less the same situations, at least for simple tasks like the one you've outlined.

How do I retain the method attributes of the functions generated through yield in python 2.7?

I have been doing a lot of searching, and I don't think I've really found what I have been looking for. I will try my best to explain what I am trying to do, and hopefully there is a simple solution, and I'll be glad to have learned something new.
This is ultimately what I am trying to accomplish: Using nosetests, decorate some test cases using the attribute selector plugin, then execute test cases that match a criteria by using the -a switch during commandline invocation. The attribute values for the tests that are executed are then stored in an external location. The command line call I'm using is like below:
nosetests \testpath\ -a attribute='someValue'
I have also created a customized nosetest plugin, which stores the test cases' attributse, and writes them to an external location. The idea is that I can select a batch of tests, and by storing the attributes of these tests, I can do filtering on these results later for reporting purposes. I am accessing the method attributes in my plugin by overriding the "wantMethod" method with the code similar to the following:
def set_attribs(self, method, attribute):
if hasattr(method, attribute):
if not self.method_attributes.has_key(method.__name__):
self.method_attributes[method.__name__] = {}
self.method_attributes[method.__name__][attribute] = getattr(method, attribute)
def wantMethod(self, method):
self.set_attribs(method, "attribute1")
self.set_attribs(method, "attribute2")
pass
I have this working for pretty much all the tests, except for one case, where the test is uing the "yield" keyword. What is happening is that the methods that are generated are being executed fine, but then the method attributes are empty for each of the generated functions.
Below is the example of what I am trying to achieve. The test below retreives a list of values, and for each of those values, yields the results from another function:
#attr(attribute1='someValue', attribute2='anotherValue')
def sample_test_generator(self):
for (key, value) in _input_dictionary.items()
f = partial(self._do_test, key, value)
f.attribute1='someValue'
yield (lambda x: f(), key)
def _do_test(self, input1, input2):
# Some code
From what I have read, and think I understand, when yield is called, it would create a new callable function which then gets executed. I have been trying to figure out how to retain the attribute values from my sample_test_generator method, but I have not been successful. I thought I could create a partial method, and then add the attribute to the method, but no luck. The tests execute without errors at all, it just seems that from my plugin's perspective, the method attributes aren't present, so they don't get recorded.
I realize this a pretty involved question, but I wanted to make sure that the context for what I am trying to achieve is clear. I have been trying to find information that could help me for this particular case, but I feel like I've reached a stumbling block now, so I would really like to ask the experts for some advice.
Thanks.
** Update **
After reading through the feedback and playing around some more, it looks like if I modified the lambda expression, it would achieve what I am looking for. In fact, I didn't even need to create the partial function:
def sample_test_generator(self):
for (key, value) in _input_dictionary.items()
yield (lambda: self._do_test)
The only downside to this approach is that the test name will not change. As I am playing around more, it looks like in nosetests, when a test generator is used, it would actually change the test name in the result based on the keywords it contains. Same thing was happening when I was using the lambda expression with a parameter.
For example:
Using lamdba expression with a parameter:
yield (lambda x: self._do_test, "value1")
In nosetests plugin, when you access the test case name, it would be displayed as "sample_test_generator(value1)
Using lambda expression without a parameter:
yield (lambda: self._do_test)
The test case name in this case would be "sample_test_generator". In my example above, if there are multiple values in the dictionary, then the yield call would occur multiple times. However, the test name would always remain as "sample_test_generator". This is not as bad as when I would get the unique test names, but then not be able to store the attribute values at all. I will keep playing around, but thanks for the feedback so far!
EDIT
I forgot to come back and provide my final update on how I was able to get this to work in the end, there was a little confusion on my part at first, and after I looked through it some more, I figured out that it had to do with how the tests are recognized:
My original implementation assumed that every test that gets picked up for execution goes through the "wantMethod" call from the plugin's base class. This is not true when "yield" is used to generate the test, because at this point, the test method has already passed the "wantMethod" call.
However, once the test case is generated through the "yeild" call, it does go through the "startTest" call from the plug-in base class, and this is where I was finally able to store the attribute successfully.
So in a nut shell, my test execution order looked like this:
nose -> wantMethod(method_name) -> yield -> startTest(yielded_test_name)
In my override of the startTest method, I have the following:
def startTest(self, test):
# If a test is spawned by using the 'yield' keyword, the test names would be the parent test name, appended by the '(' character
# example: If the parent test is "smoke_test", the generated test from yield would be "smoke_test('input')
parent_test_name = test_name.split('(')[0]
if self.method_attributes.has_key(test_name):
self._test_attrib = self.method_attributes[test_name]
elif self.method_attributes.has_key(parent_test_name):
self._test_attrib = self.method_attributes[parent_test_name]
else:
self._test_attrib = None
With this implementation, along with my overide of wantMethod, each test spawned by the parent test case also inherits attributes from the parent method, which is what I needed.
Again, thanks to all who send replies. This was quite a learning experience.
Would this fix your name issue?
def _actual_test(x, y):
assert x == y
def test_yield():
_actual_test.description = "test_yield_%s_%s" % (5, 5)
yield _actual_test, 5, 5
_actual_test.description = "test_yield_%s_%s" % (4, 8) # fail
yield _actual_test, 4, 8
_actual_test.description = "test_yield_%s_%s" % (2, 2)
yield _actual_test, 2, 2
Rename survives #attr too.
does this work?
#attr(attribute1='someValue', attribute2='anotherValue')
def sample_test_generator(self):
def get_f(f, key):
return lambda x: f(), key
for (key, value) in _input_dictionary.items()
f = partial(self._do_test, key, value)
f.attribute1='someValue'
yield get_f(f, key)
def _do_test(self, input1, input2):
# Some code
The Problem ist that the local variables change after you created the lambda.

Categories

Resources