Automatically refactor string concatenation to string substitution? - python

I'm faced with a really ugly code that is a code generator, that takes a configuration file and outputs C code.
It works, but the script is full of things like:
outstr = "if(" + mytype + " == " + otherType + "){\n"
outstr += " call_" + fun_for_type(mytype) + "();\n"
outstr += "}\n"
# Now imagine 1000 times more lines like the previous ones...
Is there a tool to automatically change code like that to something more palatable (partial changes are more than welcome)? Like:
outstr = """if ({type} == {otherType}) {
call_{fun_for_type}({type});
}
""".format(type=mytype, otherType=otherType, fun_for_type=(mytype))
If this would have been C then I would have abused of Coccinelle, but I don't know of similar tools for Python.
Thanks

You can use dictionaries :
datas = {"type":mytype, "otherType":otherType, "fun_for_type":(mytype)}
outstr = "if ({type} == {otherType}) {{\n\
call_{fun_for_type}({type});\n\
}}\n".format(**datas)

Related

problem while creating a filepath using variables

I want to create a filepath using a variable i want to do it like this
import os
import gettitle as gt
def convert_file(
oldfilelocation = 'C:/Muziek' + (gt.finalyoutubetitle) + '.m4a'
newfilefilelocation = 'C:/Muziek' + (gt.finalyoutubetitle) + '.mmp3'
os.rename(r(oldfilelocation),r(newfilelocation))
)
exit()
But if i do this is get a lot of errors shown below.
The correct syntax is
2 method parameters oldfilelocation and newfilelocation, with default value
1 statement
def convert_file(oldfilelocation='C:/Muziek' + (gt.finalyoutubetitle) + '.m4a',
newfilelocation='C:/Muziek' + (gt.finalyoutubetitle) + '.mmp3'):
os.rename(oldfilelocation, newfilelocation)

How can i run a php function in python?

for some reasons, i have to run a php function in python.
However, i realized that it's beyond my limit.
So, i'm asking for help here.
below is the code
function munja_send($mtype, $name, $phone, $msg, $callback, $contents) {
$host = "www.sendgo.co.kr";
$id = ""; // id
$pass = ""; // password
$param = "remote_id=".$id;
$param .= "&remote_pass=".$pass;
$param .= "&remote_name=".$name;
$param .= "&remote_phone=".$phone; //cellphone number
$param .= "&remote_callback=".$callback; // my cellphone number
$param .= "&remote_msg=".$msg; // message
$param .= "&remote_contents=".$contents; // image
if ($mtype == "lms") {
$path = "/Remote/RemoteMms.html";
} else {
$path = "/Remote/RemoteSms.html";
}
$fp = #fsockopen($host,80,$errno,$errstr,30);
$return = "";
if (!$fp) {
echo $errstr."(".$errno.")";
} else {
fputs($fp, "POST ".$path." HTTP/1.1\r\n");
9
fputs($fp, "Host: ".$host."\r\n");
fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");
fputs($fp, "Content-length: ".strlen($param)."\r\n");
fputs($fp, "Connection: close\r\n\r\n");
fputs($fp, $param."\r\n\r\n");
while(!feof($fp)) $return .= fgets($fp,4096);
}
fclose ($fp);
$_temp_array = explode("\r\n\r\n", $return);
$_temp_array2 = explode("\r\n", $_temp_array[1]);
if (sizeof($_temp_array2) > 1) {
$return_string = $_temp_array2[1];
} else {
$return_string = $_temp_array2[0];
}
return $return_string;
}
i would be glad if anyone can show me a way.
thank you.
I don't know PHP, but based on my understanding, here should be a raw line-for-line translation of the code you provided, from PHP to python. I've preserved your existing comments, and added new ones for clarification in places where I was unsure or where you might want to change.
It should be pretty straightforward to follow - the difference is mostly in syntax (e.g. + for concatenation instead of .), and in converting str to bytes and vice versa.
import socket
def munja_send(mtype, name, phone, msg, callback, contents):
host = "www.sendgo.co.kr"
remote_id = "" # id (changed the variable name, since `id` is also a builtin function)
password = "" # password (`pass` is a reserved keyword in python)
param = "remote_id=" + remote_id
param += "&remote_pass=" + password
param += "&remote_name=" + name
param += "&remote_phone=" + phone # cellphone number
param += "&remote_callback=" + callback # my cellphone number
param += "&remote_msg=" + msg # message
param += "&remote_contents=" + contents # image
if mtype == "lms"
path = "/Remote/RemoteMms.html"
else:
path = "/Remote/RemoteSms.html"
socket.settimeout(30)
# change these parameters as necessary for your desired outcome
fp = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
errno = fp.connect_ex((host, 80))
if errno != 0:
# I'm not sure where errmsg comes from in php or how to get it in python
# errno should be the same, though, as it refers to the same system call error code
print("Error(" + errno + ")")
else:
returnstr = b""
fp.send("POST " + path + "HTTP/1.1\r\n")
fp.send("Host: " + host + "\r\n")
fp.send("Content-type: application/x-www-form-urlencoded\r\n")
# for accuracy, we convert param to bytes using utf-8 encoding
# before checking its length. Change the encoding as necessary for accuracy
fp.send("Content-length: " + str(len(bytes(param, 'utf-8'))) + "\r\n")
fp.send("Connection: close\r\n\r\n")
fp.send(param + "\r\n\r\n")
while (data := fp.recv(4096)):
# fp.recv() should return an empty string if eof has been hit
returnstr += data
fp.close()
_temp_array = returnstr.split(b'\r\n\r\n')
_temp_array2 = _temp_array[1].split(b'\r\n')
if len(temp_array2) > 1:
return_string = _temp_array2[1]
else:
return_string = _temp_array2[0]
# here I'm converting the raw bytes to a python string, using encoding
# utf-8 by default. Replace with your desired encoding if necessary
# or just remove the `.decode()` call if you're fine with returning a
# bytestring instead of a regular string
return return_string.decode('utf-8')
If possible, you should probably use subprocess to execute your php code directly, as other answers suggest, as straight-up translating code is often error-prone and has slightly different behavior (case in point, the lack of errmsg and probably different error handling in general, and maybe encoding issues in the above snippet). But if that's not possible, then hopefully this will help.
according to the internet, you can use subprocess and then execute the PHP script
import subprocess
# if the script don't need output.
subprocess.call("php /path/to/your/script.php")
# if you want output
proc = subprocess.Popen("php /path/to/your/script.php", shell=True, stdout=subprocess.PIPE)
script_response = proc.stdout.read()
PHP code can be executed in python using libraries subprocess or php.py based on the situation.
Please refer this answer for further details.

