Python?

Posted by Ixokai on Thu 24 Apr 2003 07:54 AM — 29 posts, 101,721 views.

USA #0
How much begging, prodding, crying and worshipping would it take to get Python added to the list of supported scripting languages?

I don't know what interface you're using, but if its the ActiveX/Windows Scripting Host, then Python interfaces to it just fine with the win32all package...

Plllease? :)
Australia Forum Administrator #1
I tried that - the appropriate changes are in the code, however it didn't work. Some bizarre interface problem. Unless they have fixed up the Python script interface I can't do it.
Australia Forum Administrator #2
See my earlier attempts
Amended on Thu 24 Apr 2003 08:04 AM by Nick Gammon
Australia Forum Administrator #3
Don't get me wrong - I would if I could - I had a demo bit of source that reproduces the fault that I sent to WillFa (see earlier posts).

If I can make that work, or if someone can tell me what I am doing wrong, I'll put it in. You are welcome to a copy.
USA #4
Do you mean:

m_IActiveScript->AddNamedItem (L"world",
SCRIPTITEM_ISVISIBLE | SCRIPTITEM_ISSOURCE);

in reference to the demo, or did you send a different bit? Since you said it crashed even without the above, I was wondering if I missed something.

Can you provide details on what sort of crash? What error message; access violation, etc? I might be able to do some digging for you.
Australia Forum Administrator #5
Yes, that is what I meant.

This is what I had last time:


// pScriptEngine = new CScriptEngine (this, "vbscript"); // this works
pScriptEngine = new CScriptEngine (this, "python"); // this doesn't



If you change the language to "vbscript" then it works and displays the message box. Otherwise you get the message about the ESP value. If you comment out the line that adds the "world" variable to the script engine it crashes anyway (scripttengine.cpp line 210).

The files are largely unchanged from the MUSHclient version, in the stdafx.h file is a define:

#define CMUSHclientDoc CScripttestDoc

This is so that the files think it is using a CMUSHclientDoc document.

If you can get this to work (changing compile options or something?) then I should be able to make MUSHclient work too.

Continued in next message ...
Amended on Thu 24 Apr 2003 11:20 AM by Nick Gammon
Australia Forum Administrator #6

I got this error:

The source is at pythontest.zip - 28 Kb - just unzip, build, run and select View menu -> Test.

Amended on Thu 24 Apr 2003 11:17 AM by Nick Gammon
Australia Forum Administrator #7
I don't know about this "declared with a different calling convention" bit - the exact same code works if you change the language to Vbscript, Jscript, or Perlscript.
Australia Forum Administrator #8
I downloaded Python today to make sure I had the latest version - it was 2.2.2 build 224.
Australia Forum Administrator #9
Get the example program to work reliably and you can have Python this week. :)
USA #10
Hmm. Did a bit of hunting and found that most things dealing with Python and 'calling convention' involve the facts that Python and C++ do not automatically use the same method. While my brief search didn't uncover specifics, one possibility is that Python uses the Pascal convention and in that case the difference involves stack management. The method C++ uses is 'caller clears the stack', while the pascal method employs 'the program called clears the stack'. This is only a guess though, but it suggests that a key process is either being done by both ends or by neither end and this would definitely cause a crash.

Wish I knew if this was the case or how to actually fix it though.. I imagine that changing the calling method to properly support Python could break everything else, so there has to be some sort of better solution. :p
Australia Forum Administrator #11
After making a subtle change to the way scripting was instantiated - after spending hours reading web pages - I now have Python active (nothing to do with calling conventions BTW). However after a script error in "immediate" mode it stops processing further scripts. I am investigating this.

Meanwhile, as a newbie to Python, perhaps a few examples of the sort of thing you would like to try would help me to test it.
Australia Forum Administrator #12
Like, for instance, how do I cast types?

Here is a simple example. In the plugins I echo the description by getting plugininfo, which is a variant, and displaying it with Note, which takes a string. Like this:

/world.Note (world.GetPluginInfo (world.GetPluginID, 3))

This gives a type mismatch.
Australia Forum Administrator #13
Hmm - I withdraw that comment slightly - the error was when not running as a plugin, so it probably got an empty variant.

My experimenting seems to indicate that str(x) casts x to a string.

What about the format for constants? See this page:

http://www.gammon.com.au/scripts/function.php?action=errors

Can you suggest the syntax (for one line, I can work out the rest) for the constant list? This is auto-generated by the page anyway, I just need the format to do it.
Australia Forum Administrator #14
What about iterating through an array - a variant array? See this page:

http://www.gammon.com.au/scripts/function.php?name=GetInternalCommandsList

