Check-in [2059d531f3]

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

Overview
Comment:Implemented Feature Request [ff08074318] -- provide access to class attributes.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256:2059d531f3c56f6fa2cb7a3053ec4fbfece2a22001f3a8b97a4ab5fb08ac1e91
User & Date: gwlester 2018-02-04 07:24:13
References
2018-02-04
07:25 Fixed ticket [ff08074318]: Need access to class attributes. plus 4 other changes artifact: 14b77adfc9 user: gwlester
Context
2018-02-05
05:26
Reimplement _attributes. Start example. check-in: 7dbfdf9c42 user: gwlester tags: trunk
2018-02-04
07:24
Implemented Feature Request [ff08074318] -- provide access to class attributes. check-in: 2059d531f3 user: gwlester tags: trunk
2018-02-03
18:11
Fixed ticket [0275a61338] -- pyman import failing on picamera module. Changed import to ignore private and magic functions/methods. check-in: ee90660103 user: gwlester tags: trunk, Release_0.5.1
Changes

Changes to src/pyman.tcl.

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
...
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
        append getModuleInfoFmt "\n\t" {for name, data in inspect.getmembers(%1$s):}
        append getModuleInfoFmt "\n\t\t" {temp = []}
        append getModuleInfoFmt "\n\t\t" {temp.append(name)}
        append getModuleInfoFmt "\n\t\t" {temp.append(repr(data))}
        append getModuleInfoFmt "\n\t\t" {results.append(temp)}
        append getModuleInfoFmt "\n\t" {return results}










        py eval [format $getModuleInfoFmt $moduleName]
        foreach moduleItem [py call pymanInspect] {
            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
................................................................................
            }
        }
    }

    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')}







>
>
>
>
>
>
>
>
>









|
>

>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




>







 







