@@ -18,7 +18,7 @@ namespace NppPythonScript
1818PythonHandler::PythonHandler (TCHAR *pluginsDir, TCHAR *configDir, HINSTANCE hInst, HWND nppHandle, HWND scintilla1Handle, HWND scintilla2Handle, boost::shared_ptr<PythonConsole> pythonConsole)
1919 : PyProducerConsumer<RunScriptArgs>(),
2020 m_nppHandle (nppHandle),
21- m_scintilla1Handle (scintilla1Handle),
21+ m_scintilla1Handle (scintilla1Handle),
2222 m_scintilla2Handle (scintilla2Handle),
2323 m_hInst (hInst),
2424 m_machineBaseDir (pluginsDir),
@@ -89,99 +89,179 @@ void PythonHandler::initPython()
8989
9090 preinitScintillaModule ();
9191
92+ PyStatus status;
93+
94+ PyConfig config;
95+ PyConfig_InitPythonConfig (&config);
96+
97+ // Read all configuration at once
98+ // implicit pre config python
99+ status = PyConfig_Read (&config);
100+ if (PyStatus_Exception (status))
101+ {
102+ PyConfig_Clear (&config);
103+ }
104+
92105 // Don't import site - if Python 2.7 doesn't find it as part of Py_Initialize,
93106 // it does an exit(1) - AGH!
94107 Py_NoSiteFlag = 1 ;
95108 Py_IgnoreEnvironmentFlag = 1 ;
96109 Py_NoUserSiteDirectory = 1 ;
97110
98- Py_Initialize ();
99- // Initialise threading and create & acquire Global Interpreter Lock
100- PyEval_InitThreads ();
111+ # ifdef DEBUG
112+ Py_VerboseFlag = 1 ;
113+ # endif
101114
115+ bool configSetFailed = false ;
102116
103- std::shared_ptr<char > machineBaseDir = WcharMbcsConverter::tchar2char (m_machineBaseDir.c_str ());
104- std::shared_ptr<char > configDir = WcharMbcsConverter::tchar2char (m_userBaseDir.c_str ());
117+ // appended or prepended below in this order
118+ std::wstring machinelib = m_machineBaseDir + std::wstring (L" lib" );
119+ std::wstring userlib = m_userBaseDir + std::wstring (L" lib" );
120+ std::wstring machineScripts = m_machineBaseDir + std::wstring (L" scripts" );
121+ std::wstring userScripts = m_userBaseDir + std::wstring (L" scripts" );
122+ std::wstring machinelibTK = m_machineBaseDir + std::wstring (L" lib\\ lib-tk" );
105123
106- bool machineIsUnicode = containsExtendedChars (machineBaseDir.get ());
107- bool userIsUnicode = containsExtendedChars (configDir.get ());
124+ // If the user wants to use their installed python version, append the paths.
125+ // If not (and they want to use the bundled python install), the default, then prepend the paths
126+ if (ConfigFile::getInstance ()->getSetting (_T (" PREFERINSTALLEDPYTHON" )) == _T (" 1" ))
127+ {
128+ /* Append our custom search path to sys.path */
129+ status = PyWideStringList_Append (&config.module_search_paths ,
130+ machinelib.c_str ());
108131
132+ if (PyStatus_Exception (status))
133+ {
134+ configSetFailed = true ;
135+ }
109136
110- std::string smachineDir (machineBaseDir.get ());
111- std::string suserDir (configDir.get ());
137+ /* Append our custom search path to sys.path */
138+ status = PyWideStringList_Append (&config.module_search_paths ,
139+ userlib.c_str ());
112140
141+ if (PyStatus_Exception (status))
142+ {
143+ configSetFailed = true ;
144+ }
113145
114- // Init paths
115- char initBuffer[ 1024 ];
116- char pathCommands[ 500 ] ;
146+ /* Append our custom search path to sys.path */
147+ status = PyWideStringList_Append (&config. module_search_paths ,
148+ machineScripts. c_str ()) ;
117149
118- // If the user wants to use their installed python version, append the paths.
119- // If not (and they want to use the bundled python install), the default, then prepend the paths
120- if (ConfigFile::getInstance ()->getSetting (_T (" PREFERINSTALLEDPYTHON" )) == _T (" 1" )) {
121- strcpy_s<500 >(pathCommands, " import sys\n "
122- " sys.path.append(r'%slib'%s)\n "
123- " sys.path.append(r'%slib'%s)\n "
124- " sys.path.append(r'%sscripts'%s)\n "
125- " sys.path.append(r'%sscripts'%s)\n "
126- " sys.path.append(r'%slib\\ lib-tk'%s)\n " );
127- } else {
128- strcpy_s<500 >(pathCommands, " import sys\n "
129- " sys.path.insert(0,r'%slib'%s)\n "
130- " sys.path.insert(1,r'%slib'%s)\n "
131- " sys.path.insert(2,r'%sscripts'%s)\n "
132- " sys.path.insert(3,r'%sscripts'%s)\n "
133- " sys.path.insert(4,r'%slib\\ lib-tk'%s)\n "
134- );
150+ if (PyStatus_Exception (status))
151+ {
152+ configSetFailed = true ;
153+ }
154+
155+ /* Append our custom search path to sys.path */
156+ status = PyWideStringList_Append (&config.module_search_paths ,
157+ userScripts.c_str ());
158+
159+ if (PyStatus_Exception (status))
160+ {
161+ configSetFailed = true ;
162+ }
163+
164+ /* Append our custom search path to sys.path */
165+ status = PyWideStringList_Append (&config.module_search_paths ,
166+ machinelibTK.c_str ());
167+
168+ if (PyStatus_Exception (status))
169+ {
170+ configSetFailed = true ;
171+ }
135172 }
173+ else
174+ {
175+ /* Prepend via insert our custom search path to sys.path */
176+ status = PyWideStringList_Insert (&config.module_search_paths , 0 ,
177+ machinelib.c_str ());
136178
137- _snprintf_s (initBuffer, 1024 , 1024 ,
138- pathCommands,
139- smachineDir. c_str (),
140- machineIsUnicode ? " .decode('utf8') " : " " ,
179+ if ( PyStatus_Exception (status))
180+ {
181+ configSetFailed = true ;
182+ }
141183
142- suserDir.c_str (),
143- userIsUnicode ? " .decode('utf8')" : " " ,
184+ /* Prepend via insert our custom search path to sys.path */
185+ status = PyWideStringList_Insert (&config.module_search_paths , 1 ,
186+ userlib.c_str ());
144187
145- smachineDir.c_str (),
146- machineIsUnicode ? " .decode('utf8')" : " " ,
188+ if (PyStatus_Exception (status))
189+ {
190+ PyConfig_Clear (&config);
191+ }
192+
193+ /* Prepend via insert our custom search path to sys.path */
194+ status = PyWideStringList_Insert (&config.module_search_paths , 2 ,
195+ machineScripts.c_str ());
196+
197+ if (PyStatus_Exception (status))
198+ {
199+ configSetFailed = true ;
200+ }
201+
202+ /* Prepend via insert our custom search path to sys.path */
203+ status = PyWideStringList_Insert (&config.module_search_paths , 3 ,
204+ userScripts.c_str ());
205+
206+ if (PyStatus_Exception (status))
207+ {
208+ PyConfig_Clear (&config);
209+ }
210+
211+ /* Prepend via insert our custom search path to sys.path */
212+ status = PyWideStringList_Insert (&config.module_search_paths , 4 ,
213+ machinelibTK.c_str ());
214+
215+ if (PyStatus_Exception (status))
216+ {
217+ configSetFailed = true ;
218+ }
219+ }
220+
221+ if (!configSetFailed)
222+ {
223+ status = Py_InitializeFromConfig (&config);
224+ if (PyStatus_Exception (status))
225+ {
226+ PyConfig_Clear (&config);
227+ }
228+ }
147229
148- suserDir. c_str (),
149- userIsUnicode ? " .decode('utf8') " : " " ,
230+ // Initialise threading and create & acquire Global Interpreter Lock
231+ PyEval_InitThreads ();
150232
151- smachineDir.c_str (),
152- machineIsUnicode ? " .decode('utf8')" : " "
153- );
233+ std::string importSys (" import sys\n " );
154234
155- PyRun_SimpleString (initBuffer );
235+ PyRun_SimpleString (importSys. c_str () );
156236
157- initSysArgv ();
237+ initSysArgv ();
158238
159239
160240 // Init Notepad++/Scintilla modules
161241 initModules ();
162242
163- mp_mainThreadState = PyEval_SaveThread ();
243+ mp_mainThreadState = PyEval_SaveThread ();
164244
165245}
166246
167247void PythonHandler::initSysArgv ()
168248{
169- LPWSTR commandLine = ::GetCommandLineW ();
170- int argc;
171- LPWSTR* argv = ::CommandLineToArgvW (commandLine, &argc);
249+ LPWSTR commandLine = ::GetCommandLineW ();
250+ int argc;
251+ LPWSTR* argv = ::CommandLineToArgvW (commandLine, &argc);
172252
173253
174- boost::python::list argvList;
175- for (int currentArg = 0 ; currentArg != argc; ++currentArg)
254+ boost::python::list argvList;
255+ for (int currentArg = 0 ; currentArg != argc; ++currentArg)
176256 {
177- std::shared_ptr<char > argInUtf8 = WcharMbcsConverter::wchar2char (argv[currentArg]);
178- PyObject* unicodeArg = PyUnicode_FromString (argInUtf8.get ());
257+ std::shared_ptr<char > argInUtf8 = WcharMbcsConverter::wchar2char (argv[currentArg]);
258+ PyObject* unicodeArg = PyUnicode_FromString (argInUtf8.get ());
179259
180260 argvList.append (boost::python::handle<>(unicodeArg));
181- }
261+ }
182262
183- boost::python::object sysModule (boost::python::handle<>(boost::python::borrowed (PyImport_AddModule (" sys" ))));
184- sysModule.attr (" argv" ) = argvList;
263+ boost::python::object sysModule (boost::python::handle<>(boost::python::borrowed (PyImport_AddModule (" sys" ))));
264+ sysModule.attr (" argv" ) = argvList;
185265
186266
187267}
@@ -286,7 +366,7 @@ void PythonHandler::consume(std::shared_ptr<RunScriptArgs> args)
286366void PythonHandler::runScriptWorker (const std::shared_ptr<RunScriptArgs>& args)
287367{
288368
289- GILLock gilLock;
369+ GILLock gilLock;
290370
291371 if (args->m_isStatement )
292372 {
@@ -296,7 +376,7 @@ void PythonHandler::runScriptWorker(const std::shared_ptr<RunScriptArgs>& args)
296376 {
297377 mp_console->writeText (boost::python::str (" \n " ));
298378 }
299-
379+
300380 if (ConfigFile::getInstance ()->getSetting (_T (" OPENCONSOLEONERROR" )) == _T (" 1" ))
301381 {
302382 mp_console->pythonShowDialog ();
@@ -314,7 +394,7 @@ void PythonHandler::runScriptWorker(const std::shared_ptr<RunScriptArgs>& args)
314394 {
315395 mp_console->writeText (boost::python::str (" \n " ));
316396 }
317-
397+
318398 if (ConfigFile::getInstance ()->getSetting (_T (" OPENCONSOLEONERROR" )) == _T (" 1" ))
319399 {
320400 mp_console->pythonShowDialog ();
@@ -368,7 +448,7 @@ void PythonHandler::stopScript()
368448
369449void PythonHandler::stopScriptWorker (PythonHandler *handler)
370450{
371- GILLock gilLock;
451+ GILLock gilLock;
372452
373453 PyThreadState_SetAsyncExc ((long )handler->getExecutingThreadID (), PyExc_KeyboardInterrupt);
374454
0 commit comments