Python Regular Expression TypeError - python

I am writing my first python program and I am running into a problem with regex. I am using regular expression to search for a specific value in a registry key.
import _winreg
import re
key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{26A24AE4-039D-4CA4-87B4-2F83216020FF}")
results=[]
v = re.compile(r"(?i)Java")
try:
i = 0
while 1:
name, value, type = _winreg.EnumValue(key, i)
if v.search(value):
results.append((name,value,type))
i += 1
except WindowsError:
print
for x in results:
print "%-50s%-80s%-20s" % x
I am getting the following error:
exceptions.TypeError: expected string
or buffer
I can use the "name" variable and my regex works fine. For example if I make the following changes regex doesn't complain:
v = re.compile(r"(?i)DisplayName")
if v.search(name):
Thanks for any help.

The documentation for EnumValue explains that the 3-tuple returned is a string, an object that can be any of the Value Types, then an integer. As the error explained, you must pass in a string or a buffer, so that's why v.search(value) fails.
You should be able to get away with v.search(str(value)) to convert value to a string.

Related

TypeError when calling dict.keys in python

I have some code, in Python which (if it would work) should replace data in a string using a dictionary to do the replacement. eg. key would be the thing that gets replaced, and value would be the replaced data.
Code
def replace(data=str, options=dict):
for i in range(options.keys()):
data = data.replace(options.keys()[i], options.get(options.keys()[i]))
return data
However, when I call this function, it gives me this error, I have looked online and have found no way of fixing it.
for i in range(options.keys()):
TypeError: 'dict_keys' object cannot be interpreted as an integer
How I call this function:
test = {
"a":"b",
"c":"d"
}
replace("abcd", test)
def replace(data=str, options=dict):
for k, v in options.items():
data = data.replace(k, v)
return data

How to automatically determine type for user input?

I want to make a simple math function that takes user input, yet allows the user to not input an integer/float. I quickly learned Python does not identify type by default. Quick Google search shows using literal_eval, but it returns with ValueError: malformed string if a string is the input. This is what I have so far:
from ast import literal_eval
def distance_from_zero(x):
if type(x) == int or type(x) == float:
return abs(x)
else:
return "Not possible"
x = literal_eval(raw_input("Please try to enter a number "))
print distance_from_zero(x)
Just answer your query why ValueError: malformed string occurred if you read the literal_eval doc :
Safely evaluate an expression node or a string containing a Python
expression. The string or node provided may only consist of the
following Python literal structures: strings, numbers, tuples, lists,
dicts, booleans, and None.
so string should be inclosed by "" as used to write in editor like s = "string"
raw_input takes the input and convert to string data type so i have tried this and able to convert using literal_eval
>>> x=raw_input()
string
>>> x= "\""+x+"\"" # concatenating the "" to string
>>> literal_eval(x)
'string'
>>>
Like you mentioned you will get malformed string error (ValueError) if you get input like ast.literal_eval('c1'). You will also get SyntaxError if you do something like ast.literal_eval('1c'). You will want get the input data and then pass it to literal_eval. You can then catch both of these exceptions, and then return your 'Not Possible'.
from ast import literal_eval
def distance_from_zero(x):
try:
return abs(literal_eval(x))
except (SyntaxError, ValueError):
return 'Not possible'
x = raw_input("Please try to enter a number ")
print distance_from_zero(x)

Python how to shorten a uuuid and decode?

I'm trying to create a shortened ID for one of my models using the following method:
_char_map = string.ascii_letters+string.digits
def index_to_char(sequence):
return "".join([_char_map[x] for x in sequence])
def make_short_id(self):
_id = self.id
digits = []
while _id > 0:
rem = _id % 62
digits.append(rem)
_id /= 62
digits.reverse()
return index_to_char(digits)
#staticmethod
def decode_id(string):
i = 0
for c in string:
i = i * 64 + _char_map.index(c)
return i
Where self.id is a uuid i.e. 1c7a2bc6-ca2d-47ab-9808-1820241cf4d4, but I get the following error:
rem = _id % 62
TypeError: not all arguments converted during string formatting
This method only seems to work when the id is an int.
How can I modify the method to shorten a uuuid and decode?
UPDATE:
Thank you for the help. I was trying to find a way create an encode and decode method that took a string, made it shorter then decode it back again. The methods above can never work with a string (uuid) as pointed out,
The % operator is the string formatting or interpolation operator and does not return the remainder in Python when used with strings. It will try to return a formatted string instead.
I'm not sure what your input is, but try converting it using int so you can get the remainder of it.
Edit: I see your input now, not sure why I missed it. Here's one method of converting a UUID to a number:
import uuid
input = "1c7a2bc6-ca2d-47ab-9808-1820241cf4d4"
id = uuid.UUID(input)
id.int
# returns 37852731992078740357317306657835644116L
Not sure what you mean by "shorten", but it looks like you are trying to "base 62 encode" the UUID. If you use the function from this question you will end up with the following:
uuid62 = base62_encode(id.int)
# uuid62 contains 'RJChvUCPWDvJ7BdQKOw7i'
To get the original UUID back:
# Create a UUID again
id = uuid.UUID(int=base62_decode(uuid62))
id.hex
# returns '1c7a2bc6ca2d47ab98081820241cf4d4'
str(id)
# returns '1c7a2bc6-ca2d-47ab-9808-1820241cf4d4'
_id is string
>>> 11 % 2
1
>>> "11" % 2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: not all arguments converted during string formatting
I would suggest using base64.urlsafe_b64encode() from the standard library, rather than rolling your own base62_encode() function.
You first need to convert your hex string to a binary string:
binary_id = id.replace("-", "").decode("hex")
This binary string can the be encoded using the afore-mentioned function:
shortened_id = base64.urlsafe_b64encode(binary_id)