Python: advapi32.SetServiceStatus() fails with error 6

Original issue is now resolved, many thanks to eryksun.
Fixed code is below, I now have a different issue that I will ask about in another thread if I cannot figure it out.
Error 6 is invalid handle, however, the handle appears to be good, I believe the error is coming from the second parameter.
status = advapi32.SetServiceStatus(g_hServiceStatus, pointer(m_oServiceStatus))
if 0 == status:
dwStatus = winKernel.GetLastError()
Note: if I make the pointer None, then it doesn't fail (but obviously doesn't do anything useful either).
python -V
Python 3.6.6
Larger snippet:
from ctypes import *
from ctypes.wintypes import *
winKernel = ctypes.WinDLL('kernel32', use_last_error=True)
advapi32 = ctypes.WinDLL('advapi32', use_last_error=True)
global g_ServiceName
g_ServiceName = "StatusMonitor"
global g_lpcstrServiceName
g_lpcstrServiceName = LPCSTR(b"StatusMonitor")
class _SERVICE_STATUS(Structure):
_pack_ = 4
_fields_ = [
("dwServiceType", DWORD),
("dwCurrentState", DWORD),
("dwControlsAccepted", DWORD),
("dwWin32ExitCode", DWORD),
("dwServiceSpecificExitCode", DWORD),
("dwCheckPoint", DWORD),
("dwWaitHint", DWORD)
]
LPSERVICE_STATUS = POINTER(_SERVICE_STATUS)
global m_oServiceStatus
m_oServiceStatus = _SERVICE_STATUS(0, 0, 0, 0, 0, 0, 0)
global g_hServiceStatus
g_hServiceStatus = SERVICE_STATUS_HANDLE(None)
<lots of code snipped>
def status_report(dwCurrentState, dwWin32ExitCode, dwWaitHint):
global g_dwCheckPoint
global g_isService
try:
# Fill in the SERVICE_STATUS structure.
m_oServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS
m_oServiceStatus.dwCurrentState = dwCurrentState
m_oServiceStatus.dwWin32ExitCode = dwWin32ExitCode
m_oServiceStatus.dwWaitHint = dwWaitHint
if dwCurrentState == SERVICE_START_PENDING:
m_oServiceStatus.dwControlsAccepted = 0
else:
m_oServiceStatus.dwControlsAccepted = 1
if (dwCurrentState == SERVICE_STOPPED) or (dwCurrentState == SERVICE_RUNNING):
m_oServiceStatus.dwCheckPoint = 0
else:
g_dwCheckPoint += 1
m_oServiceStatus.dwCheckPoint = g_dwCheckPoint
status = advapi32.SetServiceStatus(g_hServiceStatus, pointer(m_oServiceStatus))
if 0 == status:
dwStatus = winKernel.GetLastError()
#logging.info("SetServiceStatus(" + str(g_hServiceStatus) + ", status=" + str(dwStatus) + ")")
logging.info("status_report(" + str(g_hServiceStatus) + ", " + str(dwCurrentState) + ", " + str(dwWin32ExitCode) + ", " + str(dwWaitHint) + ")")
dwStatus = None
if g_isService:
# Report the status of the service to the SCM.
ptrServiceStatus = LPSERVICE_STATUS(m_oServiceStatus)
logging.info("m_oServiceStatus struct: " + str(m_oServiceStatus) + ", ref: " + str(byref(m_oServiceStatus)))
logging.info(" " + "ptr: " + str(str(pointer(m_oServiceStatus))) + " PTR: " + str(ptrServiceStatus))
advapi32.SetServiceStatus.restype = BOOL
advapi32.SetServiceStatus.argtypes = [SERVICE_STATUS_HANDLE, LPSERVICE_STATUS]
status = advapi32.SetServiceStatus(g_hServiceStatus, ptrServiceStatus)
if 0 == status:
dwStatus = ctypes.get_last_error()
except Exception as e:
exc_type, exc_obj, exc_tb = sys.exc_info()
logging.error("status_report " + str(e) + " line: " + str(exc_tb.tb_lineno))
return dwStatus
advapi32.RegisterServiceCtrlHandlerExA.restype = SERVICE_STATUS_HANDLE
advapi32.RegisterServiceCtrlHandlerExA.argtypes = [LPCSTR, LPHANDLER_FUNCTION_EX, LPVOID]
g_hServiceStatus = advapi32.RegisterServiceCtrlHandlerExA(g_lpcstrServiceName, LPHANDLER_FUNCTION_EX(svc_control_handler_ex), LPVOID(None))
logging.info("control handler " + str(g_hServiceStatus))
logging.info("control handler called count " + str(g_nServiceControlHandlerCalled))
m_oServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
m_oServiceStatus.dwServiceSpecificExitCode = 0;
# set the service state as pending
dwStatus = status_report(SERVICE_START_PENDING, NO_ERROR, 3000);
logging.info("service_main: status_report(" + str(g_hServiceStatus) + "), status=" + str(dwStatus))
log_service_status(m_oServiceStatus)
Updated logging result:
INFO service_start
INFO service_start: StopEventHandle 952
INFO service_main called JimsStatusMonitor control handler called count 0
INFO control handler 2787686645712
INFO control handler called count 0
INFO status_report(2787686645712, 2, 0, 3000)128
INFO m_oServiceStatus struct: <__main__._SERVICE_STATUS object at 0x000002890FC666C8>, ref: <cparam 'P' (000002890FCA8A30)>
INFO ptr: <__main__.LP__SERVICE_STATUS object at 0x000002890FC66848> PTR: <__main__.LP__SERVICE_STATUS object at 0x000002890FC66648>
INFO service_main: status_report(2787686645712), status=None
INFO 16, 2, 0, 0, 0, 1, 3000
I must be missing something obvious, but I don't see it. I tried different pack to the structure, but with no improvement.
I also tried using byref() instead of pointer() and just passing the structure, but none of those worked. I believe using pointer() is correct here because there is another API to set the dispatch table that is working using pointer().
Note that I am specifically using FFI for this as I found the existing packages lacking for what I am trying to do. This Python solution is based on a C++ solution that I wrote that works, I just need to understand whatever nuance to the FFI that is causing it to fail.
I should add that the service is actually running at this point, I just can't transition it out of Starting state with this issue.
Hopefully someone can tell me what I am doing wrong?
Thanks in advance,
-Dave
With many thanks to eryksun, I was able to resolve the original issue.
The main issue was that I was assuming the Windows APIs were fully defined because it seemed like they were working without restype and argstype defined.
Needed the following:
advapi32.RegisterServiceCtrlHandlerExA.restype = SERVICE_STATUS_HANDLE
advapi32.RegisterServiceCtrlHandlerExA.argtypes = [LPCSTR, LPHANDLER_FUNCTION_EX, LPVOID]
g_hServiceStatus = advapi32.RegisterServiceCtrlHandlerExA(g_lpcstrServiceName, LPHANDLER_FUNCTION_EX(svc_control_handler_ex), LPVOID(None))
advapi32.SetServiceStatus.restype = BOOL
advapi32.SetServiceStatus.argtypes = [SERVICE_STATUS_HANDLE, LPSERVICE_STATUS]
status = advapi32.SetServiceStatus(g_hServiceStatus, ptrServiceStatus)
With those defined correctly, there were still two remaining issues that I was able to figure out from the documentation.
The first was I missed that restype is the first argument to WINFUNCTYPE(), given the responses from eryksun, it was more obvious to me, and that explained why my definition for my service_main() wasn't working as expected.
The second was a bit more subtle and is found at the end of the callback documentation here:
Important note for callback functions:
Make sure you keep references to CFUNCTYPE objects as long as they are
used from C code. ctypes doesn't, and if you don't, they may be
garbage collected, crashing your program when a callback is made.
Note that the original code that was failing can be found in the Python forum here.