|








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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
...
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
        append getModuleInfoFmt "\n\t" {for name, data in inspect.getmembers(%1$s):}
        append getModuleInfoFmt "\n\t\t" {temp = []}
        append getModuleInfoFmt "\n\t\t" {temp.append(name)}
        append getModuleInfoFmt "\n\t\t" {temp.append(repr(data))}
        append getModuleInfoFmt "\n\t\t" {results.append(temp)}
        append getModuleInfoFmt "\n\t" {return results}

        set pymanGetAttributesFmt {def pymanGetAttributes():}
        append pymanGetAttributesFmt "\n\t" {results = []}
        append pymanGetAttributesFmt "\n\t" {for name, data in inspect.getmembers(%1$s.%2$s, lambda a:not(inspect.isroutine(a))):}
        append pymanGetAttributesFmt "\n\t\t" {temp = []}
        append pymanGetAttributesFmt "\n\t\t" {temp.append(name)}
        append pymanGetAttributesFmt "\n\t\t" {temp.append(repr(data))}
        append pymanGetAttributesFmt "\n\t\t" {results.append(temp)}
        append pymanGetAttributesFmt "\n\t" {return results}

        py eval [format $getModuleInfoFmt $moduleName]
        foreach moduleItem [py call pymanInspect] {
            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

                        self method init {attributes} {
                            variable Attributes

                            dict set Attributes list {}
                            dict set Attributes constants {}
                            dict set Attributes properties {}
                            foreach item $attributes {
                                lassign $item name value

                                if {[string index $name 0] eq "_"} {
                                    ##
                                    ## Skip private and magic attributes
                                    ##
                                    continue
                                }

                                if {[string match {<property object at *} $value]} {
                                    ##
                                    ## Property that we can read/set
                                    ##
                                    dict set Attributes type $name property
                                    dict lappend Attributes properties $name
                                } elseif {[string match {<*} $value]} {
                                    ##
                                    ## Subobject Constant
                                    ##
                                    dict set Attributes type $name constant
                                    dict set Attributes constants $name type subobject
                                } elseif {[string equal -length 4 $value {set([*} ]} {
                                    ##
                                    ## Enumeration Constant
                                    ##
                                    dict set Attributes type $name constant
                                    dict set Attributes constants $name type enum
                                    set enumList {}
                                    foreach item [split [string range $value 5 end-2] ","] {
                                        lappend enumList [string range [string trim $item] 2 end-1]
                                    }
                                    dict set Attributes constants $name value $enumList
                                } elseif {[string match {{*}} $value]} {
                                    ##
                                    ## Symbol Value Enumeration Constants
                                    ##
                                    dict set Attributes type $name constant
                                    dict set Attributes constants $name type symbolics
                                    foreach item [split [string range $value 1 end-1] ","] {
                                        lassign [split $item ":"] symbol itemValue
                                        set symbol [string range [string trim $symbol] 2 end-1]
                                        set itemValue [string trim $itemValue]
                                        dict set Attributes constants $name value $symbol $itemValue
                                        dict set Attributes constants $name symbol $value $symbol
                                    }
                                } else {
                                    ##
                                    ## Simple Constant Value
                                    ##
                                    dict set Attributes type $name constant
                                    dict set Attributes constants $name type simple
                                    dict set Attributes constants $name value $value
                                }
                            }
                            dict set Attributes list [lsort -dictionary [dict get $Attributes list]]

                            ::oo::objdefine [self] deletemethod init
                        }

                        method _attributes {{pattern {*}}} {
                            classvariable Attributes

                            return [dict get $Attributes list]
                        }

                        method _getAttribute {attribute} {
                            classvariable Attributes
                            variable pythonObject

                            if {![dict exists $Attributes type $attribute]} {
                                throw [list PYMAN UNKATTR $attribute] "unknown attribute '$attribute'"
                            }
                            switch -exact [dict get $Attributes type $attribute] {
                                constant {
                                    if {[dict get $Attributes constants $attribute type] eq "subobject"} {
                                        set pymanSetAttrFmt {def pymanGetAttr():}
                                        append pymanSetAttrFmt "\n\t" {return %1$s.%2$s}
                                        py eval [format $pymanSetAttrFmt $pythonObject $attribute]
                                        set result [py call pymanGetAttr]
                                    } else {
                                        set result [dict get $Attributes constants $attribute value]
                                    }
                                }
                                property {
                                    set pymanSetAttrFmt {def pymanGetAttr():}
                                    append pymanSetAttrFmt "\n\t" {return %1$s.%2$s}
                                    py eval [format $pymanSetAttrFmt $pythonObject $attribute]
                                    set result [py call pymanGetAttr]
                                }
                            }
                            return $result
                        }

                        method _setAttribute {attribute value} {
                            classvariable Attributes
                            variable pythonObject

                            if {![dict exists $Attributes type $attribute]} {
                                throw [list PYMAN UNKATTR $attribute] "unknown attribute '$attribute'"
                            }
                            switch -exact [dict get $Attributes type $attribute] {
                                constant {
                                    throw [list PYMAN SETCONST $attribute] "can not set constant attribute '$attribute'"
                                }
                                property {
                                    set pymanSetAttrFmt {def pymanSetAttr(newValue):}
                                    append pymanSetAttrFmt "\n\t" {globals()%1$s.%2$s = newValue}
                                    py eval [format $pymanSetAttrFmt $pythonObject $attribute]
                                    py call pymanSetAttr $value
                                }
                            }
                        }
                    }
                    
                    ##
                    ## Get attributes and their defaults
                    ##
                    py eval [format $pymanGetAttributesFmt $moduleName $name]
                    set attrList [py call pymanGetAttributes]
                    $className init $attrList

                    ##
                    ## Remove unwanted class methods
                    ##
                    #::oo::define $className deletemethod addPath
                    #::oo::define $className deletemethod import
                    ::oo::define $className export _attributes _getAttribute _setAttribute

                    ##
                    ## 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
................................................................................
            }
        }
    }

    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')}

Changes to src/version.txt.

1
2

major 0
minor 5



>
1
2
3
major 0
minor 5
patch 3