as the title states, I know runpy can run a module's code w/o importing it,
but what I'm trying to do is send the module object to a... function supplied by my interface which is directly called by the module.

what I'm talking about is:

my interface provides these functions for it's scripts:
ugeImportType()
ugeExportType()

via:
run_module( UGE_Script, init_globals=COMMON.dict, )# run_name=??)

and those functions should be the first things called in the script.

what those functions do is set a global collection with the:
- python module object of the imported script
- filetypes the script works with
- UGE-libraries used by the script

NOTE:
in a UGE-Script, it's best to avoid using the import statement as everything needed is supplied for handling file data.
UGE, or currently, UMC has it's own model, file, and data interfaces, and you're not expected to know how to work them via the backend, so a very simple frontend is supplied which can do more than current python extensions up to the point of importing and exporting 3D models.

Well, let's take an example. We have a module file foo.py containing the code

print('Hello from foo.py')

Can you tell us precisely which statements should be executed and in which order ?

Edited 1 Year Ago by Gribouillis

ok... to start off:

API.py (test scripts):

from data import COMMON

for script in scripts: # scripts directory
    UGE_Script = script
    run_module( 'scripts/%s.py'%UGE_Script, init_globals=COMMON.__dict__, )# run_name=??)

scripts/script.py (this will set UGE_Script with 'script')

ugeImportType(UGE_MODEL_SCRIPT)
ugeImportFormats([ ('test',['tst','test']), ])

def ugeImportModel(fileType,Commands):
    pass

^that's all you need to have a working script

but now to actually run the script I need to have the module object, which should be added by ugeImportType()

how can I do that??

Edited 1 Year Ago by Tcll

I don't see where you need the module object. I don't think run_module() actually uses a module object. It uses the module mechanism to locate the file. Instead of run_module(), why not create a module object and use an exec statement ?

import types
mod = types.ModuleType('script')
mod.__dict__.update(COMMON.__dict__)
with open('script.py') as ifh:
    src = ifh.read()
exec(src, mod.__dict__)

Edited 1 Year Ago by Gribouillis

ah ok, that'll be perfect :)
thanks

I don't see where you need the module object.

I didn't really know how to explain that in-depth as the interface for that is a little complex, however, I can mention the variable that holds the module object in COMMON.py

global _UGE_Scripts; _UGE_Scripts = {
    UGE_MODEL_SCRIPT: { 'I':{},
                        'O':{} },
    # I'll leave this... might update FORMAT later (SES can suport it w/o messing anything up)
    UGE_ANIMATION_SCRIPT: { 'I':{},
                            'O':{} },
    UGE_IMAGE_SCRIPT: { 'I':{},
                        'O':{} },
    UGE_PALLET_SCRIPT: { 'I':{},
                         'O':{} },
    UGE_COMPRESSION_SCRIPT: { 'I':{},
                              'O':{} }
    }

# for script in _UGE_Scripts[ type ][ 'I'/'O' ]:
#     module, formats, libraries = _UGE_Scripts[ type ][ 'I'/'O' ][ script ]

this is updated with the modules via ugeImportType() and ugeExportType(), and is shared between any action that calls upon a script:
- importing/exporting a model (GUI/KBd action)
- ugeSetImageData()/ugeGetImageData()
- ugeSetImagePallet()/ugeGetImagePallet()
- ugeDecompress()/ugeCompress()

Edited 1 Year Ago by Tcll

just 1 Q about your code... will this work as expected??

eg:

import types
mod = types.ModuleType('script')
mod.__dict__.update(COMMON.__dict__)
with open('script.py') as ifh:
    src = ifh.read()
exec(src, mod.__dict__)

#on import-model event: (Ctrl+I)
mod.ugeImportModel( ... )

I havn't played around with exec too much, so I don't know alot about it :P

also, this'll be faster for UMC's interpreter:

exec src in mod.__dict__ # no extra objects created

