Codebase list golang-github-alecthomas-repr / de79c51e-874d-4873-a874-3ab3bb981215/upstream
Import upstream version 0.0~git20220113.b1b626a Debian Janitor 2 years ago
17 changed file(s) with 259 addition(s) and 58 deletion(s). Raw diff Collapse all Expand all
0 github: [alecthomas]
0 on:
1 push:
2 branches:
3 - master
4 pull_request:
5 name: CI
6 jobs:
7 test:
8 name: Test
9 runs-on: ubuntu-latest
10 steps:
11 - name: Checkout code
12 uses: actions/checkout@v2
13 - name: Init Hermit
14 run: ./bin/hermit env -r >> $GITHUB_ENV
15 - name: Test
16 run: go test ./...
17 lint:
18 name: Lint
19 runs-on: ubuntu-latest
20 steps:
21 - name: Checkout code
22 uses: actions/checkout@v2
23 - name: Init Hermit
24 run: ./bin/hermit env -r >> $GITHUB_ENV
25 - name: golangci-lint
26 run: golangci-lint run
+0
-4
.travis.yml less more
0 sudo: false
1 language: go
2 install: go get -t -v ./...
3 go: 1.9
0 # Python's repr() for Go [![](https://godoc.org/github.com/alecthomas/repr?status.svg)](http://godoc.org/github.com/alecthomas/repr) [![Build Status](https://travis-ci.org/alecthomas/repr.png)](https://travis-ci.org/alecthomas/repr)
0 # Python's repr() for Go [![](https://godoc.org/github.com/alecthomas/repr?status.svg)](http://godoc.org/github.com/alecthomas/repr) [![CircleCI](https://img.shields.io/circleci/project/github/alecthomas/repr.svg)](https://circleci.com/gh/alecthomas/repr)
11
22 This package attempts to represent Go values in a form that can be used almost directly in Go source
33 code.
0 # Hermit environment
1
2 This is a [Hermit](https://github.com/cashapp/hermit) bin directory.
3
4 The symlinks in this directory are managed by Hermit and will automatically
5 download and install Hermit itself as well as packages. These packages are
6 local to this environment.
0 #!/bin/bash
1 # This file must be used with "source bin/activate-hermit" from bash or zsh.
2 # You cannot run it directly
3
4 if [ "${BASH_SOURCE-}" = "$0" ]; then
5 echo "You must source this script: \$ source $0" >&2
6 exit 33
7 fi
8
9 BIN_DIR="$(dirname "${BASH_SOURCE[0]:-${(%):-%x}}")"
10 if "${BIN_DIR}/hermit" noop > /dev/null; then
11 eval "$("${BIN_DIR}/hermit" activate "${BIN_DIR}/..")"
12
13 if [ -n "${BASH-}" ] || [ -n "${ZSH_VERSION-}" ]; then
14 hash -r 2>/dev/null
15 fi
16
17 echo "Hermit environment $("${HERMIT_ENV}"/bin/hermit env HERMIT_ENV) activated"
18 fi
0 .go@latest.pkg
0 .go@latest.pkg
0 .golangci-lint-1.26.0.pkg
0 #!/bin/bash
1
2 set -eo pipefail
3
4 if [ -z "${HERMIT_STATE_DIR}" ]; then
5 case "$(uname -s)" in
6 Darwin)
7 export HERMIT_STATE_DIR="${HOME}/Library/Caches/hermit"
8 ;;
9 Linux)
10 export HERMIT_STATE_DIR="${XDG_CACHE_HOME:-${HOME}/.cache}/hermit"
11 ;;
12 esac
13 fi
14
15 export HERMIT_DIST_URL="${HERMIT_DIST_URL:-https://github.com/cashapp/hermit/releases/download/stable}"
16 HERMIT_CHANNEL="$(basename "${HERMIT_DIST_URL}")"
17 export HERMIT_CHANNEL
18 export HERMIT_EXE=${HERMIT_EXE:-${HERMIT_STATE_DIR}/pkg/hermit@${HERMIT_CHANNEL}/hermit}
19
20 if [ ! -x "${HERMIT_EXE}" ]; then
21 echo "Bootstrapping ${HERMIT_EXE} from ${HERMIT_DIST_URL}" 1>&2
22 curl -fsSL "${HERMIT_DIST_URL}/install.sh" | /bin/bash 1>&2
23 fi
24
25 exec "${HERMIT_EXE}" --level=fatal exec "$0" -- "$@"
(New empty file)
0 module github.com/alecthomas/repr
1
2 go 1.15
(New empty file)
1010 "io"
1111 "os"
1212 "reflect"
13 "sort"
14 "time"
1315 "unsafe"
1416 )
1517
6062 // OmitEmpty sets whether empty field members should be omitted from output.
6163 func OmitEmpty(omitEmpty bool) Option { return func(o *Printer) { o.omitEmpty = omitEmpty } }
6264
65 // ExplicitTypes adds explicit typing to slice and map struct values that would normally be inferred by Go.
66 func ExplicitTypes(ok bool) Option { return func(o *Printer) { o.explicitTypes = true } }
67
6368 // IgnoreGoStringer disables use of the .GoString() method.
6469 func IgnoreGoStringer() Option { return func(o *Printer) { o.ignoreGoStringer = true } }
6570
8287 omitEmpty bool
8388 ignoreGoStringer bool
8489 alwaysIncludeType bool
90 explicitTypes bool
8591 exclude map[reflect.Type]bool
8692 w io.Writer
8793 }
120126 if i > 0 {
121127 fmt.Fprint(p.w, " ")
122128 }
123 p.reprValue(map[reflect.Value]bool{}, reflect.ValueOf(v), "")
129 p.reprValue(map[reflect.Value]bool{}, reflect.ValueOf(v), "", true)
124130 }
125131 }
126132
130136 if i > 0 {
131137 fmt.Fprint(p.w, " ")
132138 }
133 p.reprValue(map[reflect.Value]bool{}, reflect.ValueOf(v), "")
139 p.reprValue(map[reflect.Value]bool{}, reflect.ValueOf(v), "", true)
134140 }
135141 fmt.Fprintln(p.w)
136142 }
137143
138 func (p *Printer) reprValue(seen map[reflect.Value]bool, v reflect.Value, indent string) { // nolint: gocyclo
144 func (p *Printer) reprValue(seen map[reflect.Value]bool, v reflect.Value, indent string, showType bool) { // nolint: gocyclo
139145 if seen[v] {
140146 fmt.Fprint(p.w, "...")
141147 return
154160 t := v.Type()
155161
156162 if t == byteSliceType {
157 fmt.Fprintf(p.w, "[]byte(%q)", v.Interface())
163 fmt.Fprintf(p.w, "[]byte(%q)", v.Bytes())
158164 return
159165 }
160166
174180 ni := p.nextIndent(indent)
175181 switch v.Kind() {
176182 case reflect.Slice, reflect.Array:
177 if p.omitEmpty && v.Len() == 0 {
178 return
179 }
180183 fmt.Fprintf(p.w, "%s{", v.Type())
181184 if v.Len() == 0 {
182185 fmt.Fprint(p.w, "}")
187190 for i := 0; i < v.Len(); i++ {
188191 e := v.Index(i)
189192 fmt.Fprintf(p.w, "%s", ni)
190 p.reprValue(seen, e, ni)
193 p.reprValue(seen, e, ni, p.alwaysIncludeType || p.explicitTypes)
191194 if p.indent != "" {
192195 fmt.Fprintf(p.w, ",\n")
193196 } else if i < v.Len()-1 {
207210 if p.indent != "" && v.Len() != 0 {
208211 fmt.Fprintf(p.w, "\n")
209212 }
210 for i, k := range v.MapKeys() {
213 keys := v.MapKeys()
214 sort.Slice(keys, func(i, j int) bool {
215 return fmt.Sprint(keys[i]) < fmt.Sprint(keys[j])
216 })
217 for i, k := range keys {
211218 kv := v.MapIndex(k)
212219 fmt.Fprintf(p.w, "%s", ni)
213 p.reprValue(seen, k, ni)
220 p.reprValue(seen, k, ni, p.alwaysIncludeType || p.explicitTypes)
214221 fmt.Fprintf(p.w, ": ")
215 p.reprValue(seen, kv, ni)
222 p.reprValue(seen, kv, ni, true)
216223 if p.indent != "" {
217224 fmt.Fprintf(p.w, ",\n")
218225 } else if i < v.Len()-1 {
222229 fmt.Fprintf(p.w, "%s}", in)
223230
224231 case reflect.Struct:
225 fmt.Fprintf(p.w, "%s{", v.Type())
226 if p.indent != "" && v.NumField() != 0 {
227 fmt.Fprintf(p.w, "\n")
228 }
229 for i := 0; i < v.NumField(); i++ {
230 t := v.Type().Field(i)
231 f := v.Field(i)
232 if p.omitEmpty && isZero(f) {
233 continue
234 }
235 fmt.Fprintf(p.w, "%s%s: ", ni, t.Name)
236 p.reprValue(seen, f, ni)
237 if p.indent != "" {
238 fmt.Fprintf(p.w, ",\n")
239 } else if i < v.NumField()-1 {
240 fmt.Fprintf(p.w, ", ")
241 }
242 }
243 fmt.Fprintf(p.w, "%s}", indent)
244
232 if td, ok := v.Interface().(time.Time); ok {
233 timeToGo(p.w, td)
234 } else {
235 if showType {
236 fmt.Fprintf(p.w, "%s{", v.Type())
237 } else {
238 fmt.Fprint(p.w, "{")
239 }
240 if p.indent != "" && v.NumField() != 0 {
241 fmt.Fprintf(p.w, "\n")
242 }
243 for i := 0; i < v.NumField(); i++ {
244 t := v.Type().Field(i)
245 f := v.Field(i)
246 if p.omitEmpty && isZero(f) {
247 continue
248 }
249 fmt.Fprintf(p.w, "%s%s: ", ni, t.Name)
250 p.reprValue(seen, f, ni, true)
251 if p.indent != "" {
252 fmt.Fprintf(p.w, ",\n")
253 } else if i < v.NumField()-1 {
254 fmt.Fprintf(p.w, ", ")
255 }
256 }
257 fmt.Fprintf(p.w, "%s}", indent)
258 }
245259 case reflect.Ptr:
246260 if v.IsNil() {
247261 fmt.Fprintf(p.w, "nil")
248262 return
249263 }
250 fmt.Fprintf(p.w, "&")
251 p.reprValue(seen, v.Elem(), indent)
264 if showType {
265 fmt.Fprintf(p.w, "&")
266 }
267 p.reprValue(seen, v.Elem(), indent, showType)
252268
253269 case reflect.String:
254270 if t.Name() != "string" || p.alwaysIncludeType {
261277 if v.IsNil() {
262278 fmt.Fprintf(p.w, "interface {}(nil)")
263279 } else {
264 p.reprValue(seen, v.Elem(), indent)
280 p.reprValue(seen, v.Elem(), indent, true)
265281 }
266282
267283 default:
322338 }
323339 return false
324340 }
341
342 func timeToGo(w io.Writer, t time.Time) {
343 if t.IsZero() {
344 fmt.Fprint(w, "time.Time{}")
345 return
346 }
347
348 var zone string
349 switch loc := t.Location(); loc {
350 case nil:
351 zone = "nil"
352 case time.UTC:
353 zone = "time.UTC"
354 case time.Local:
355 zone = "time.Local"
356 default:
357 n, off := t.Zone()
358 zone = fmt.Sprintf("time.FixedZone(%q, %d)", n, off)
359 }
360 y, m, d := t.Date()
361 fmt.Fprintf(w, `time.Date(%d, %d, %d, %d, %d, %d, %d, %s)`, y, m, d, t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), zone)
362 }
00 package repr
11
22 import (
3 "bytes"
4 "runtime"
35 "strings"
46 "testing"
5
6 "github.com/stretchr/testify/assert"
77 )
8
9 func equal(t *testing.T, want, have string) {
10 t.Helper()
11 if want != have {
12 t.Errorf("\nWant: %q\nHave: %q", want, have)
13 }
14 }
815
916 type anotherStruct struct {
1017 A []int
1724 }
1825
1926 func TestReprEmptyArray(t *testing.T) {
20 assert.Equal(t, "[]string{}", String([]string{}, OmitEmpty(false)))
27 equal(t, "[]string{}", String([]string{}, OmitEmpty(false)))
2128 }
2229
2330 func TestReprStringArray(t *testing.T) {
24 assert.Equal(t, "[]string{\"a\", \"b\"}", String([]string{"a", "b"}))
31 equal(t, "[]string{\"a\", \"b\"}", String([]string{"a", "b"}))
2532 }
2633
2734 func TestReprIntArray(t *testing.T) {
28 assert.Equal(t, "[]int{1, 2}", String([]int{1, 2}))
35 equal(t, "[]int{1, 2}", String([]int{1, 2}))
2936 }
3037
3138 func TestReprPointerToInt(t *testing.T) {
3239 pi := new(int)
3340 *pi = 13
34 assert.Equal(t, `&13`, String(pi))
41 equal(t, `&13`, String(pi))
3542 }
3643
3744 func TestReprChannel(t *testing.T) {
3845 ch := make(<-chan map[string]*testStruct, 1)
39 assert.Equal(t, `make(<-chan map[string]*repr.testStruct, 1)`, String(ch))
46 equal(t, `make(<-chan map[string]*repr.testStruct, 1)`, String(ch))
4047 }
4148
4249 func TestReprEmptyMap(t *testing.T) {
43 assert.Equal(t, "map[string]bool{}", String(map[string]bool{}))
50 equal(t, "map[string]bool{}", String(map[string]bool{}))
4451 }
4552
4653 func TestReprMap(t *testing.T) {
47 m := map[string]int{"a": 1}
48 assert.Equal(t, "map[string]int{\"a\": 1}", String(m))
54 m := map[string]int{"b": 3, "a": 1, "c": 5}
55 for i := 0; i < 1000; i++ {
56 equal(t, "map[string]int{\"a\": 1, \"b\": 3, \"c\": 5}", String(m))
57 }
58 }
59
60 func TestReprIntMap(t *testing.T) {
61 m := map[int]string{3: "b", 1: "a", 5: "c"}
62 for i := 0; i < 1000; i++ {
63 equal(t, "map[int]string{1: \"a\", 3: \"b\", 5: \"c\"}", String(m))
64 }
4965 }
5066
5167 func TestReprStructWithIndent(t *testing.T) {
5874 A: []int{1, 2, 3},
5975 },
6076 }
61 assert.Equal(t, `&repr.testStruct{
77 equal(t, `&repr.testStruct{
6278 S: "String",
6379 I: &13,
6480 A: repr.anotherStruct{
6985 },
7086 },
7187 }`, String(s, Indent(" ")))
72
7388 }
7489
7590 func TestReprByteArray(t *testing.T) {
7691 b := []byte{1, 2, 3}
77 assert.Equal(t, "[]byte(\"\\x01\\x02\\x03\")", String(b))
92 equal(t, "[]byte(\"\\x01\\x02\\x03\")", String(b))
7893 }
7994
8095 type privateTestStruct struct {
8398
8499 func TestReprPrivateField(t *testing.T) {
85100 s := privateTestStruct{"hello"}
86 assert.Equal(t, `repr.privateTestStruct{a: "hello"}`, String(s))
101 equal(t, `repr.privateTestStruct{a: "hello"}`, String(s))
87102 }
88103
89104 func TestReprNilAlone(t *testing.T) {
90105 var err error
91106 s := String(err)
92 assert.Equal(t, "nil", s)
107 equal(t, "nil", s)
108 }
109
110 func TestExplicitTypes(t *testing.T) {
111 arr := []*privateTestStruct{{"hello"}, nil}
112 s := String(arr, ExplicitTypes(true))
113 equal(t, "[]*repr.privateTestStruct{&repr.privateTestStruct{a: \"hello\"}, nil}", s)
93114 }
94115
95116 func TestReprNilInsideArray(t *testing.T) {
96117 arr := []*privateTestStruct{{"hello"}, nil}
97118 s := String(arr)
98 assert.Equal(t, "[]*repr.privateTestStruct{&repr.privateTestStruct{a: \"hello\"}, nil}", s)
119 equal(t, "[]*repr.privateTestStruct{{a: \"hello\"}, nil}", s)
120 }
121
122 func TestReprEmptySlice(t *testing.T) {
123 a := []int{}
124 s := String(a)
125 equal(t, "[]int{}", s)
126 }
127
128 func TestReprNilSlice(t *testing.T) {
129 var a []int
130 s := String(a)
131 equal(t, "nil", s)
132 }
133
134 type intSliceStruct struct{ f []int }
135
136 func TestReprEmptySliceStruct(t *testing.T) {
137 a := intSliceStruct{f: []int{}}
138 s := String(a)
139 equal(t, "repr.intSliceStruct{f: []int{}}", s)
140 }
141
142 func TestReprNilSliceStruct(t *testing.T) {
143 var a intSliceStruct
144 s := String(a)
145 equal(t, "repr.intSliceStruct{}", s)
99146 }
100147
101148 type Enum int
107154 func TestEnum(t *testing.T) {
108155 v := Enum(1)
109156 s := String(v)
110 assert.Equal(t, "repr.Enum(Value)", s)
157 equal(t, "repr.Enum(Value)", s)
111158 }
112159
113160 func TestShowType(t *testing.T) {
114161 a := map[string]privateTestStruct{"foo": {"bar"}}
115162 s := String(a, AlwaysIncludeType(), Indent(" "))
116 t.Log(s)
117 assert.Equal(t, strings.TrimSpace(`
163 equal(t, strings.TrimSpace(`
118164 map[string]repr.privateTestStruct{
119165 string("foo"): repr.privateTestStruct{
120166 a: string("bar"),
122168 }
123169 `), s)
124170 }
171
172 func TestRecursiveIssue3(t *testing.T) {
173 type data struct {
174 parent *data
175 children []*data
176 }
177 child := &data{}
178 root := &data{children: []*data{child}}
179 child.parent = root
180 want := "&repr.data{children: []*repr.data{{parent: &..., }}}"
181 have := String(root)
182 equal(t, want, have)
183 }
184
185 type MyBuffer struct {
186 buf *bytes.Buffer
187 }
188
189 func TestReprPrivateBytes(t *testing.T) {
190 mb := MyBuffer{
191 buf: bytes.NewBufferString("Hi th3re!"),
192 }
193 s := String(mb)
194
195 switch v := runtime.Version(); {
196 case strings.Contains(v, "go1.9"):
197 equal(t, "repr.MyBuffer{buf: &bytes.Buffer{buf: []byte(\"Hi th3re!\"), bootstrap: [64]uint8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}", s)
198 case strings.Contains(v, "go1.10"), strings.Contains(v, "go1.11"):
199 equal(t, "repr.MyBuffer{buf: &bytes.Buffer{buf: []byte(\"Hi th3re!\"), bootstrap: [64]uint8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }}", s)
200 default:
201 equal(t, "repr.MyBuffer{buf: &bytes.Buffer{buf: []byte(\"Hi th3re!\"), }}", s)
202 }
203 }