How to get the value of the last assigned variable in iPython?

I am a total iPython newbie, but I was wondering if there is a way to get the value of the last assigned variable:
In [1]: long_variable_name = 333
In [2]: <some command/shortcut that returns 333>
In R we have .Last.value:
> long_variable_name = 333
> .Last.value
[1] 333
There's a shortcut for the last returned object, _.
In [1]: 1 + 3
Out[1]: 4
In [2]: _
Out[2]: 4
You can use IPython's In and Out variables which contain the commands/statements entered and the the corresponding output (if any) of those statements.
So, a naive approach would be to use those variables as the basis of defining a %last magic method.
However, since not all statements necessarily generate output, In and Out are not synchronous.
So, the approach I came up with was to parse In, and look for the occurrences of = and parse those lines for the output:
def last_assignment_value(self, parameter_s=''):
ops = set('()')
has_assign = [i for i,inpt in enumerate(In) if '=' in inpt] #find all line indices that have `=`
has_assign.sort(reverse=True) #reverse sort, because the most recent assign will be at the end
for idx in has_assign:
inpt_line_tokens = [token for token in In[idx].split(' ') if token.strip() != ''] #
indices = [inpt_line_tokens.index(token) for token in inpt_line_tokens if '=' in token and not any((c in ops) for c in token)]
#Since assignment is an operator that occurs in the middle of two terms
#a valid assignment occurs at index 1 (the 2nd term)
if 1 in indices:
return ' '.join(inpt_line_tokens[2:]) #this simply returns on the first match with the above criteria
And, lastly to make that your own custom command in IPython:
get_ipython().define_magic('last', last_assignment_value)
And, now you can call:
%last
And this will output the term assigned as a string (which may not be what you want).
However, there is a caveat to this: in that if you had entered incorrect input that involved assignment; e.g.: (a = 2), this method will pick it up. And, if your assignment involved variables: e.g. a = name, this method will return name and the not the value of name.
Given that limitation, you can then use the parser module to try and evaluate the expression like this (which can be appended to last_assignment_value in the last if statement):
import parser
def eval_expression(src):
try:
st = parser.expr(src)
code = st.compile('obj.py')
return eval(code)
except SyntaxError:
print 'Warning: there is a Syntax Error with the RHS of the last assignment! "%s"' % src
return None
However, given the possible evils of eval, I've left that inclusion up to you.
But, to be perfectly honest, a truly wholesome method would involve a parsing of the statement to verify the validity of the found input, as well as the input before it and more.
REFERENCES:
https://gist.github.com/fperez/2396341

Python 3.3 binary to hex function

def bintohex(path):
hexvalue = []
file = open(path,'rb')
while True:
buffhex = pkmfile.read(16)
bufflen = len(buffhex)
if bufflen == 0: break
for i in range(bufflen):
hexvalue.append("%02X" % (ord(buffhex[i])))
I am making a function that will return a list of hex values of a specific file. However, this function doesn't work properly in Python 3.3. How should I modify this code?
File "D:\pkmfile_web\pkmtohex.py", line 12, in bintohex hexvalue.append("%02X" % (ord(buffhex[i]))) TypeError: ord() expected string of length 1, but int found
There's a module for that :-)
>>> import binascii
>>> binascii.hexlify(b'abc')
'616263'
In Python 3, indexing a bytes object returns the integer value; there is no need to call ord:
hexvalue.append("%02X" % buffhex[i])
Additionally, there is no need to be manually looping over the indices. Just loop over the bytes object. I've also modified it to use format rather than %:
buffhex = pkmfile.read(16)
if not buffhex:
for byte in buffhex:
hexvalue.append(format(byte, '02X'))
You may want to even make bintohex a generator. To do that, you could start yielding values:
yield format(byte, '02X')

Categories