Check-in [5d85eb1bdd]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Initial implementation. Creation of a new instance does not work.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256:5d85eb1bdd0e654a76e4247b9f43fcec636661d1ea5403f88bf49ec1a4211cbd
User & Date: gwlester 2018-02-02 23:49:14
Context
2018-02-03
04:37
Got instance creation working! check-in: c45f0d9d7c user: gwlester tags: trunk
2018-02-02
23:49
Initial implementation. Creation of a new instance does not work. check-in: 5d85eb1bdd user: gwlester tags: trunk
16:13
Basic housekeeping files -- no code. check-in: c80c04cad8 user: gwlester tags: trunk
Changes

Added src/pyman.tcl.































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package require tclpy
package require oo::util

package provide pyman 0.5

oo::class create ::pyman {
    variable pythonObject

    constructor {args} {
        variable pythonObject

        set className [info object class [self]]
        if {$className eq "::pyman"} {
            throw [list PYMAN LOOKUP SUBCOMMAND] {unknown subcommand must be: import or addPath}
        }

        set tclModuleName [join [lrange [split $className {:}] 0 end-2] {:}]
        set pythonModuleName [set ${tclModuleName}::pythonModuleName]
        set pythonClassName [lindex [split $className {:}] end]
        set pythonObject [string map {{::} {_}} [self]]

        ##
        ## Not sure about the line below!!
        ##
        py eval "$pythonObject = $pythonModuleName.${pythonClassName}([join $args ,])"
    }

    classmethod import {args} {
        switch -exact -- [llength $args] {
            1   {
                ##
                ## Just a moduleName
                ##
                set moduleName [lindex $args 0]
                set namespaceName [format {::pyman::%s} $moduleName]
            }
            3 {
                ##
                ## We have -namespace namespaceName moudleName
                ##
                if {[lindex $args 0] ne "-namespace"} {
                    throw [list PYMAN BADIMP $args] "Bad usage must be: pyman import ?-namespace namespaceName? moduleName"
                }
                set namespaceName [lindex $args 1]
                set moduleName [lindex $args 2]
            }
            default {
                ##
                ## Illegal usage
                ##
                throw [list PYMAN BADIMP $args] "Bad usage must be: pyman import ?-namespace namespaceName? moduleName"
            }
        }

        ##
        ## Format for message bodies
        ##
        set methodBodyFmt {
            variable pythonObject

            py call $pythonObject.%1$s {*}$args
        }

        ##
        ## Have python import the module
        ##
        py import $moduleName

        ##
        ## Create the Tcl namespace that maps to the imported module
        ##
        namespace eval $namespaceName {}
        set ${namespaceName}::pythonModuleName $moduleName

        ##
        ## Create the inspection macro and look at the contents of the module
        ##
        py eval "pyman.inspect = lambda : inspect.getmembers($moduleName)"
        foreach moduleItem [py call pyman.inspect] {
            lassign $moduleItem name type
            switch -glob -- $type {
                {<class *} {
                    ##
                    ## Define the class
                    ##
                    set className [format {%s::%s} [string trimright $namespaceName] $name]
                    ::oo::class create $className {superclass ::pyman}

                    ##
                    ## Remove unwanted class methods
                    ##
                    #::oo::define $className deletemethod addPath
                    #::oo::define $className deletemethod import

                    ##
                    ## Introspect to see what methods exists and add them in
                    ##
                    py eval "pyman.getMethods = lambda : inspect.getmembers($moduleName.$name)"
                    foreach classItem [py call pyman.getMethods] {
                        lassign $classItem methodName methodInfo
                        if {[string match {<unbound method *} $methodInfo] && $methodName ne "__init__"} {
                            ::oo::define $className method $methodName args [format $methodBodyFmt $methodName]
                        }
                    }
                }
                {<function *} {
                    ##
                    ## Define the wrapper procedure
                    ##
                    {*}[format {proc %1$s::%3$s {args} {py call %2$s.%3$s {*}$args}} $namespaceName $moduleName $name]
                }
            }
        }
    }

    classmethod addPath {pathName} {
        py eval "sys.path.append('$pathName')"
    }

}

py import inspect
py import sys
py import os
py import types
py eval {from types import ModuleType}
py eval {pyman = ModuleType('pyman')}

Added tests/example.py.

































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
"""Sample file to serve as the basis for inspect examples.
"""

def module_level_function(arg1, arg2='default', *args, **kwargs):
    """This function is declared in the module."""
    local_variable = arg1
    return

class A(object):
    """The A class."""
    def __init__(self, name):
        self.name = name

    def get_name(self):
        "Returns the name of the instance."
        return self.name

instance_of_a = A('sample_instance')

class B(A):
    """This is the B class.
    It is derived from A.
    """

    # This method is not part of A.
    def do_something(self):
        """Does some work"""
        pass

    def get_name(self):
        "Overrides version from A"
        return 'B(' + self.name + ')'