Question

I am trying to rewrite my lib written in PHP into python. It handles all sphinx requests. In the init function, I am trying to set default search and match modes, but I have run into a little problem. I get the modes from a config file.

In PHP, you need to use a constant as an input:

$this->sphinx->SetMatchMode(constant($this->conf['match_mode']));

This will convert the string from config file into a constant and everything works. The tricky part starts in python, when I try to do this:

self.sphinx.SetMatchMode(self.config['match_mode'])

I get:

AssertionError in
assert(mode in [SPH_MATCH_ALL, SPH_MATCH_ANY, SPH_MATCH_PHRASE, SPH_MATCH_BOOLEAN, SPH_MATCH_EXTENDED, SPH_MATCH_FULLSCAN, SPH_MATCH_EXTENDED2]) 

In this case, the input should be an integer, but the input is a string and I cant convert it because I get an exception - the string is SPH_MATCH_ALL.

invalid literal for int() with base 10: 'SPH_MATCH_ALL'

When I try this:

print type(self.config['match_mode']) # -- string
print type(SPH_MATCH_ALL) # -- integer
print SPH_MATCH_ALL # -- 1 
print SPH_MATCH_ANY # -- 0

So my question would be, how can I convert the string into an integer or whatever it thinks it is, so I wont get an assertion error. Of course, that I could just do some if/else statements, but I dont want that. Is there any elegant way to do this?

Was it helpful?

Solution

Python doesn't have a direct equivalent of the PHP constant() function. If the constant in question is imported from a module, the cleanest way to do it is like this:

import myconstants
num = int(getattr(myconstants, self.config['match_mode']))

Or if it's defined at global scope within the current module, you can do this:

X = 1
num = int(globals()['X'])

Either way, you're doing something slightly risky by letting the user control which objects your code deals with. It's not quite eval(), but it's a little way down that road. That's why I've included the int() conversions there - they should fail if the user configures the system with the name of something that isn't an integer. There may be more robust ways to do this - I'm not quite comfortable with it, but it's somewhere close to your PHP constant() code without a complete rewrite.

OTHER TIPS

I'm not familiar with sphinx, but based on you question, I would try something like this

DEFAULT = 0
mode = getattr(self.sphinx, self.config['match_mode'], DEFAULT)
self.sphinx.SetMatchMode(mode)

That's assuming that the sphinx module defines the modes in the form

SPH_MATCH_ANY = 0
SPH_MATCH_ALL = 1
# ....

Write a function that converts the mode string to the corresponding integer, then use that when you call in the config:

self.sphinx.SetMatchMode(modeToInt(self.config['match_mode']))

You can hive away whatever if/else ugliness is required into the function.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top