How would you do that in Python?
Australia Forum Administrator #15
Never mind, I seem to have worked that out.


x = world.GetInternalCommandsList

#
# show length of array
#

world.note (len (x))

#
# interate through array
#

for cmd in world.GetInternalCommandsList: world.Note (cmd)

Amended on Fri 25 Apr 2003 03:21 AM by Nick Gammon
USA #16
*laugh* Mark, you answer your own questions faster then I can even think about trying to pretend to answer them. The only question I see that you don't appear to have answered yourself is the constants list. There is no conception of 'constant' in python, although I can build a class to do it for you rather easily. Its unnessecary though, really... Just spit out a list of variables.

eOK = 0 # No Error
eWorldOpen = 30001 # The world is already open.

..etc... that's it.. Python is very not-force-you-to-obey-the-rules. Python programmers do what they're supposed to without it. :)
USA #17
One comment: is GetInternalCommandList a function or the /actual/ array? If its a function you need ()'s at the end..

x = world.GetInternalCommandList()

world.note(len(x))

for cmd in world.GetInternalCommandList():
world.note(cmd)
Australia Forum Administrator #18
I misspelt it, it is GetInternalCommandsList, not GetInternalCommandList, however my example worked apart from that.

Adding the brackets stops it working, however GetInternalCommandsList is a function returning a variant array, not an actual array.

for cmd in world.GetInternalCommandsList: world.Note (cmd)

If I add the brackets I get the error "'tuple' object is not callable".


The only remaining problem seems to be that the script engine doesn't seem to support "global" members. so I need to explicitly use world.X whereas in the other languages I can omit "world." which I am starting to do in recent examples. Unless you know a way of working around that, eg. something like the old Pascal syntax:

with world do
Note ("aha")
end

instead of world.Note ("aha")
Australia Forum Administrator #19
OK, check out Script error codes - the Python list is now there.
USA #20
That's odd. Python is seeing that GetInternalCommandsList as an array. A tuple is an array which can't change size, basically. Interesting.

You can't do that whole "with" type of thing in Pyhton. If world was a module, you might be able to:

from world import *

But i highly doubt that'll work in this situation. You'll probably havae to 'world.Note' etc. Its pythonic.
Australia Forum Administrator #21
In case someone is searching the Net for this one day, here is how I fixed it.

The error message was:

"The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention."

Module: chkesp.c line 42

The solution was to change the CoCreateInstance call slightly. No change was made to calling conventions.



Old, did not work:


IActiveScript       * m_IActiveScript;

::CoCreateInstance(clsid,  
    NULL, 
    CLSCTX_ALL, 
    IID_IUnknown,
    reinterpret_cast<void**>(&m_IActiveScript));




New, this works:


IActiveScript       * m_IActiveScript;

::CoCreateInstance(clsid,  
    NULL, 
    CLSCTX_ALL, 
    IID_IActiveScript,
    reinterpret_cast<void**>(&m_IActiveScript));


Amended on Sat 26 Apr 2003 04:13 AM by Nick Gammon
USA #22
The only way I can think of to achieve that global members issue, is for you to do:

import __builtin__

__builtin__.Note = world.Note

... for each of the functions. A short cut that may or may not work is:

__builtin__.__dict__.update(world.__dict__)

If 'world' doesn't have a dictionary, this won't work... I dont know how these activex objects work in python internally. If it does work it'll copy world's dictionary into the global namespace. __dict__ is an associative array that represents a perticular namespace, essentially.

I *personally* think this is a bad idea and that everything should be 'world.Note' etc... Standard pythonism is 'explicit is better then implicit' :)
Australia Forum Administrator #23
Quote:

import __builtin__

__builtin__.Note = world.Note



This idea seems to work, however I agree there isn't much point, especially if you need to only do one line.


world.Note ("hello")


seems shorter to me than:


import __builtin__
__builtin__.Note = world.Note
Note ("hello")


I only asked because I was starting to get used to the way VBscript lets me get away without typing "world." all the time.

I am about ready to release the Python-compatible version, if you look at the scripting functions pages you see there is now an entry for the Python example for each script function.

Australia Forum Administrator #24
Hey, this is pretty cute. In Python I can do this:

/world.note (str(world.GetInternalCommandsList))

This gives me:


