fixed issue #6 (py command doesn't repeat 'python -m' functionality)

This commit is contained in:
ussrhero 2018-01-10 19:29:16 +03:00
parent 34c9190bdb
commit bcdbe37f78
4 changed files with 108 additions and 97 deletions

View File

@ -35,7 +35,8 @@ Options::Options(const std::string& cmdline) :
pyMajorVersion(-1), pyMajorVersion(-1),
pyMinorVersion(-1), pyMinorVersion(-1),
global(false), global(false),
showHelp(false) showHelp(false),
runModule(false)
{ {
args = getArgsList( cmdline ); args = getArgsList( cmdline );
@ -68,6 +69,13 @@ Options::Options(const std::string& cmdline) :
continue; continue;
} }
if (*it == "--module" || *it == "-m")
{
runModule = true;
it = args.erase(it);
continue;
}
std::smatch mres; std::smatch mres;
if (std::regex_match(*it, mres, versionRe)) if (std::regex_match(*it, mres, versionRe))
{ {

View File

@ -11,13 +11,15 @@ struct Options
int pyMinorVersion; int pyMinorVersion;
bool global; bool global;
bool showHelp; bool showHelp;
bool runModule;
std::vector<std::string> args; std::vector<std::string> args;
Options() : Options() :
pyMajorVersion(-1), pyMajorVersion(-1),
pyMinorVersion(-1), pyMinorVersion(-1),
global(true), global(true),
showHelp(false) showHelp(false),
runModule(false)
{} {}
Options(const std::string& cmdline); Options(const std::string& cmdline);

View File

@ -3,7 +3,7 @@
#define PYKDEXT_VERSION_MAJOR 2 #define PYKDEXT_VERSION_MAJOR 2
#define PYKDEXT_VERSION_MINOR 0 #define PYKDEXT_VERSION_MINOR 0
#define PYKDEXT_VERSION_SUBVERSION 0 #define PYKDEXT_VERSION_SUBVERSION 0
#define PYKDEXT_VERSION_BUILDNO 14 #define PYKDEXT_VERSION_BUILDNO 15
#define __VER_STR2__(x) #x #define __VER_STR2__(x) #x
#define __VER_STR1__(x) __VER_STR2__(x) #define __VER_STR1__(x) __VER_STR2__(x)

View File

@ -182,8 +182,9 @@ info(
CComQIPtr<IDebugControl> control = client; CComQIPtr<IDebugControl> control = client;
control->ControlledOutput( control->ControlledOutput(
DEBUG_OUTCTL_THIS_CLIENT, DEBUG_OUTCTL_AMBIENT_TEXT,
DEBUG_OUTPUT_NORMAL, DEBUG_OUTPUT_NORMAL,
"%s",
sstr.str().c_str() sstr.str().c_str()
); );
} }
@ -192,8 +193,9 @@ info(
CComQIPtr<IDebugControl> control = client; CComQIPtr<IDebugControl> control = client;
control->ControlledOutput( control->ControlledOutput(
DEBUG_OUTCTL_THIS_CLIENT, DEBUG_OUTCTL_AMBIENT_TEXT,
DEBUG_OUTPUT_ERROR, DEBUG_OUTPUT_ERROR,
"%s",
e.what() e.what()
); );
} }
@ -254,11 +256,13 @@ static const char printUsageMsg[] =
"\tOptions:\n" "\tOptions:\n"
"\t-g --global : run code in the common namespace\n" "\t-g --global : run code in the common namespace\n"
"\t-l --local : run code in the isolated namespace\n" "\t-l --local : run code in the isolated namespace\n"
"\t-m --module : run module as the __main__ module ( see the python command line option -m )\n"
"\n" "\n"
"\tcommand samples:\n" "\tcommand samples:\n"
"\t\"!py\" : run REPL\n" "\t\"!py\" : run REPL\n"
"\t\"!py --local\" : run REPL in the isolated namespace\n" "\t\"!py --local\" : run REPL in the isolated namespace\n"
"\t\"!py -g script.py 10 \"string\"\" : run script file with argument in the commom namespace\n" "\t\"!py -g script.py 10 \"string\"\" : run a script file with an argument in the commom namespace\n"
"\t\"!py -m module_name\" : run a named module as the __main__\n"
"\n" "\n"
"!pip [version] [args]\n" "!pip [version] [args]\n"
"\trun pip package manager\n" "\trun pip package manager\n"
@ -290,8 +294,9 @@ help(
CComQIPtr<IDebugControl> control = client; CComQIPtr<IDebugControl> control = client;
control->ControlledOutput( control->ControlledOutput(
DEBUG_OUTCTL_THIS_CLIENT, DEBUG_OUTCTL_AMBIENT_TEXT,
DEBUG_OUTPUT_NORMAL, DEBUG_OUTPUT_NORMAL,
"%s",
printUsageMsg printUsageMsg
); );
@ -331,13 +336,21 @@ py(
int majorVersion = opts.pyMajorVersion; int majorVersion = opts.pyMajorVersion;
int minorVersion = opts.pyMinorVersion; int minorVersion = opts.pyMinorVersion;
if ( opts.args.size() > 0 && majorVersion == -1 && minorVersion == -1 ) std::string scriptFileName;
if ( opts.args.size() > 0 && !opts.runModule )
{ {
std::ifstream scriptFile(opts.args[0]); scriptFileName = getScriptFileName(opts.args[0]);
if ( scriptFileName.empty() )
throw std::invalid_argument("script not found\n");
}
if ( !opts.runModule && majorVersion == -1 && minorVersion == -1 )
{
std::ifstream scriptFile(scriptFileName);
if ( scriptFile.is_open() ) if ( scriptFile.is_open() )
{ {
std::string firstline; std::string firstline;
std::getline(scriptFile, firstline); std::getline(scriptFile, firstline);
@ -358,7 +371,6 @@ py(
AutoInterpreter autoInterpreter(opts.global, majorVersion, minorVersion); AutoInterpreter autoInterpreter(opts.global, majorVersion, minorVersion);
//PyObjectRef mainName = IsPy3() ? PyUnicode_FromString("__main__") : PyString_FromString("__main__");
PyObjectRef mainMod = PyImport_ImportModule("__main__"); PyObjectRef mainMod = PyImport_ImportModule("__main__");
PyObjectRef globals = PyObject_GetAttrString(mainMod, "__dict__"); PyObjectRef globals = PyObject_GetAttrString(mainMod, "__dict__");
@ -381,8 +393,6 @@ py(
} }
else else
{ {
std::string scriptFileName = getScriptFileName(opts.args[0]);
if (IsPy3()) if (IsPy3())
{ {
std::wstring scriptFileNameW = _bstr_t(scriptFileName.c_str()); std::wstring scriptFileNameW = _bstr_t(scriptFileName.c_str());
@ -390,7 +400,10 @@ py(
// óñòàíàâèëèâàåì ïèòîíîâñêèå àðãóìåíòû // óñòàíàâèëèâàåì ïèòîíîâñêèå àðãóìåíòû
std::vector<std::wstring> argws(opts.args.size()); std::vector<std::wstring> argws(opts.args.size());
if ( !scriptFileNameW.empty() )
argws[0] = scriptFileNameW; argws[0] = scriptFileNameW;
else
argws[0] = L"";
for (size_t i = 1; i < opts.args.size(); ++i) for (size_t i = 1; i < opts.args.size(); ++i)
argws[i] = _bstr_t(opts.args[i].c_str()); argws[i] = _bstr_t(opts.args[i].c_str());
@ -401,23 +414,49 @@ py(
PySys_SetArgv_Py3((int)opts.args.size(), &pythonArgs[0]); PySys_SetArgv_Py3((int)opts.args.size(), &pythonArgs[0]);
if ( opts.runModule )
{
std::stringstream sstr;
sstr << "runpy.run_module(\"" << opts.args[0] << "\", run_name='__main__', alter_sys=True)" << std::endl;
PyObjectRef result;
result = PyRun_String("import runpy\n", Py_file_input, globals, globals);
result = PyRun_String(sstr.str().c_str(), Py_file_input, globals, globals);
}
else
{
FILE* fs = _Py_fopen(scriptFileName.c_str(), "r"); FILE* fs = _Py_fopen(scriptFileName.c_str(), "r");
if ( !fs ) if ( !fs )
throw std::invalid_argument("script not found\n"); throw std::invalid_argument("script not found\n");
PyObjectRef result = PyRun_File(fs, scriptFileName.c_str(), Py_file_input, globals, globals); PyObjectRef result = PyRun_File(fs, scriptFileName.c_str(), Py_file_input, globals, globals);
} }
}
else else
{ {
std::vector<char*> pythonArgs(opts.args.size()); std::vector<char*> pythonArgs(opts.args.size());
if ( !scriptFileName.empty() )
pythonArgs[0] = const_cast<char*>(scriptFileName.c_str()); pythonArgs[0] = const_cast<char*>(scriptFileName.c_str());
else
pythonArgs[0] = "";
for (size_t i = 1; i < opts.args.size(); ++i) for (size_t i = 1; i < opts.args.size(); ++i)
pythonArgs[i] = const_cast<char*>(opts.args[i].c_str()); pythonArgs[i] = const_cast<char*>(opts.args[i].c_str());
PySys_SetArgv((int)opts.args.size(), &pythonArgs[0]); PySys_SetArgv((int)opts.args.size(), &pythonArgs[0]);
if ( opts.runModule )
{
std::stringstream sstr;
sstr << "runpy.run_module('" << opts.args[0] << "', run_name='__main__', alter_sys=True)" << std::endl;
PyObjectRef result;
result = PyRun_String("import runpy\n", Py_file_input, globals, globals);
result = PyRun_String(sstr.str().c_str(), Py_file_input, globals, globals);
}
else
{
PyObjectRef pyfile = PyFile_FromString(const_cast<char*>(scriptFileName.c_str()), "r"); PyObjectRef pyfile = PyFile_FromString(const_cast<char*>(scriptFileName.c_str()), "r");
if (!pyfile) if (!pyfile)
throw std::invalid_argument("script not found\n"); throw std::invalid_argument("script not found\n");
@ -427,6 +466,7 @@ py(
PyObjectRef result = PyRun_File(fs, scriptFileName.c_str(), Py_file_input, globals, globals); PyObjectRef result = PyRun_File(fs, scriptFileName.c_str(), Py_file_input, globals, globals);
} }
} }
}
handleException(); handleException();
@ -438,8 +478,9 @@ py(
CComQIPtr<IDebugControl> control = client; CComQIPtr<IDebugControl> control = client;
control->ControlledOutput( control->ControlledOutput(
DEBUG_OUTCTL_AMBIENT_TEXT, //DEBUG_OUTCTL_ALL_CLIENTS, DEBUG_OUTCTL_AMBIENT_TEXT,
DEBUG_OUTPUT_ERROR, DEBUG_OUTPUT_ERROR,
"%s",
e.what() e.what()
); );
} }
@ -508,8 +549,9 @@ pip(
CComQIPtr<IDebugControl> control = client; CComQIPtr<IDebugControl> control = client;
control->ControlledOutput( control->ControlledOutput(
DEBUG_OUTCTL_AMBIENT_TEXT, //DEBUG_OUTCTL_ALL_CLIENTS, DEBUG_OUTCTL_AMBIENT_TEXT,
DEBUG_OUTPUT_ERROR, DEBUG_OUTPUT_ERROR,
"%s",
e.what() e.what()
); );
} }
@ -519,10 +561,8 @@ pip(
return S_OK; return S_OK;
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
void handleException() void handleException()
{ {
// îøèáêà â ñêðèïòå // îøèáêà â ñêðèïòå
@ -602,87 +642,50 @@ void getPathList( std::list<std::string> &pathStringLst)
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
std::string findScriptPath(const std::string &fullFileName) std::string getScriptFileName(const std::string &scriptName)
{ {
std::list<std::string> pathList; char* ext = NULL;
getPathList(pathList);
for ( auto path : pathList ) DWORD searchResult =
{ SearchPathA(
DWORD bufSize = SearchPathA( NULL,
path.c_str(), scriptName.c_str(),
fullFileName.c_str(),
NULL, NULL,
0, 0,
NULL, NULL,
NULL); NULL );
if (bufSize > 0) if ( searchResult == 0 )
{ {
bufSize += 1; ext = ".py";
std::vector<char> fullFileNameCStr(bufSize);
char *partFileNameCStr = NULL;
bufSize = SearchPathA( searchResult =
path.c_str(), SearchPathA(
fullFileName.c_str(),
NULL, NULL,
bufSize, scriptName.c_str(),
&fullFileNameCStr[0], ext,
&partFileNameCStr); 0,
NULL,
NULL );
DWORD fileAttr = GetFileAttributesA(&fullFileNameCStr[0]); if ( searchResult == 0 )
if ((fileAttr & FILE_ATTRIBUTE_DIRECTORY) == 0)
return std::string(&fullFileNameCStr[0]);
}
}
std::stringstream sstr;
sstr << "script not found" << std::endl << std::endl;
if ( pathList.empty() )
{ {
sstr << "Path list: empty" << std::endl; return "";
}
else
{
sstr << "Path list:" << std::endl;
for ( auto path : pathList )
{
sstr << '\t' << path << std::endl;
} }
} }
throw std::invalid_argument(sstr.str().c_str()); std::vector<char> pathBuffer(searchResult);
}
/////////////////////////////////////////////////////////////////////////////// searchResult =
SearchPathA(
NULL,
scriptName.c_str(),
ext,
pathBuffer.size(),
&pathBuffer.front(),
NULL );
std::string getScriptFileName(const std::string &scriptName) return std::string(&pathBuffer.front(), searchResult);
{
if ( scriptName.find('\\') != std::string::npos || scriptName.find('/') != std::string::npos )
{
if (GetFileAttributesA(scriptName.c_str()) != INVALID_FILE_ATTRIBUTES)
return scriptName;
std::stringstream sstr;
sstr << "File \'" << scriptName << "\' not found" << std::endl;
throw std::invalid_argument(sstr.str().c_str());
}
try {
return findScriptPath(scriptName);
}
catch( std::invalid_argument& )
{}
return findScriptPath(scriptName + ".py");
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -735,8 +738,6 @@ void getPythonVersion(int& majorVersion, int& minorVersion)
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
void getDefaultPythonVersion(int& majorVersion, int& minorVersion) void getDefaultPythonVersion(int& majorVersion, int& minorVersion)
{ {
std::list<InterpreterDesc> interpreterList = getInstalledInterpreter(); std::list<InterpreterDesc> interpreterList = getInstalledInterpreter();