I don't intend to use Python3 unless PyOpenGL will ever run faster on it.
(and no, I don't intend to use wrapper interfaces such as pyglet which only provide half the functionality)

Edited 1 Year Ago by Tcll

Yes, mod.ugeImportModel( ... ) will work as expected after the exec statement. If you stick with python 2, add an encoding string in your module, it may ease things (the # -*-coding: utf8-*- thing at the top).

Edited 1 Year Ago by Gribouillis

hey grib, need a small hand, now that I've finally gotten this far:

def __ReloadScripts(): #reload any changes made to the existing scripts
    global _UGE_Script,_UGE_Module,_GatherScripts
    bad = []
    for script in [m for m in os.listdir('scripts') if m.endswith('.py')]: #only get .py files
        _UGE_Script = script.replace('.py','')
        if _UGE_Script in sys.modules: reload( sys.modules[_UGE_Script] ) # remove the outdated code
        sys.modules[_UGE_Script] = __MOD(_UGE_Script) # set the namespace
        sys.modules[_UGE_Script].__dict__.update(sys.modules['data.COMMON'].__dict__) # update with COMMON
        with open('scripts/%s'%script) as ifh: src = ifh.read() # get the script's code
        _UGE_Module = sys.modules[_UGE_Script] # update the current namespace in COMMON
        try:
            _GatherScripts = False; exec src in sys.modules[_UGE_Script].__dict__ # fill the namespace
            _GatherScripts = True; exec src in sys.modules[_UGE_Script].__dict__ # add to the collection
        except: bad.append(script) # execution failed likely because of a syntax error
    return bad

this code is located in COMMON, which is why I'm using sys.modules['data.COMMON'].__dict__

it works properly on initialization, but on reload (when (just before) importing or exporting a file), this happens:

Traceback (most recent call last):
  File "Z:\home\tcll\sync\copy\UMC_v3.0a\API.py", line 40, in run
    VIEWER.Init()
  File "Z:\home\tcll\sync\copy\UMC_v3.0a\data\VIEWER.py", line 925, in Init
    __GUI.__Release(e.button,x,y)
  File "Z:\home\tcll\sync\copy\UMC_v3.0a\data\GUI.py", line 2084, in __Release
    [W.releaseL,W.releaseM,W.releaseR,W.scrollU,W.scrollD][b-1](); _recompile()
  File "Z:\home\tcll\sync\copy\UMC_v3.0a\data\GUI.py", line 408, in releaseL
    this.action(this)
  File "Z:\home\tcll\sync\copy\UMC_v3.0a\data\GUI.py", line 1530, in action_Import
    def action_Import(this,button): this.Import(button); this.UI.update()
  File "Z:\home\tcll\sync\copy\UMC_v3.0a\data\GUI.py", line 1407, in Import
    VIEWER._ImportModel(this.MITE.Text,this.Iscript)
  File "Z:\home\tcll\sync\copy\UMC_v3.0a\data\VIEWER.py", line 674, in _ImportModel
    COMMON.__ReloadScripts() #check for valid changes to the scripts
  File "Z:\home\tcll\sync\copy\UMC_v3.0a\data\COMMON.py", line 40, in __ReloadScripts
    if _UGE_Script in sys.modules: reload( sys.modules[_UGE_Script] ) # remove the outdated code
ImportError: reload(): module data.COMMON not in sys.modules

yea... quite a conundrum... heh

Edited 1 Year Ago by Tcll

Hey Tcll, here is a small experiment which may explain what happens

>>> import sys
>>> import anytree
>>> anytree.__name__
'anytree'
>>> anytree.__name__ = 'foobarbazqux'
>>> reload(anytree)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: reload(): module foobarbazqux not in sys.modules

reload() found the name of the module to reload by looking its __name__ attribute but this name was changed by another operation similar to your __dict__.update() above. You could perhaps exclude special attributes from the dict update. Another attribute to keep could be __path__.

you know... shortly after I asked, I has a slight suspicion it had to do with __name__. XD

thanks for clarifying :)

here's the update that works properly:

def __ReloadScripts(): #reload any changes made to the existing scripts
    global _UGE_Script,_UGE_Module,_GatherScripts
    bad = []
    for script in [m for m in os.listdir('scripts') if m.endswith('.py')]: #only get .py files
        _GatherScripts = False; _UGE_Script = script.replace('.py','')
        try:
            if _UGE_Script in sys.modules:
                reload( sys.modules[_UGE_Script] )
                #try: reload( sys.modules[_UGE_Script] )
                #except NameError: pass # script loads
            else:
                sys.modules[_UGE_Script] = __MOD(_UGE_Script) # set the namespace
                sys.modules[_UGE_Script].__dict__.update(sys.modules['data.COMMON'].__dict__) # update with COMMON
                with open('scripts/%s'%script) as ifh: src = ifh.read() # get the script's code
                _UGE_Module = sys.modules[_UGE_Script] # update the current namespace in COMMON

                exec src in sys.modules[_UGE_Script].__dict__ # fill the namespace
                _GatherScripts = True; exec src in sys.modules[_UGE_Script].__dict__ # add to the collection
        except: bad.append(script) # execution failed likely because of a syntax error or name error
        sys.modules[_UGE_Script].__name__ = _UGE_Script
    return bad

Edited 1 Year Ago by Tcll

This article has been dead for over six months. Start a new discussion instead.