Simulate multiple users in Grinder

I was wondering if this is even possible. I just set up Grinder and ran some base test but what if I want to have each thread be a different user? I see this line of code in the file that is generated (I am not a python developer)-could I somehow pass the username/password as a variable?
# Expecting 302 'Found'
result = request10501.POST('/site/home' +
'?p_p_id=' +
self.token_p_p_id +
'&p_p_lifecycle=' +
self.token_p_p_lifecycle +
'&p_p_state=' +
self.token_p_p_state +
'&p_p_mode=' +
self.token_p_p_mode +
'&p_p_col_id=' +
self.token_p_p_col_id +
'&p_p_col_count=' +
self.token_p_p_col_count +
'&_58_doActionAfterLogin=' +
self.token__58_doActionAfterLogin +
'&_58_struts_action=' +
self.token__58_struts_action +
'&saveLastPath=' +
self.token_saveLastPath,
( NVPair('_58_formDate', '1466168922083'),
NVPair('_58_login', 'user1'),
NVPair('_58_password', 'pass1'), ),
( NVPair('Content-Type', 'application/x-www-form-urlencoded'), ))
Thanks
So what I have done is maintain the users in a csv file and read them into an array . Now for eg there are 3 threads you can use a multiple of grinder.getRunNumber& grinder.getThreadNumber(check the exact api name) and extract that record dynamically .
Move the user1 & pass1 to a global scope and perform all the logic there.
See the API Link

