From c6a9502ea2c65116ef74d5861a067a027c6713c8 Mon Sep 17 00:00:00 2001 From: Lucian Petrut Date: Fri, 3 Nov 2023 15:11:58 +0000 Subject: [PATCH] Add py 3.12 unicode fixes PyArg_ParseTupleAndKeywords does not support 'u' types starting from Python 3.12. These changes use the 's' type and then converts it to the former required type using a new helper method ToWstring. --- PyMI/Application.cpp | 32 +++++++-------- PyMI/DestinationOptions.cpp | 30 +++++++------- PyMI/OperationOptions.cpp | 6 +-- PyMI/Session.cpp | 78 ++++++++++++++++++------------------- PyMI/Utils.cpp | 28 +++++++++++++ PyMI/Utils.h | 1 + 6 files changed, 102 insertions(+), 73 deletions(-) diff --git a/PyMI/Application.cpp b/PyMI/Application.cpp index e51aa18..c37a62f 100644 --- a/PyMI/Application.cpp +++ b/PyMI/Application.cpp @@ -19,15 +19,15 @@ static PyObject* Application_new(PyTypeObject *type, PyObject *args, PyObject *k static int Application_init(Application *self, PyObject *args, PyObject *kwds) { - wchar_t* appId = L""; + char* appId = ""; static char *kwlist[] = { "app_id", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|u", kwlist, &appId)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|s", kwlist, &appId)) return -1; try { AllowThreads(&self->cs, [&]() { - self->app = std::make_shared(appId); + self->app = std::make_shared(ToWstring(appId).c_str()); }); return 0; } @@ -40,12 +40,12 @@ static int Application_init(Application *self, PyObject *args, PyObject *kwds) static PyObject* Application_NewSession(Application *self, PyObject *args, PyObject *kwds) { - wchar_t* protocol = L""; - wchar_t* computerName = L"."; + char* protocol = ""; + char* computerName = "."; PyObject* destinationOptions = NULL; static char *kwlist[] = { "protocol", "computer_name", "destination_options", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|uuO", kwlist, &protocol, &computerName, &destinationOptions)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ssO", kwlist, &protocol, &computerName, &destinationOptions)) return NULL; try @@ -57,7 +57,7 @@ static PyObject* Application_NewSession(Application *self, PyObject *args, PyObj std::shared_ptr session; AllowThreads(&self->cs, [&]() { - session = self->app->NewSession(protocol, computerName, + session = self->app->NewSession(ToWstring(protocol).c_str(), ToWstring(computerName).c_str(), !CheckPyNone(destinationOptions) ? ((DestinationOptions*)destinationOptions)->destinationOptions : NULL); }); return (PyObject*)Session_New(session); @@ -84,10 +84,10 @@ static void Application_dealloc(Application* self) static PyObject* Application_NewMethodInboundParameters(Application *self, PyObject *args, PyObject *kwds) { PyObject* pyClass = NULL; - wchar_t* methodName = NULL; + char* methodName = NULL; static char *kwlist[] = { "mi_class", "method_name", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "Ou", kwlist, &pyClass, &methodName)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "Os", kwlist, &pyClass, &methodName)) return NULL; try @@ -97,7 +97,7 @@ static PyObject* Application_NewMethodInboundParameters(Application *self, PyObj std::shared_ptr instance; AllowThreads(&self->cs, [&]() { - instance = self->app->NewMethodParamsInstance(*((Class*)pyClass)->miClass, methodName); + instance = self->app->NewMethodParamsInstance(*((Class*)pyClass)->miClass, ToWstring(methodName).c_str()); }); return (PyObject*)Instance_New(instance); } @@ -110,16 +110,16 @@ static PyObject* Application_NewMethodInboundParameters(Application *self, PyObj static PyObject* Application_NewInstance(Application *self, PyObject *args, PyObject *kwds) { - wchar_t* className = NULL; + char* className = NULL; static char *kwlist[] = { "class_name", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "u", kwlist, &className)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &className)) return NULL; try { std::shared_ptr instance; AllowThreads(&self->cs, [&]() { - instance = self->app->NewInstance(className); + instance = self->app->NewInstance(ToWstring(className).c_str()); }); return (PyObject*)Instance_New(instance); } @@ -132,10 +132,10 @@ static PyObject* Application_NewInstance(Application *self, PyObject *args, PyOb static PyObject* Application_NewInstanceFromClass(Application *self, PyObject *args, PyObject *kwds) { - wchar_t* className = NULL; + char* className = NULL; PyObject* miClass = NULL; static char *kwlist[] = { "class_name", "mi_class", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "uO", kwlist, &className, &miClass)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO", kwlist, &className, &miClass)) return NULL; try @@ -145,7 +145,7 @@ static PyObject* Application_NewInstanceFromClass(Application *self, PyObject *a std::shared_ptr instance; AllowThreads(&self->cs, [&]() { - instance = self->app->NewInstanceFromClass(className, *((Class*)miClass)->miClass); + instance = self->app->NewInstanceFromClass(ToWstring(className).c_str(), *((Class*)miClass)->miClass); }); return (PyObject*)Instance_New(instance); } diff --git a/PyMI/DestinationOptions.cpp b/PyMI/DestinationOptions.cpp index 73a9034..e16ab1f 100644 --- a/PyMI/DestinationOptions.cpp +++ b/PyMI/DestinationOptions.cpp @@ -75,15 +75,15 @@ static PyObject* DestinationOptions_GetUILocale(DestinationOptions* self) static PyObject* DestinationOptions_SetUILocale(DestinationOptions* self, PyObject *args, PyObject *kwds) { - wchar_t* locale = NULL; + char* locale = NULL; static char *kwlist[] = { "locale_name", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "u", kwlist, &locale)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &locale)) return NULL; try { AllowThreads(&self->cs, [&]() { - self->destinationOptions->SetUILocale(locale); + self->destinationOptions->SetUILocale(ToWstring(locale).c_str()); }); Py_RETURN_NONE; } @@ -139,15 +139,15 @@ static PyObject* DestinationOptions_SetTimeout(DestinationOptions* self, PyObjec static PyObject* DestinationOptions_SetTransport(DestinationOptions* self, PyObject *args, PyObject *kwds) { - wchar_t* transport = NULL; + char* transport = NULL; static char *kwlist[] = { "transport", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "u", kwlist, &transport)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &transport)) return NULL; try { AllowThreads(&self->cs, [&]() { - self->destinationOptions->SetTransport(transport); + self->destinationOptions->SetTransport(ToWstring(transport).c_str()); }); Py_RETURN_NONE; } @@ -178,26 +178,26 @@ static PyObject* DestinationOptions_GetTransport(DestinationOptions* self) static PyObject* DestinationOptions_AddCredentials(DestinationOptions* self, PyObject *args, PyObject *kwds) { - wchar_t* authType = NULL; - wchar_t* domain = NULL; - wchar_t* username = NULL; - wchar_t* password = NULL; - wchar_t* certThumbprint = NULL; + char* authType = NULL; + char* domain = NULL; + char* username = NULL; + char* password = NULL; + char* certThumbprint = NULL; static char *kwlist[] = { "auth_type", "domain", "username", "password", "cert_thumbprint", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "u|uuuu", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|ssss", kwlist, &authType, &domain, &username, &password, &certThumbprint)) return NULL; try { - if (certThumbprint && wcslen(certThumbprint)) + if (ToWstring(certThumbprint).c_str() && wcslen(ToWstring(certThumbprint).c_str())) AllowThreads(&self->cs, [&]() { - self->destinationOptions->AddCredentials(authType, certThumbprint); + self->destinationOptions->AddCredentials(ToWstring(authType).c_str(), ToWstring(certThumbprint).c_str()); }); else AllowThreads(&self->cs, [&]() { - self->destinationOptions->AddCredentials(authType, domain, username, password); + self->destinationOptions->AddCredentials(ToWstring(authType).c_str(), ToWstring(domain).c_str(), ToWstring(username).c_str(), ToWstring(password).c_str()); }); Py_RETURN_NONE; } diff --git a/PyMI/OperationOptions.cpp b/PyMI/OperationOptions.cpp index 2122920..18c528f 100644 --- a/PyMI/OperationOptions.cpp +++ b/PyMI/OperationOptions.cpp @@ -101,13 +101,13 @@ static PyObject* OperationOptions_SetTimeout(OperationOptions* self, PyObject* t static PyObject* OperationOptions_SetCustomOption(OperationOptions* self, PyObject *args, PyObject *kwds) { - wchar_t* optionName = NULL; + char* optionName = NULL; unsigned int optionValueType = 0; PyObject* optionValue = NULL; PyObject* mustComply = NULL; static char *kwlist[] = { "name", "value_type", "value", "must_comply", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "uIO|O", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "sIO|O", kwlist, &optionName, &optionValueType, &optionValue, &mustComply)) return NULL; @@ -116,7 +116,7 @@ static PyObject* OperationOptions_SetCustomOption(OperationOptions* self, PyObj { auto miValue = Py2MI(optionValue, (MI_Type)optionValueType); AllowThreads(&self->cs, [&]() { - self->operationOptions->SetCustomOption(optionName, (MI_Type)optionValueType, + self->operationOptions->SetCustomOption(ToWstring(optionName).c_str(), (MI_Type)optionValueType, *miValue, PyObject_IsTrue(mustComply)); }); Py_RETURN_NONE; diff --git a/PyMI/Session.cpp b/PyMI/Session.cpp index 7003e61..010d532 100644 --- a/PyMI/Session.cpp +++ b/PyMI/Session.cpp @@ -39,13 +39,13 @@ static void Session_dealloc(Session* self) static PyObject* Session_ExecQuery(Session *self, PyObject *args, PyObject *kwds) { - wchar_t* ns = NULL; - wchar_t* query = NULL; - wchar_t* dialect = L"WQL"; + char* ns = NULL; + char* query = NULL; + char* dialect = "WQL"; PyObject* operationOptions = NULL; static char *kwlist[] = { "ns", "query", "dialect", "operation_options", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "uu|uO", kwlist, &ns, &query, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss|sO", kwlist, &ns, &query, &dialect, &operationOptions)) return NULL; @@ -56,7 +56,7 @@ static PyObject* Session_ExecQuery(Session *self, PyObject *args, PyObject *kwds std::shared_ptr op; AllowThreads(&self->cs, [&]() { op = self->session->ExecQuery( - ns, query, dialect, + ToWstring(ns).c_str(), ToWstring(query).c_str(), ToWstring(dialect).c_str(), !CheckPyNone(operationOptions) ? ((OperationOptions*)operationOptions)->operationOptions : NULL); @@ -73,17 +73,17 @@ static PyObject* Session_ExecQuery(Session *self, PyObject *args, PyObject *kwds static PyObject* Session_GetAssociators(Session *self, PyObject *args, PyObject *kwds) { PyObject* instance = NULL; - wchar_t* ns = NULL; - wchar_t* assocClass = L""; - wchar_t* resultClass = L""; - wchar_t* role = L""; - wchar_t* resultRole = L""; + char* ns = NULL; + char* assocClass = ""; + char* resultClass = ""; + char* role = ""; + char* resultRole = ""; PyObject* keysOnlyObj = NULL; PyObject* operationOptions = NULL; static char *kwlist[] = { "ns", "instance", "assoc_class", "result_class", "role", "result_role", "keys_only", "operation_options", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "uO|uuuuOO", kwlist, &ns, &instance, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO|ssssOO", kwlist, &ns, &instance, &assocClass, &resultClass, &role, &resultRole, &keysOnlyObj, &operationOptions)) return NULL; @@ -99,8 +99,8 @@ static PyObject* Session_GetAssociators(Session *self, PyObject *args, PyObject std::shared_ptr op; AllowThreads(&self->cs, [&]() { op = self->session->GetAssociators( - ns, *((Instance*)instance)->instance, assocClass, - resultClass, role, resultRole, keysOnly, + ToWstring(ns).c_str(), *((Instance*)instance)->instance, ToWstring(assocClass).c_str(), + ToWstring(resultClass).c_str(), ToWstring(role).c_str(), ToWstring(resultRole).c_str(), keysOnly, !CheckPyNone(operationOptions) ? ((OperationOptions*)operationOptions)->operationOptions : NULL); @@ -150,12 +150,12 @@ static PyObject* Session_exit(Session* self, PyObject*) static PyObject* Session_CreateInstance(Session *self, PyObject *args, PyObject *kwds) { - wchar_t* ns = NULL; + char* ns = NULL; PyObject* instance = NULL; PyObject* operationOptions = NULL; static char *kwlist[] = { "ns", "instance", "operation_options", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "uO|O", kwlist, &ns, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO|O", kwlist, &ns, &instance, &operationOptions)) return NULL; @@ -167,7 +167,7 @@ static PyObject* Session_CreateInstance(Session *self, PyObject *args, PyObject AllowThreads(&self->cs, [&]() { self->session->CreateInstance( - ns, *((Instance*)instance)->instance, + ToWstring(ns).c_str(), *((Instance*)instance)->instance, !CheckPyNone(operationOptions) ? ((OperationOptions*)operationOptions)->operationOptions : NULL); @@ -183,12 +183,12 @@ static PyObject* Session_CreateInstance(Session *self, PyObject *args, PyObject static PyObject* Session_ModifyInstance(Session *self, PyObject *args, PyObject *kwds) { - wchar_t* ns = NULL; + char* ns = NULL; PyObject* instance = NULL; PyObject* operationOptions = NULL; static char *kwlist[] = { "ns", "instance", "operation_options", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "uO|O", kwlist, &ns, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO|O", kwlist, &ns, &instance, &operationOptions)) return NULL; @@ -200,7 +200,7 @@ static PyObject* Session_ModifyInstance(Session *self, PyObject *args, PyObject AllowThreads(&self->cs, [&]() { self->session->ModifyInstance( - ns, *((Instance*)instance)->instance, + ToWstring(ns).c_str(), *((Instance*)instance)->instance, !CheckPyNone(operationOptions) ? ((OperationOptions*)operationOptions)->operationOptions : NULL); @@ -216,12 +216,12 @@ static PyObject* Session_ModifyInstance(Session *self, PyObject *args, PyObject static PyObject* Session_DeleteInstance(Session *self, PyObject *args, PyObject *kwds) { - wchar_t* ns = NULL; + char* ns = NULL; PyObject* instance = NULL; PyObject* operationOptions = NULL; static char *kwlist[] = { "ns", "instance", "operation_options", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "uO|O", kwlist, &ns, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO|O", kwlist, &ns, &instance, &operationOptions)) return NULL; @@ -233,7 +233,7 @@ static PyObject* Session_DeleteInstance(Session *self, PyObject *args, PyObject AllowThreads(&self->cs, [&]() { self->session->DeleteInstance( - ns, *((Instance*)instance)->instance, + ToWstring(ns).c_str(), *((Instance*)instance)->instance, !CheckPyNone(operationOptions) ? ((OperationOptions*)operationOptions)->operationOptions : NULL); @@ -249,18 +249,18 @@ static PyObject* Session_DeleteInstance(Session *self, PyObject *args, PyObject static PyObject* Session_GetClass(Session *self, PyObject *args, PyObject *kwds) { - wchar_t* ns = NULL; - wchar_t* className = NULL; + char* ns = NULL; + char* className = NULL; static char *kwlist[] = { "ns", "class_name", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "uu", kwlist, &ns, &className)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss", kwlist, &ns, &className)) return NULL; try { std::shared_ptr op; AllowThreads(&self->cs, [&]() { - op = self->session->GetClass(ns, className); + op = self->session->GetClass(ToWstring(ns).c_str(), ToWstring(className).c_str()); }); return (PyObject*)Operation_New(op); } @@ -273,11 +273,11 @@ static PyObject* Session_GetClass(Session *self, PyObject *args, PyObject *kwds) static PyObject* Session_GetInstance(Session *self, PyObject *args, PyObject *kwds) { - wchar_t* ns = NULL; + char* ns = NULL; PyObject* keyInstance = NULL; static char *kwlist[] = { "ns", "key_instance", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "uO", kwlist, &ns, &keyInstance)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "sO", kwlist, &ns, &keyInstance)) return NULL; try @@ -287,7 +287,7 @@ static PyObject* Session_GetInstance(Session *self, PyObject *args, PyObject *kw std::shared_ptr op; AllowThreads(&self->cs, [&]() { - op = self->session->GetInstance(ns, *((Instance*)keyInstance)->instance); + op = self->session->GetInstance(ToWstring(ns).c_str(), *((Instance*)keyInstance)->instance); }); return (PyObject*)Operation_New(op); } @@ -300,14 +300,14 @@ static PyObject* Session_GetInstance(Session *self, PyObject *args, PyObject *kw static PyObject* Session_Subscribe(Session *self, PyObject *args, PyObject *kwds) { - wchar_t* ns = NULL; - wchar_t* query = NULL; + char* ns = NULL; + char* query = NULL; PyObject* indicationResultCallback = NULL; PyObject* operationOptions = NULL; - wchar_t* dialect = L"WQL"; + char* dialect = "WQL"; static char *kwlist[] = { "ns", "query", "indication_result", "operation_options", "dialect", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "uu|OOu", kwlist, &ns, &query, &indicationResultCallback, &operationOptions, &dialect)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss|OOs", kwlist, &ns, &query, &indicationResultCallback, &operationOptions, &dialect)) return NULL; try @@ -325,9 +325,9 @@ static PyObject* Session_Subscribe(Session *self, PyObject *args, PyObject *kwds std::shared_ptr op; AllowThreads(&self->cs, [&]() { - op = self->session->Subscribe(ns, query, callbacks, + op = self->session->Subscribe(ToWstring(ns).c_str(), ToWstring(query).c_str(), callbacks, !CheckPyNone(operationOptions) ? ((OperationOptions*)operationOptions)->operationOptions : NULL, - dialect); + ToWstring(dialect).c_str()); }); PyObject* obj = (PyObject*)Operation_New(op); if (callbacks) @@ -346,12 +346,12 @@ static PyObject* Session_Subscribe(Session *self, PyObject *args, PyObject *kwds static PyObject* Session_InvokeMethod(Session *self, PyObject *args, PyObject *kwds) { PyObject* target = NULL; - wchar_t* methodName = NULL; + char* methodName = NULL; PyObject* inboundParams = NULL; PyObject* operationOptions = NULL; static char *kwlist[] = { "target", "method_name", "inbound_params", "operation_options", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "Ou|OO", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "Os|OO", kwlist, &target, &methodName, &inboundParams, &operationOptions)) return NULL; @@ -365,7 +365,7 @@ static PyObject* Session_InvokeMethod(Session *self, PyObject *args, PyObject *k if (PyObject_IsInstance(target, reinterpret_cast(&InstanceType))) { AllowThreads(&self->cs, [&]() { - op = self->session->InvokeMethod(*((Instance*)target)->instance, methodName, + op = self->session->InvokeMethod(*((Instance*)target)->instance, ToWstring(methodName).c_str(), !CheckPyNone(inboundParams) ? ((Instance*)inboundParams)->instance : NULL, !CheckPyNone(operationOptions) ? ((OperationOptions*)operationOptions)->operationOptions @@ -376,7 +376,7 @@ static PyObject* Session_InvokeMethod(Session *self, PyObject *args, PyObject *k { AllowThreads(&self->cs, [&]() { auto miClass = ((Class*)target)->miClass; - op = self->session->InvokeMethod(miClass->GetNameSpace(), miClass->GetClassName(), methodName, + op = self->session->InvokeMethod(miClass->GetNameSpace(), miClass->GetClassName(), ToWstring(methodName).c_str(), !CheckPyNone(inboundParams) ? ((Instance*)inboundParams)->instance : NULL, !CheckPyNone(operationOptions) ? ((OperationOptions*)operationOptions)->operationOptions diff --git a/PyMI/Utils.cpp b/PyMI/Utils.cpp index 0588604..441dbc9 100644 --- a/PyMI/Utils.cpp +++ b/PyMI/Utils.cpp @@ -516,3 +516,31 @@ void ValidatePyObjectType(PyObject* obj, const std::wstring& objName, throw MI::TypeConversionException( L"\"" + objName + L"\"must have type " + expectedTypeName); } + +std::wstring ToWstring(const std::string& inString) +{ + if (inString.empty()) + { + return L""; + } + + int sizeNeeded = MultiByteToWideChar(CP_UTF8, 0, &inString.at(0), (int)inString.size(), nullptr, 0); + if (sizeNeeded <= 0) + { + DWORD err = GetLastError(); + throw MI::TypeConversionException( + L"wstring conversion failed. Error: " + std::to_wstring(err)); + } + + std::wstring result(sizeNeeded, 0); + sizeNeeded = MultiByteToWideChar( + CP_UTF8, 0, &inString.at(0), (int)inString.size(), + &result.at(0), sizeNeeded); + if (sizeNeeded <= 0) { + DWORD err = GetLastError(); + throw MI::TypeConversionException( + L"wstring conversion failed. Error: " + std::to_wstring(err)); + } + + return result; +} diff --git a/PyMI/Utils.h b/PyMI/Utils.h index b4a556a..d6643d2 100644 --- a/PyMI/Utils.h +++ b/PyMI/Utils.h @@ -20,3 +20,4 @@ bool CheckPyNone(PyObject* obj); void ValidatePyObjectType(PyObject* obj, const std::wstring& objName, PyTypeObject* expectedType, const std::wstring& expectedTypeName, bool allowNone = true); +std::wstring ToWstring(const std::string& inString); \ No newline at end of file