Skip to content

Commit 668e31d

Browse files
author
Randall C. O'Reilly
committed
add support for Enum types in Python, based on const values of the same type in Go. Also generates the raw const values at global package scope, as accessed in Go.
1 parent fcba594 commit 668e31d

File tree

4 files changed

+126
-1
lines changed

4 files changed

+126
-1
lines changed

bind/gen.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ os.chdir(cwd)
250250
# %[2]s
251251
252252
import _%[1]s, collections
253+
from enum import Enum
253254
254255
# to use this code in your end-user python file, import it as follows:
255256
# from %[1]s import %[3]s
@@ -757,6 +758,11 @@ func (g *pyGen) genAll() {
757758
g.genType(sym, false, false) // not exttypes
758759
}
759760

761+
g.pywrap.Printf("\n\n#---- Enums from Go (collections of consts with same type) ---\n")
762+
for _, e := range g.pkg.enums {
763+
g.genEnum(e)
764+
}
765+
760766
g.pywrap.Printf("\n\n#---- Constants from Go: Python can only ask that you please don't change these! ---\n")
761767
for _, c := range g.pkg.consts {
762768
g.genConst(c)

bind/gen_varconst.go

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package bind
66

77
import (
88
"fmt"
9+
"strings"
910
)
1011

1112
func (g *pyGen) genConst(c *Const) {
@@ -110,7 +111,7 @@ func (g *pyGen) genVarSetter(v *Var) {
110111

111112
func (g *pyGen) genConstValue(c *Const) {
112113
// constants go directly into wrapper as-is
113-
val := c.obj.Val().ExactString()
114+
val := c.val
114115
switch val {
115116
case "true":
116117
val = "True"
@@ -119,3 +120,34 @@ func (g *pyGen) genConstValue(c *Const) {
119120
}
120121
g.pywrap.Printf("%s = %s\n", c.GoName(), val)
121122
}
123+
124+
func (g *pyGen) genEnum(e *Enum) {
125+
g.pywrap.Printf("class %s(Enum):\n", e.typ.Obj().Name())
126+
g.pywrap.Indent()
127+
doc := e.Doc()
128+
if doc != "" {
129+
lns := strings.Split(doc, "\n")
130+
g.pywrap.Printf(`"""`)
131+
g.pywrap.Printf("\n")
132+
for _, l := range lns {
133+
g.pywrap.Printf("%s\n", l)
134+
}
135+
g.pywrap.Printf(`"""`)
136+
g.pywrap.Printf("\n")
137+
}
138+
e.SortConsts()
139+
for _, c := range e.items {
140+
g.genConstValue(c)
141+
}
142+
g.pywrap.Outdent()
143+
144+
// Go has each const value globally available within a given package
145+
// so to keep the code consistent, we redundantly generate the consts
146+
// again here. The Enum organization however is critical for organizing
147+
// the values under the type (making them accessible programmatically)
148+
g.pywrap.Printf("\n")
149+
for _, c := range e.items {
150+
g.genConstValue(c)
151+
}
152+
g.pywrap.Printf("\n")
153+
}

bind/package.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"go/types"
1111
"path/filepath"
1212
"reflect"
13+
"strconv"
1314
"strings"
1415
)
1516

@@ -24,6 +25,7 @@ type Package struct {
2425
syms *symtab // note: this is now *always* = symbols.current
2526
objs map[string]Object
2627
consts []*Const
28+
enums []*Enum
2729
vars []*Var
2830
structs []*Struct
2931
ifaces []*Interface
@@ -484,7 +486,34 @@ func (p *Package) process() error {
484486
return err
485487
}
486488

489+
func (p *Package) findEnum(ntyp *types.Named) *Enum {
490+
for _, enm := range p.enums {
491+
if enm.typ == ntyp {
492+
return enm
493+
}
494+
}
495+
return nil
496+
}
497+
487498
func (p *Package) addConst(obj *types.Const) {
499+
if ntyp, ok := obj.Type().(*types.Named); ok {
500+
enm := p.findEnum(ntyp)
501+
if enm != nil {
502+
enm.AddConst(p, obj)
503+
return
504+
} else {
505+
val := obj.Val().String()
506+
_, err := strconv.Atoi(val)
507+
if err == nil {
508+
enm, err := newEnum(p, obj)
509+
if err == nil {
510+
p.enums = append(p.enums, enm)
511+
return
512+
}
513+
}
514+
}
515+
}
516+
488517
nc, err := newConst(p, obj)
489518
if err == nil {
490519
p.consts = append(p.consts, nc)

bind/types.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ package bind
77
import (
88
"fmt"
99
"go/types"
10+
"sort"
11+
"strconv"
1012
)
1113

1214
type Object interface {
@@ -461,20 +463,23 @@ type Const struct {
461463
obj *types.Const
462464
id string
463465
doc string
466+
val string
464467
}
465468

466469
func newConst(p *Package, o *types.Const) (*Const, error) {
467470
pkg := o.Pkg()
468471
sym := p.syms.symtype(o.Type())
469472
id := pkg.Name() + "_" + o.Name()
470473
doc := p.getDoc("", o)
474+
val := o.Val().String()
471475

472476
return &Const{
473477
pkg: p,
474478
sym: sym,
475479
obj: o,
476480
id: id,
477481
doc: doc,
482+
val: val,
478483
}, nil
479484
}
480485

@@ -483,6 +488,59 @@ func (c *Const) Doc() string { return c.doc }
483488
func (c *Const) GoName() string { return c.obj.Name() }
484489
func (c *Const) GoType() types.Type { return c.obj.Type() }
485490

491+
///////////////////////////////////////////////////////////////////////////////////
492+
// Enum
493+
494+
type Enum struct {
495+
pkg *Package
496+
sym *symbol
497+
obj *types.Const // first one -- random..
498+
typ *types.Named
499+
id string
500+
doc string
501+
items []*Const
502+
}
503+
504+
func newEnum(p *Package, o *types.Const) (*Enum, error) {
505+
pkg := o.Pkg()
506+
sym := p.syms.symtype(o.Type())
507+
id := pkg.Name() + "_" + o.Name()
508+
typ := o.Type().(*types.Named)
509+
doc := p.getDoc("", typ.Obj())
510+
511+
e := &Enum{
512+
pkg: p,
513+
sym: sym,
514+
obj: o,
515+
typ: typ,
516+
id: id,
517+
doc: doc,
518+
}
519+
e.AddConst(p, o)
520+
return e, nil
521+
}
522+
523+
func (e *Enum) ID() string { return e.id }
524+
func (e *Enum) Doc() string { return e.doc }
525+
func (e *Enum) GoName() string { return e.obj.Name() }
526+
func (e *Enum) GoType() types.Type { return e.obj.Type() }
527+
528+
func (e *Enum) AddConst(p *Package, o *types.Const) (*Const, error) {
529+
c, err := newConst(p, o)
530+
if err == nil {
531+
e.items = append(e.items, c)
532+
}
533+
return c, err
534+
}
535+
536+
func (e *Enum) SortConsts() {
537+
sort.Slice(e.items, func(i, j int) bool {
538+
iv, _ := strconv.Atoi(e.items[i].val)
539+
jv, _ := strconv.Atoi(e.items[j].val)
540+
return iv < jv
541+
})
542+
}
543+
486544
///////////////////////////////////////////////////////////////////////////////////
487545
// Var
488546

0 commit comments

Comments
 (0)