pyparsing lineno issue (bug?)

I am using pyparsing to parse a language called pig. I found some unexpected result when used the function 'lineno' when the input text have some '\t' in it.
For easy to ask, I simplified the code to address the problem:
#/usr/bin/env python
from pyparsing import *
ident = Word(alphas)
statement1 = ident + Literal('=')+ Keyword('GENERATE', caseless = True) + SkipTo(Literal(';'),ignore = nestedExpr())+ Literal(';').suppress()
statement2 = Keyword('STORE',caseless = True) + ident + Literal(';').suppress()
statement = statement1|statement2
text = """
fact = GENERATE
('Exp' :(a
)
) ;
STORE fact ;
"""
all_statements = statement.scanString(text)
for tokens,startloc,endloc in all_statements:
print 'startloc:' + str(startloc) , 'lineno:' + str(lineno(startloc,text))
print 'endloc:' + str(endloc), 'lineno:' + str(lineno(endloc,text))
print tokens
Notice that in the input text, there is more than 3 '\t' in the beginning of the third line
When I run this , the output is :
startloc:1 lineno:2
endloc:66 lineno:10
['fact', '=', 'GENERATE', "('Exp' :(a\n )\n) "]
startloc:68 lineno:10
endloc:80 lineno:10
['STORE', 'fact']
this should be wrong, as there is total 9 line, it said the first statement is from line 2 to line 10.
I happened to found that when I delete those '\t', the input text is :
text = """
fact = GENERATE
('Exp' :(a
)
) ;
STORE fact ;
"""
and I run it again, the result is :
startloc:1 lineno:2
endloc:34 lineno:5
['fact', '=', 'GENERATE', "('Exp' :(a\n)\n) "]
startloc:36 lineno:7
endloc:48 lineno:7
['STORE', 'fact']
And this result seems correct, the first statement is from line 2 to line 5, the second statemenet is from line 7 to line 7 .This is what I expected.
So I think there maybe something wrong in the lineno() function, or maybe scanString.
Or maybe there is something wrong in my code?
Use parseWithTabs before calling scanString.

Categories