(u'ActivityList', u'ActivityToolbar', u'AltDownArrow', u'AltUpArrow', u'AlwaysOnTop', u'AutoSay', u'BookmarkSelection', u'BugReports', u'ClearCommandHistory', u'ClearOutput', u'CloseAllNotepadWindows', u'ColourPicker', u'CommandEnd', u'CommandHistory', u'CommandHome', u'ConfigureAliases', u'ConfigureAutosay', u'ConfigureColours', u'ConfigureCommands', u'ConfigureCustomColours', u'ConfigureHighlighting', u'ConfigureKeypad', u'ConfigureLogging', u'ConfigureMacros', u'ConfigureMudaddress', u'ConfigureMxpPueblo', u'ConfigureNameAndPassword', u'ConfigureNotes', u'ConfigureOutput', u'ConfigurePasteToWorld', u'ConfigurePrinting', u'ConfigureScripting', u'ConfigureSendFile', u'ConfigureTimers', u'ConfigureTriggers', u'ConfigureVariables', u'Connect', u'ConnectToAllOpenWorlds', u'ConnectToWorldsInStartupList', u'ContextHelp', u'Copy', u'CopyAsHTML', u'CtrlN', u'CtrlP', u'CtrlZ', u'Cut', u'DebugIncomingPackets', u'DebugWorldInput', u'DiscardQueuedCommands', u'Disconnect', u'DoMapperComment', u'DoMapperSpecial', u'East', u'EditScriptFile', u'End', u'Examine', u'Find', u'FindAgain', u'FlipToNotepad', u'Forum', u'FreezeOutput', u'FullScreenMode', u'FunctionsWebPage', u'GettingStarted', u'GenerateCharacterName', u'GlobalPreferences', u'GoToBookmark', u'GoToLine', u'GoToURL', u'Help', u'HelpContents', u'Immediate', u'Import', u'Info', u'InfoBar', u'InputGlobalChange', u'Keypad0', u'Keypad1', u'Keypad2', u'Keypad3', u'Keypad4', u'Keypad5', u'Keypad6', u'Keypad7', u'Keypad8', u'Keypad9', u'KeypadDash', u'KeypadDot', u'KeypadPlus', u'KeypadSlash', u'KeypadStar', u'KeysEscape', u'KeysTab', u'LineDown', u'LineUp', u'LogSession', u'Look', u'MacroCtrlF10', u'MacroCtrlF11', u'MacroCtrlF12', u'MacroCtrlF2', u'MacroCtrlF3', u'MacroCtrlF5', u'MacroCtrlF7', u'MacroCtrlF8', u'MacroCtrlF9', u'MacroF10', u'MacroF11', u'MacroF12', u'MacroF2', u'MacroF3', u'MacroF4', u'MacroF5', u'MacroF7', u'MacroF8', u'MacroF9', u'MacroShiftF10', u'MacroShiftF11', u'MacroShiftF12', u'MacroShiftF2', u'MacroShiftF3', u'MacroShiftF4', u'MacroShiftF5', u'MacroShiftF6', u'MacroShiftF7', u'MacroShiftF8', u'MacroShiftF9', u'Mapper', u'MinimiseProgram', u'Minimize', u'MudLists', u'NextCommand', u'NextPane', u'NoCommandEcho', u'North', u'NotesWorkArea', u'OpenWorldsInStartupList', u'PageDown', u'Pageup', u'Paste', u'Paste', u'PasteFile', u'PasteToMush', u'PluginWizard', u'Plugins', u'Preferences', u'PreviousCommand', u'Print', u'QuickConnect', u'Quit', u'RecallText', u'ReconnectOnDisconnect', u'Register', u'ReloadDefaults', u'ReloadNamesFile', u'ReloadScriptFile', u'RepeatLastCommand', u'RepeatLastWord', u'ResetAllTimers', u'ResetToolbars', u'Save', u'SelectAll', u'SendToAllWorlds', u'South', u'SpellCheck', u'Start', u'StopSoundPlaying', u'Take', u'TestCommand', u'TestTrigger', u'TextAttributes', u'TipOfTheDay', u'Trace', u'Undo', u'Up', u'WebPage', u'West', u'Whisper', u'WindowsSocketInformation', u'WrapOutput')


I presume the "u" is for Unicode.
Amended on Fri 25 Apr 2003 11:55 PM by Nick Gammon
USA #25
Yep. u'' is a unicode string. r'' is a raw-string... They're used for regexps or paths, so you don't have to constantly escape slashes. Etc, etc. :)

In reference to the builtin thing, I was confused and thought you wanted to do this in some global-default sort of way.
Greece #26
Quote:
*laugh* Mark, you answer your own questions faster then I can even think about trying to pretend to answer them.

Who's Mark? :p
USA #27
Er. Me in a stupid-moment. Mark is Nick. Nick is Mark. Come on, I can rename whoever I want.
Greece #28
Just kidding :p