├── examples ├── iris.jpg ├── Elman_srnn.png ├── Feed_forward_neural_net.gif ├── Simple-Example.ipynb ├── iris.csv ├── Worker-Pools.ipynb ├── Pattern-Recognition.ipynb ├── Feed-Forward-Recurrent-NN.ipynb ├── Stateful-Goroutines.ipynb └── Time-Formatting-Parsing.ipynb ├── files ├── screencast.gif ├── gophernotes.jpg └── gophernotes2.jpg ├── kernel ├── logo-32x32.png ├── logo-64x64.png └── kernel.json ├── vendor ├── github.com │ ├── alecthomas │ │ └── gozmq │ │ │ ├── .todo2 │ │ │ ├── .gitignore │ │ │ ├── .travis.yml │ │ │ ├── AUTHORS │ │ │ ├── zmq_windows.go │ │ │ ├── zmq_2_2.go │ │ │ ├── zmq_unix.go │ │ │ ├── zmq_4_x.go │ │ │ ├── zmq_2_x.go │ │ │ ├── .godocdown.md │ │ │ ├── zmq_3_x.go │ │ │ ├── zmqgen_2_1.go │ │ │ └── zmqgen_2_2.go │ ├── nu7hatch │ │ └── gouuid │ │ │ ├── .gitignore │ │ │ ├── README.md │ │ │ ├── COPYING │ │ │ └── uuid.go │ ├── motemen │ │ └── go-quickfix │ │ │ ├── .travis.yml │ │ │ ├── LICENSE │ │ │ └── README.adoc │ ├── stretchr │ │ └── testify │ │ │ ├── assert │ │ │ ├── assertion_forward.go.tmpl │ │ │ ├── errors.go │ │ │ ├── forward_assertions.go │ │ │ ├── doc.go │ │ │ └── http_assertions.go │ │ │ ├── LICENSE │ │ │ └── LICENCE.txt │ ├── mitchellh │ │ └── go-homedir │ │ │ ├── README.md │ │ │ ├── LICENSE │ │ │ └── homedir.go │ ├── davecgh │ │ └── go-spew │ │ │ ├── LICENSE │ │ │ └── spew │ │ │ ├── bypasssafe.go │ │ │ ├── bypass.go │ │ │ ├── spew.go │ │ │ └── doc.go │ └── pmezard │ │ └── go-difflib │ │ └── LICENSE └── golang.org │ └── x │ └── tools │ ├── go │ └── ast │ │ └── astutil │ │ └── util.go │ ├── imports │ ├── fastwalk_dirent_ino.go │ ├── fastwalk_dirent_fileno.go │ ├── fastwalk_portable.go │ ├── mkstdlib.go │ ├── fastwalk_unix.go │ ├── mkindex.go │ ├── fastwalk.go │ ├── sortimports.go │ └── imports.go │ ├── PATENTS │ └── LICENSE ├── zmq-win ├── lib-386 │ ├── libzmq.a │ └── libzmq.dll ├── lib-amd64 │ ├── libzmq.a │ └── libzmq.dll ├── build.bat └── include │ └── zmq_utils.h ├── Godeps ├── Readme └── Godeps.json ├── internal └── repl │ ├── utils.go │ ├── log.go │ ├── node.go │ ├── quickfix.go │ └── commands.go ├── main.go ├── Dockerfile ├── LICENSE.md ├── gophernotes_test.go ├── execution.go ├── messages.go └── gophernotes.go /examples/iris.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/gophernotes/master/examples/iris.jpg -------------------------------------------------------------------------------- /files/screencast.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/gophernotes/master/files/screencast.gif -------------------------------------------------------------------------------- /files/gophernotes.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/gophernotes/master/files/gophernotes.jpg -------------------------------------------------------------------------------- /files/gophernotes2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/gophernotes/master/files/gophernotes2.jpg -------------------------------------------------------------------------------- /kernel/logo-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/gophernotes/master/kernel/logo-32x32.png -------------------------------------------------------------------------------- /kernel/logo-64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/gophernotes/master/kernel/logo-64x64.png -------------------------------------------------------------------------------- /examples/Elman_srnn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/gophernotes/master/examples/Elman_srnn.png -------------------------------------------------------------------------------- /vendor/github.com/alecthomas/gozmq/.todo2: -------------------------------------------------------------------------------- 1 | { 2 | "title": "GoZMQ - ZMQ bindings for Go", 3 | "tasks": [] 4 | } -------------------------------------------------------------------------------- /zmq-win/lib-386/libzmq.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/gophernotes/master/zmq-win/lib-386/libzmq.a -------------------------------------------------------------------------------- /zmq-win/lib-386/libzmq.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/gophernotes/master/zmq-win/lib-386/libzmq.dll -------------------------------------------------------------------------------- /zmq-win/lib-amd64/libzmq.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/gophernotes/master/zmq-win/lib-amd64/libzmq.a -------------------------------------------------------------------------------- /zmq-win/lib-amd64/libzmq.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/gophernotes/master/zmq-win/lib-amd64/libzmq.dll -------------------------------------------------------------------------------- /examples/Feed_forward_neural_net.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/gophernotes/master/examples/Feed_forward_neural_net.gif -------------------------------------------------------------------------------- /vendor/github.com/nu7hatch/gouuid/.gitignore: -------------------------------------------------------------------------------- 1 | _obj 2 | _test 3 | *.6 4 | *.out 5 | _testmain.go 6 | \#* 7 | .\#* 8 | *.log 9 | _cgo* 10 | *.o 11 | *.a 12 | -------------------------------------------------------------------------------- /vendor/github.com/motemen/go-quickfix/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - 1.5 4 | - 1.6 5 | - tip 6 | install: 7 | - go get ./... 8 | - go get -t ./... 9 | -------------------------------------------------------------------------------- /Godeps/Readme: -------------------------------------------------------------------------------- 1 | This directory tree is generated automatically by godep. 2 | 3 | Please do not edit. 4 | 5 | See https://github.com/tools/godep for more information. 6 | -------------------------------------------------------------------------------- /kernel/kernel.json: -------------------------------------------------------------------------------- 1 | { 2 | "argv": [ 3 | "gophernotes", 4 | "{connection_file}" 5 | ], 6 | "display_name": "Go", 7 | "language": "go", 8 | "name": "go" 9 | } 10 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl: -------------------------------------------------------------------------------- 1 | {{.CommentWithoutT "a"}} 2 | func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) bool { 3 | return {{.DocInfo.Name}}(a.t, {{.ForwardedParams}}) 4 | } 5 | -------------------------------------------------------------------------------- /vendor/github.com/alecthomas/gozmq/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.a 3 | *.[568vq] 4 | [568vq].out 5 | *.cgo1.go 6 | *.cgo2.c 7 | _cgo_defun.c 8 | _cgo_gotypes.go 9 | _cgo_export.* 10 | *.so 11 | _obj 12 | _test 13 | _testmain.go 14 | *.exe 15 | .cache 16 | -------------------------------------------------------------------------------- /vendor/github.com/alecthomas/gozmq/.travis.yml: -------------------------------------------------------------------------------- 1 | before_install: 2 | - sudo apt-get install libzmq3-dev 3 | language: go 4 | go: 1.1.1 5 | install: go get -tags zmq_3_x -d -v ./... && go build -tags zmq_3_x -v ./... 6 | script: go test -v -tags zmq_3_x ./... 7 | -------------------------------------------------------------------------------- /internal/repl/utils.go: -------------------------------------------------------------------------------- 1 | package replpkg 2 | 3 | import ( 4 | "bytes" 5 | 6 | "go/printer" 7 | "go/token" 8 | ) 9 | 10 | func showNode(fset *token.FileSet, node interface{}) string { 11 | var buf bytes.Buffer 12 | printer.Fprint(&buf, fset, node) 13 | return buf.String() 14 | } 15 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/go/ast/astutil/util.go: -------------------------------------------------------------------------------- 1 | package astutil 2 | 3 | import "go/ast" 4 | 5 | // Unparen returns e with any enclosing parentheses stripped. 6 | func Unparen(e ast.Expr) ast.Expr { 7 | for { 8 | p, ok := e.(*ast.ParenExpr) 9 | if !ok { 10 | return e 11 | } 12 | e = p.X 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /vendor/github.com/alecthomas/gozmq/AUTHORS: -------------------------------------------------------------------------------- 1 | The GoZmq package was originally written by Alec Thomas . 2 | 3 | Thanks to the following frequent contributors: 4 | 5 | @mcgoo Jim McGrath (https://github.com/mcgoo) 6 | @jtacoma Joshua Tacoma (https://github.com/jtacoma) 7 | @jhawk28 8 | 9 | And many others. 10 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/imports/fastwalk_dirent_ino.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build linux darwin 6 | 7 | package imports 8 | 9 | import "syscall" 10 | 11 | func direntInode(dirent *syscall.Dirent) uint64 { 12 | return uint64(dirent.Ino) 13 | } 14 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/errors.go: -------------------------------------------------------------------------------- 1 | package assert 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | // AnError is an error instance useful for testing. If the code does not care 8 | // about error specifics, and only needs to return the error for example, this 9 | // error should be used to make the test code more readable. 10 | var AnError = errors.New("assert.AnError general error for testing") 11 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/imports/fastwalk_dirent_fileno.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build freebsd openbsd netbsd 6 | 7 | package imports 8 | 9 | import "syscall" 10 | 11 | func direntInode(dirent *syscall.Dirent) uint64 { 12 | return uint64(dirent.Fileno) 13 | } 14 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/forward_assertions.go: -------------------------------------------------------------------------------- 1 | package assert 2 | 3 | // Assertions provides assertion methods around the 4 | // TestingT interface. 5 | type Assertions struct { 6 | t TestingT 7 | } 8 | 9 | // New makes a new Assertions object for the specified TestingT. 10 | func New(t TestingT) *Assertions { 11 | return &Assertions{ 12 | t: t, 13 | } 14 | } 15 | 16 | //go:generate go run ../_codegen/main.go -output-package=assert -template=assertion_forward.go.tmpl 17 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "io" 6 | "io/ioutil" 7 | "log" 8 | "os" 9 | ) 10 | 11 | func main() { 12 | 13 | debug := flag.Bool("debug", false, "Log extra info to stderr") 14 | 15 | flag.Parse() 16 | if flag.NArg() < 1 { 17 | log.Fatalln("Need a command line argument for the connection file.") 18 | } 19 | 20 | var logwriter io.Writer = os.Stderr 21 | if !*debug { 22 | logwriter = ioutil.Discard 23 | } 24 | 25 | RunKernel(flag.Arg(0), logwriter) 26 | } 27 | -------------------------------------------------------------------------------- /zmq-win/build.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | setlocal 3 | 4 | if not [%1]==[386]; if not [%1]==[amd64] ( 5 | echo Usage: %~n0 386^|amd64 6 | goto QUIT 7 | ) 8 | set target=%1 9 | 10 | REM get the bat's directory path, and replace \ with / 11 | set mydir=%~dp0 12 | set mydir=%mydir:\=/% 13 | 14 | set CGO_CFLAGS=-I %mydir%include 15 | set CGO_LDFLAGS=-L %mydir%lib-%target% -l zmq 16 | 17 | go build -tags zmq_4_x github.com/gopherds/gophernotes 18 | 19 | :QUIT 20 | endlocal 21 | echo on 22 | -------------------------------------------------------------------------------- /internal/repl/log.go: -------------------------------------------------------------------------------- 1 | package replpkg 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "path/filepath" 7 | "runtime" 8 | ) 9 | 10 | var debug bool 11 | 12 | func debugf(format string, args ...interface{}) { 13 | 14 | if !debug { 15 | return 16 | } 17 | 18 | _, file, line, ok := runtime.Caller(1) 19 | if ok { 20 | format = fmt.Sprintf("%s:%d %s", filepath.Base(file), line, format) 21 | } 22 | 23 | fmt.Fprintf(os.Stderr, format+"\n", args...) 24 | } 25 | 26 | func errorf(format string, args ...interface{}) { 27 | fmt.Fprintf(os.Stderr, "error: "+format+"\n", args...) 28 | } 29 | 30 | func infof(format string, args ...interface{}) { 31 | fmt.Fprintf(os.Stderr, format+"\n", args...) 32 | } 33 | -------------------------------------------------------------------------------- /vendor/github.com/nu7hatch/gouuid/README.md: -------------------------------------------------------------------------------- 1 | # Pure Go UUID implementation 2 | 3 | This package provides immutable UUID structs and the functions 4 | NewV3, NewV4, NewV5 and Parse() for generating versions 3, 4 5 | and 5 UUIDs as specified in [RFC 4122](http://www.ietf.org/rfc/rfc4122.txt). 6 | 7 | ## Installation 8 | 9 | Use the `go` tool: 10 | 11 | $ go get github.com/nu7hatch/gouuid 12 | 13 | ## Usage 14 | 15 | See [documentation and examples](http://godoc.org/github.com/nu7hatch/gouuid) 16 | for more information. 17 | 18 | ## Copyright 19 | 20 | Copyright (C) 2011 by Krzysztof Kowalik . See [COPYING](https://github.com/nu7hatch/gouuid/tree/master/COPYING) 21 | file for details. 22 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang 2 | 3 | # dependencies 4 | RUN apt-get update 5 | RUN apt-get install -y pkg-config libzmq3-dev build-essential python3-pip 6 | 7 | # set up golang 8 | ENV PATH /usr/local/go/bin:$PATH 9 | ENV GOPATH /go 10 | ENV PATH $GOPATH/bin:$PATH 11 | RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" && chmod -R 777 "$GOPATH" 12 | 13 | # install gophernotes 14 | RUN go get golang.org/x/tools/cmd/goimports 15 | RUN go get -tags zmq_3_x github.com/gopherds/gophernotes 16 | RUN mkdir -p ~/.ipython/kernels/gophernotes 17 | RUN cp -r $GOPATH/src/github.com/gopherds/gophernotes/kernel/* ~/.ipython/kernels/gophernotes 18 | 19 | # install jupyter 20 | RUN pip3 install jupyter 21 | 22 | EXPOSE 8888 23 | CMD ["jupyter", "notebook"] 24 | -------------------------------------------------------------------------------- /vendor/github.com/mitchellh/go-homedir/README.md: -------------------------------------------------------------------------------- 1 | # go-homedir 2 | 3 | This is a Go library for detecting the user's home directory without 4 | the use of cgo, so the library can be used in cross-compilation environments. 5 | 6 | Usage is incredibly simple, just call `homedir.Dir()` to get the home directory 7 | for a user, and `homedir.Expand()` to expand the `~` in a path to the home 8 | directory. 9 | 10 | **Why not just use `os/user`?** The built-in `os/user` package requires 11 | cgo on Darwin systems. This means that any Go code that uses that package 12 | cannot cross compile. But 99% of the time the use for `os/user` is just to 13 | retrieve the home directory, which we can do for the current user without 14 | cgo. This library does that, enabling cross-compilation. 15 | -------------------------------------------------------------------------------- /vendor/github.com/davecgh/go-spew/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012-2013 Dave Collins 2 | 3 | Permission to use, copy, modify, and distribute this software for any 4 | purpose with or without fee is hereby granted, provided that the above 5 | copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | -------------------------------------------------------------------------------- /internal/repl/node.go: -------------------------------------------------------------------------------- 1 | package replpkg 2 | 3 | import ( 4 | "reflect" 5 | 6 | "go/ast" 7 | "go/token" 8 | ) 9 | 10 | // normalizeNodePos resets all position information of node and its descendants. 11 | func normalizeNodePos(node ast.Node) { 12 | ast.Inspect(node, func(node ast.Node) bool { 13 | if node == nil { 14 | return true 15 | } 16 | 17 | if node.Pos() == token.NoPos && node.End() == token.NoPos { 18 | return true 19 | } 20 | 21 | pv := reflect.ValueOf(node) 22 | if pv.Kind() != reflect.Ptr { 23 | return true 24 | } 25 | 26 | v := pv.Elem() 27 | if v.Kind() != reflect.Struct { 28 | return true 29 | } 30 | 31 | for i := 0; i < v.NumField(); i++ { 32 | f := v.Field(i) 33 | ft := f.Type() 34 | if f.CanSet() && ft.PkgPath() == "go/token" && ft.Name() == "Pos" && f.Int() != 0 { 35 | f.SetInt(1) 36 | } 37 | } 38 | 39 | return true 40 | }) 41 | } 42 | -------------------------------------------------------------------------------- /vendor/github.com/alecthomas/gozmq/zmq_windows.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2012 Alec Thomas 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package gozmq 18 | 19 | /* 20 | #cgo !windows pkg-config: libzmq 21 | #include 22 | */ 23 | import "C" 24 | 25 | type ZmqOsSocketType C.SOCKET 26 | 27 | func (self ZmqOsSocketType) ToRaw() C.SOCKET { 28 | return C.SOCKET(self) 29 | } 30 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/imports/fastwalk_portable.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !linux,!darwin,!freebsd,!openbsd,!netbsd 6 | 7 | package imports 8 | 9 | import ( 10 | "io/ioutil" 11 | "os" 12 | ) 13 | 14 | // readDir calls fn for each directory entry in dirName. 15 | // It does not descend into directories or follow symlinks. 16 | // If fn returns a non-nil error, readDir returns with that error 17 | // immediately. 18 | func readDir(dirName string, fn func(dirName, entName string, typ os.FileMode) error) error { 19 | fis, err := ioutil.ReadDir(dirName) 20 | if err != nil { 21 | return err 22 | } 23 | for _, fi := range fis { 24 | if err := fn(dirName, fi.Name(), fi.Mode()&os.ModeType); err != nil { 25 | return err 26 | } 27 | } 28 | return nil 29 | } 30 | -------------------------------------------------------------------------------- /vendor/github.com/alecthomas/gozmq/zmq_2_2.go: -------------------------------------------------------------------------------- 1 | // +build !zmq_2_1 2 | 3 | /* 4 | Copyright 2010-2012 Alec Thomas 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | package gozmq 20 | 21 | /* 22 | #cgo !windows pkg-config: libzmq 23 | #include 24 | */ 25 | import "C" 26 | 27 | const ( 28 | RCVTIMEO = IntSocketOption(C.ZMQ_RCVTIMEO) 29 | SNDTIMEO = IntSocketOption(C.ZMQ_SNDTIMEO) 30 | ) 31 | -------------------------------------------------------------------------------- /vendor/github.com/alecthomas/gozmq/zmq_unix.go: -------------------------------------------------------------------------------- 1 | // +build darwin freebsd linux netbsd openbsd 2 | 3 | /* 4 | Copyright 2012 Alec Thomas 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | package gozmq 20 | 21 | /* 22 | #cgo !windows pkg-config: libzmq 23 | #include 24 | */ 25 | import "C" 26 | 27 | type ZmqOsSocketType C.int 28 | 29 | func (self ZmqOsSocketType) ToRaw() C.int { 30 | return C.int(self) 31 | } 32 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/nu7hatch/gouuid/COPYING: -------------------------------------------------------------------------------- 1 | Copyright (C) 2011 by Krzysztof Kowalik 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. -------------------------------------------------------------------------------- /vendor/github.com/mitchellh/go-homedir/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Mitchell Hashimoto 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/motemen/go-quickfix/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Hiroshi SHIBAMURA 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 - 2013 Mat Ryer and Tyler Bunnell 2 | 3 | Please consider promoting this project if you find it useful. 4 | 5 | Permission is hereby granted, free of charge, to any person 6 | obtaining a copy of this software and associated documentation 7 | files (the "Software"), to deal in the Software without restriction, 8 | including without limitation the rights to use, copy, modify, merge, 9 | publish, distribute, sublicense, and/or sell copies of the Software, 10 | and to permit persons to whom the Software is furnished to do so, 11 | subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included 14 | in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 20 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 21 | OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 22 | OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/LICENCE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 - 2013 Mat Ryer and Tyler Bunnell 2 | 3 | Please consider promoting this project if you find it useful. 4 | 5 | Permission is hereby granted, free of charge, to any person 6 | obtaining a copy of this software and associated documentation 7 | files (the "Software"), to deal in the Software without restriction, 8 | including without limitation the rights to use, copy, modify, merge, 9 | publish, distribute, sublicense, and/or sell copies of the Software, 10 | and to permit persons to whom the Software is furnished to do so, 11 | subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included 14 | in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 20 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 21 | OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 22 | OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /Godeps/Godeps.json: -------------------------------------------------------------------------------- 1 | { 2 | "ImportPath": "github.com/gopherds/gophernotes", 3 | "GoVersion": "go1.6", 4 | "GodepVersion": "v74", 5 | "Packages": [ 6 | "./..." 7 | ], 8 | "Deps": [ 9 | { 10 | "ImportPath": "github.com/alecthomas/gozmq", 11 | "Rev": "d1b01a2df6b2c64f03fecaeabea541963fc4749f" 12 | }, 13 | { 14 | "ImportPath": "github.com/davecgh/go-spew/spew", 15 | "Rev": "5215b55f46b2b919f50a1df0eaa5886afe4e3b3d" 16 | }, 17 | { 18 | "ImportPath": "github.com/mitchellh/go-homedir", 19 | "Rev": "d682a8f0cf139663a984ff12528da460ca963de9" 20 | }, 21 | { 22 | "ImportPath": "github.com/motemen/go-quickfix", 23 | "Rev": "5c522febc6796f9c2ceabf9374a75490e2d268da" 24 | }, 25 | { 26 | "ImportPath": "github.com/nu7hatch/gouuid", 27 | "Rev": "179d4d0c4d8d407a32af483c2354df1d2c91e6c3" 28 | }, 29 | { 30 | "ImportPath": "github.com/pmezard/go-difflib/difflib", 31 | "Rev": "792786c7400a136282c1664665ae0a8db921c6c2" 32 | }, 33 | { 34 | "ImportPath": "github.com/stretchr/testify/assert", 35 | "Comment": "v1.1.3", 36 | "Rev": "f390dcf405f7b83c997eac1b06768bb9f44dec18" 37 | }, 38 | { 39 | "ImportPath": "golang.org/x/tools/go/ast/astutil", 40 | "Rev": "ed69e84b1518b5857a9f4e01d1f9cefdcc45246e" 41 | }, 42 | { 43 | "ImportPath": "golang.org/x/tools/imports", 44 | "Rev": "ed69e84b1518b5857a9f4e01d1f9cefdcc45246e" 45 | } 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Go project. 5 | 6 | Google hereby grants to You a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this section) 8 | patent license to make, have made, use, offer to sell, sell, import, 9 | transfer and otherwise run, modify and propagate the contents of this 10 | implementation of Go, where such license applies only to those patent 11 | claims, both currently owned or controlled by Google and acquired in 12 | the future, licensable by Google that are necessarily infringed by this 13 | implementation of Go. This grant does not include claims that would be 14 | infringed only as a consequence of further modification of this 15 | implementation. If you or your agent or exclusive licensee institute or 16 | order or agree to the institution of patent litigation against any 17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging 18 | that this implementation of Go or any code incorporated within this 19 | implementation of Go constitutes direct or contributory patent 20 | infringement, or inducement of patent infringement, then any patent 21 | rights granted to you under this License for this implementation of Go 22 | shall terminate as of the date such litigation is filed. 23 | -------------------------------------------------------------------------------- /vendor/github.com/pmezard/go-difflib/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Patrick Mezard 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | The names of its contributors may not be used to endorse or promote 14 | products derived from this software without specific prior written 15 | permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 18 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 20 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 23 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 24 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 26 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/doc.go: -------------------------------------------------------------------------------- 1 | // Package assert provides a set of comprehensive testing tools for use with the normal Go testing system. 2 | // 3 | // Example Usage 4 | // 5 | // The following is a complete example using assert in a standard test function: 6 | // import ( 7 | // "testing" 8 | // "github.com/stretchr/testify/assert" 9 | // ) 10 | // 11 | // func TestSomething(t *testing.T) { 12 | // 13 | // var a string = "Hello" 14 | // var b string = "Hello" 15 | // 16 | // assert.Equal(t, a, b, "The two words should be the same.") 17 | // 18 | // } 19 | // 20 | // if you assert many times, use the format below: 21 | // 22 | // import ( 23 | // "testing" 24 | // "github.com/stretchr/testify/assert" 25 | // ) 26 | // 27 | // func TestSomething(t *testing.T) { 28 | // assert := assert.New(t) 29 | // 30 | // var a string = "Hello" 31 | // var b string = "Hello" 32 | // 33 | // assert.Equal(a, b, "The two words should be the same.") 34 | // } 35 | // 36 | // Assertions 37 | // 38 | // Assertions allow you to easily write test code, and are global funcs in the `assert` package. 39 | // All assertion functions take, as the first argument, the `*testing.T` object provided by the 40 | // testing framework. This allows the assertion funcs to write the failings and other details to 41 | // the correct place. 42 | // 43 | // Every assertion function also takes an optional string message as the final argument, 44 | // allowing custom error messages to be appended to the message the assertion method outputs. 45 | package assert 46 | -------------------------------------------------------------------------------- /vendor/github.com/davecgh/go-spew/spew/bypasssafe.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Dave Collins 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | // NOTE: Due to the following build constraints, this file will only be compiled 16 | // when either the code is running on Google App Engine or "-tags disableunsafe" 17 | // is added to the go build command line. 18 | // +build appengine disableunsafe 19 | 20 | package spew 21 | 22 | import "reflect" 23 | 24 | const ( 25 | // UnsafeDisabled is a build-time constant which specifies whether or 26 | // not access to the unsafe package is available. 27 | UnsafeDisabled = true 28 | ) 29 | 30 | // unsafeReflectValue typically converts the passed reflect.Value into a one 31 | // that bypasses the typical safety restrictions preventing access to 32 | // unaddressable and unexported data. However, doing this relies on access to 33 | // the unsafe package. This is a stub version which simply returns the passed 34 | // reflect.Value when the unsafe package is not available. 35 | func unsafeReflectValue(v reflect.Value) reflect.Value { 36 | return v 37 | } 38 | -------------------------------------------------------------------------------- /vendor/github.com/alecthomas/gozmq/zmq_4_x.go: -------------------------------------------------------------------------------- 1 | // +build zmq_4_x 2 | 3 | /* 4 | Copyright 2010-2012 Alec Thomas 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | package gozmq 20 | 21 | /* 22 | #cgo !windows pkg-config: libzmq 23 | #include 24 | #include 25 | #include 26 | */ 27 | import "C" 28 | 29 | const ( 30 | IPV6 = IntSocketOption(C.ZMQ_IPV6) 31 | IMMEDIATE = IntSocketOption(C.ZMQ_IMMEDIATE) 32 | MECHANISM = IntSocketOption(C.ZMQ_MECHANISM) 33 | PLAIN_SERVER = IntSocketOption(C.ZMQ_PLAIN_SERVER) 34 | PLAIN_USERNAME = StringSocketOption(C.ZMQ_PLAIN_USERNAME) 35 | PLAIN_PASSWORD = StringSocketOption(C.ZMQ_PLAIN_PASSWORD) 36 | CURVE_PUBLICKEY = StringSocketOption(C.ZMQ_CURVE_PUBLICKEY) 37 | CURVE_SECRETKEY = StringSocketOption(C.ZMQ_CURVE_SECRETKEY) 38 | CURVE_SERVERKEY = StringSocketOption(C.ZMQ_CURVE_SERVERKEY) 39 | ZAP_DOMAIN = StringSocketOption(C.ZMQ_ZAP_DOMAIN) 40 | ROUTER_RAW = IntSocketOption(C.ZMQ_ROUTER_RAW) 41 | PROBE_ROUTER = IntSocketOption(C.ZMQ_PROBE_ROUTER) 42 | REQ_CORRELATE = IntSocketOption(C.ZMQ_REQ_CORRELATE) 43 | REQ_RELAXED = IntSocketOption(C.ZMQ_REQ_RELAXED) 44 | CURVE_SERVER = IntSocketOption(C.ZMQ_CURVE_SERVER) 45 | CONFLATE = IntSocketOption(C.ZMQ_CONFLATE) 46 | ) 47 | -------------------------------------------------------------------------------- /vendor/github.com/motemen/go-quickfix/README.adoc: -------------------------------------------------------------------------------- 1 | = goquickfix image:https://travis-ci.org/motemen/go-quickfix.svg?branch=master["Build Status", link="https://travis-ci.org/motemen/go-quickfix"] image:http://godoc.org/github.com/motemen/go-quickfix?status.svg["GoDoc", link="http://godoc.org/github.com/motemen/go-quickfix"] image:http://gocover.io/_badge/github.com/motemen/go-quickfix["Test Coverage", link="http://gocover.io/github.com/motemen/go-quickfix"] 2 | 3 | The goquickfix command quick fixes Go source that is well typed but 4 | Go refuses to compile e.g. "x declared and not used". 5 | 6 | == Installation 7 | 8 | go get github.com/motemen/go-quickfix/cmd/goquickfix 9 | 10 | == Usage 11 | 12 | goquickfix [-w] [-revert] ... 13 | 14 | Flags: 15 | -revert=false: try to revert possible quickfixes introduced by goquickfix 16 | -w=false: write result to (source) file instead of stdout 17 | 18 | == Description 19 | 20 | While coding, sometimes you may write a Go program that is completely well typed 21 | but `go build` (or `run` or `test`) refuses to build, like this: 22 | 23 | [source,go] 24 | ---- 25 | package main 26 | 27 | import ( 28 | "fmt" 29 | "log" 30 | ) 31 | 32 | func main() { 33 | nums := []int{3, 1, 4, 1, 5} 34 | for i, n := range nums { 35 | fmt.Println(n) 36 | } 37 | } 38 | ---- 39 | 40 | The Go compiler will complain: 41 | 42 | eg.go:5: imported and not used: "log" 43 | 44 | Or 45 | 46 | eg.go:9: i declared and not used 47 | 48 | Do we have to bother to comment out the import line or remove 49 | the unused identifier one by one for the Go compiler? Of course no, 50 | `goquickfix` does the work instead of you. 51 | 52 | Run 53 | 54 | goquickfix -w eg.go 55 | 56 | and you will get the source rewritten so that Go compiles it well without 57 | changing the semantics: 58 | 59 | [source,go] 60 | ---- 61 | package main 62 | 63 | import ( 64 | "fmt" 65 | _ "log" 66 | ) 67 | 68 | func main() { 69 | nums := []int{3, 1, 4, 1, 5} 70 | for i, n := range nums { 71 | fmt.Println(n) 72 | _ = i 73 | } 74 | } 75 | ---- 76 | 77 | Now you can `go run` or `go test` your code safely. 78 | 79 | == TODO 80 | 81 | * `-d` option to show diffs 82 | * `-hard=true` option to remove erroneous code rather than adding new code 83 | -------------------------------------------------------------------------------- /zmq-win/include/zmq_utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file 3 | 4 | This file is part of libzmq, the ZeroMQ core engine in C++. 5 | 6 | libzmq is free software; you can redistribute it and/or modify it under 7 | the terms of the GNU Lesser General Public License (LGPL) as published 8 | by the Free Software Foundation; either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | As a special exception, the Contributors give you permission to link 12 | this library with independent modules to produce an executable, 13 | regardless of the license terms of these independent modules, and to 14 | copy and distribute the resulting executable under terms of your choice, 15 | provided that you also meet, for each linked independent module, the 16 | terms and conditions of the license of that module. An independent 17 | module is a module which is not derived from or based on this library. 18 | If you modify this library, you must extend this exception to your 19 | version of the library. 20 | 21 | libzmq is distributed in the hope that it will be useful, but WITHOUT 22 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 24 | License for more details. 25 | 26 | You should have received a copy of the GNU Lesser General Public License 27 | along with this program. If not, see . 28 | */ 29 | 30 | /* This file is deprecated, and all its functionality provided by zmq.h */ 31 | /* Note that -Wpedantic compilation requires GCC to avoid using its custom 32 | extensions such as #warning, hence the trick below. Also, pragmas for 33 | warnings or other messages are not standard, not portable, and not all 34 | compilers even have an equivalent concept. 35 | So in the worst case, this include file is treated as silently empty. */ 36 | 37 | #if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) || defined(_MSC_VER) 38 | #if defined(__GNUC__) || defined(__GNUG__) 39 | #pragma GCC diagnostic push 40 | #pragma GCC diagnostic warning "-Wcpp" 41 | #pragma GCC diagnostic ignored "-Werror" 42 | #pragma GCC diagnostic ignored "-Wall" 43 | #endif 44 | #pragma message("Warning: zmq_utils.h is deprecated. All its functionality is provided by zmq.h.") 45 | #if defined(__GNUC__) || defined(__GNUG__) 46 | #pragma GCC diagnostic pop 47 | #endif 48 | #endif 49 | -------------------------------------------------------------------------------- /gophernotes_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | 6 | repl "github.com/gopherds/gophernotes/internal/repl" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | // noError is a helper function for testing 11 | func noError(t *testing.T, err error) { 12 | if err != nil { 13 | t.Fatal(err) 14 | } 15 | } 16 | 17 | // TestStub is a canary test to make sure testing and testify are good to go 18 | func TestStub(t *testing.T) { 19 | assert.True(t, true, "This is good. Canary test passing") 20 | } 21 | 22 | // TestRun_import tests importing and use of a package 23 | func TestRun_import(t *testing.T) { 24 | s, err := repl.NewSession() 25 | noError(t, err) 26 | 27 | codes := []string{ 28 | ":import encoding/json", 29 | "b, err := json.Marshal(nil)", 30 | "string(b)", 31 | } 32 | 33 | for _, code := range codes { 34 | _, _, err := s.Eval(code) 35 | noError(t, err) 36 | } 37 | } 38 | 39 | // TestRun_QuickFix_evaluated_but_not_used makes sure errors are not thrown for 40 | // evaluations of variables that aren't used 41 | func TestRun_QuickFix_evaluated_but_not_used(t *testing.T) { 42 | s, err := repl.NewSession() 43 | noError(t, err) 44 | 45 | codes := []string{ 46 | `[]byte("")`, 47 | `make([]int, 0)`, 48 | `1+1`, 49 | `func() {}`, 50 | `(4 & (1 << 1))`, 51 | `1`, 52 | } 53 | 54 | for _, code := range codes { 55 | _, _, err := s.Eval(code) 56 | noError(t, err) 57 | } 58 | } 59 | 60 | // TestRun_QuickFix_used_as_value tests assignment of values to variables 61 | // and subsequent use 62 | func TestRun_QuickFix_used_as_value(t *testing.T) { 63 | s, err := repl.NewSession() 64 | noError(t, err) 65 | 66 | codes := []string{ 67 | `:import log`, 68 | `a := 1`, 69 | `log.SetPrefix("")`, 70 | } 71 | 72 | for _, code := range codes { 73 | _, _, err := s.Eval(code) 74 | noError(t, err) 75 | } 76 | } 77 | 78 | // TestRun_Copy tests a copy within the replpkg 79 | func TestRun_Copy(t *testing.T) { 80 | s, err := repl.NewSession() 81 | noError(t, err) 82 | 83 | codes := []string{ 84 | `a := []string{"hello", "world"}`, 85 | `b := []string{"goodbye", "world"}`, 86 | `copy(a, b)`, 87 | `if (a[0] != "goodbye") { 88 | panic("should be copied") 89 | }`, 90 | } 91 | 92 | for _, code := range codes { 93 | _, _, err := s.Eval(code) 94 | noError(t, err) 95 | } 96 | } 97 | 98 | // TestRun_Const tests a constant within the replpkg 99 | func TestRun_Const(t *testing.T) { 100 | s, err := repl.NewSession() 101 | noError(t, err) 102 | 103 | codes := []string{ 104 | `const ( a = iota; b )`, 105 | `a`, 106 | `b`, 107 | } 108 | 109 | for _, code := range codes { 110 | _, _, err := s.Eval(code) 111 | noError(t, err) 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/imports/mkstdlib.go: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | // mkstdlib generates the zstdlib.go file, containing the Go standard 4 | // library API symbols. It's baked into the binary to avoid scanning 5 | // GOPATH in the common case. 6 | package main 7 | 8 | import ( 9 | "bufio" 10 | "bytes" 11 | "fmt" 12 | "go/format" 13 | "io" 14 | "io/ioutil" 15 | "log" 16 | "os" 17 | "path" 18 | "path/filepath" 19 | "regexp" 20 | "sort" 21 | "strings" 22 | ) 23 | 24 | func mustOpen(name string) io.Reader { 25 | f, err := os.Open(name) 26 | if err != nil { 27 | log.Fatal(err) 28 | } 29 | return f 30 | } 31 | 32 | func api(base string) string { 33 | return filepath.Join(os.Getenv("GOROOT"), "api", base) 34 | } 35 | 36 | var sym = regexp.MustCompile(`^pkg (\S+).*?, (?:var|func|type|const) ([A-Z]\w*)`) 37 | 38 | func main() { 39 | var buf bytes.Buffer 40 | outf := func(format string, args ...interface{}) { 41 | fmt.Fprintf(&buf, format, args...) 42 | } 43 | outf("// AUTO-GENERATED BY mkstdlib.go\n\n") 44 | outf("package imports\n") 45 | outf("var stdlib = map[string]string{\n") 46 | f := io.MultiReader( 47 | mustOpen(api("go1.txt")), 48 | mustOpen(api("go1.1.txt")), 49 | mustOpen(api("go1.2.txt")), 50 | mustOpen(api("go1.3.txt")), 51 | mustOpen(api("go1.4.txt")), 52 | mustOpen(api("go1.5.txt")), 53 | mustOpen(api("go1.6.txt")), 54 | ) 55 | sc := bufio.NewScanner(f) 56 | fullImport := map[string]string{} // "zip.NewReader" => "archive/zip" 57 | ambiguous := map[string]bool{} 58 | var keys []string 59 | for sc.Scan() { 60 | l := sc.Text() 61 | has := func(v string) bool { return strings.Contains(l, v) } 62 | if has("struct, ") || has("interface, ") || has(", method (") { 63 | continue 64 | } 65 | if m := sym.FindStringSubmatch(l); m != nil { 66 | full := m[1] 67 | key := path.Base(full) + "." + m[2] 68 | if exist, ok := fullImport[key]; ok { 69 | if exist != full { 70 | ambiguous[key] = true 71 | } 72 | } else { 73 | fullImport[key] = full 74 | keys = append(keys, key) 75 | } 76 | } 77 | } 78 | if err := sc.Err(); err != nil { 79 | log.Fatal(err) 80 | } 81 | sort.Strings(keys) 82 | for _, key := range keys { 83 | if ambiguous[key] { 84 | outf("\t// %q is ambiguous\n", key) 85 | } else { 86 | outf("\t%q: %q,\n", key, fullImport[key]) 87 | } 88 | } 89 | outf("\n") 90 | for _, sym := range [...]string{"Alignof", "ArbitraryType", "Offsetof", "Pointer", "Sizeof"} { 91 | outf("\t%q: %q,\n", "unsafe."+sym, "unsafe") 92 | } 93 | outf("}\n") 94 | fmtbuf, err := format.Source(buf.Bytes()) 95 | if err != nil { 96 | log.Fatal(err) 97 | } 98 | err = ioutil.WriteFile("zstdlib.go", fmtbuf, 0666) 99 | if err != nil { 100 | log.Fatal(err) 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /execution.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "go/token" 6 | 7 | repl "github.com/gopherds/gophernotes/internal/repl" 8 | ) 9 | 10 | var ( 11 | // REPLSession manages the I/O to/from the notebook. 12 | REPLSession *repl.Session 13 | fset *token.FileSet 14 | ) 15 | 16 | // ExecCounter is incremented each time we run user code in the notebook. 17 | var ExecCounter int 18 | 19 | // SetupExecutionEnvironment initializes the REPL session and set of tmp files. 20 | func SetupExecutionEnvironment() { 21 | 22 | var err error 23 | REPLSession, err = repl.NewSession() 24 | if err != nil { 25 | panic(err) 26 | } 27 | 28 | fset = token.NewFileSet() 29 | } 30 | 31 | // OutputMsg holds the data for a pyout message. 32 | type OutputMsg struct { 33 | Execcount int `json:"execution_count"` 34 | Data map[string]string `json:"data"` 35 | Metadata map[string]interface{} `json:"metadata"` 36 | } 37 | 38 | // ErrMsg encodes the traceback of errors output to the notebook. 39 | type ErrMsg struct { 40 | EName string `json:"ename"` 41 | EValue string `json:"evalue"` 42 | Traceback []string `json:"traceback"` 43 | } 44 | 45 | // HandleExecuteRequest runs code from an execute_request method, and sends the various 46 | // reply messages. 47 | func HandleExecuteRequest(receipt MsgReceipt) { 48 | 49 | reply := NewMsg("execute_reply", receipt.Msg) 50 | content := make(map[string]interface{}) 51 | reqcontent := receipt.Msg.Content.(map[string]interface{}) 52 | code := reqcontent["code"].(string) 53 | silent := reqcontent["silent"].(bool) 54 | if !silent { 55 | ExecCounter++ 56 | } 57 | content["execution_count"] = ExecCounter 58 | 59 | // Do the compilation/execution magic. 60 | val, stderr, err := REPLSession.Eval(code) 61 | 62 | if err == nil { 63 | content["status"] = "ok" 64 | content["payload"] = make([]map[string]interface{}, 0) 65 | content["user_variables"] = make(map[string]string) 66 | content["user_expressions"] = make(map[string]string) 67 | if len(val) > 0 && !silent { 68 | var outContent OutputMsg 69 | out := NewMsg("pyout", receipt.Msg) 70 | outContent.Execcount = ExecCounter 71 | outContent.Data = make(map[string]string) 72 | outContent.Data["text/plain"] = fmt.Sprint(val) 73 | outContent.Metadata = make(map[string]interface{}) 74 | out.Content = outContent 75 | receipt.SendResponse(receipt.Sockets.IOPubSocket, out) 76 | } 77 | } else { 78 | content["status"] = "error" 79 | content["ename"] = "ERROR" 80 | content["evalue"] = err.Error() 81 | content["traceback"] = []string{stderr.String()} 82 | errormsg := NewMsg("pyerr", receipt.Msg) 83 | errormsg.Content = ErrMsg{"Error", err.Error(), []string{stderr.String()}} 84 | receipt.SendResponse(receipt.Sockets.IOPubSocket, errormsg) 85 | } 86 | 87 | // send the output back to the notebook 88 | reply.Content = content 89 | receipt.SendResponse(receipt.Sockets.ShellSocket, reply) 90 | idle := NewMsg("status", receipt.Msg) 91 | idle.Content = KernelStatus{"idle"} 92 | receipt.SendResponse(receipt.Sockets.IOPubSocket, idle) 93 | } 94 | -------------------------------------------------------------------------------- /vendor/github.com/alecthomas/gozmq/zmq_2_x.go: -------------------------------------------------------------------------------- 1 | // +build !zmq_3_x,!zmq_4_x 2 | 3 | /* 4 | Copyright 2010-2012 Alec Thomas 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | package gozmq 20 | 21 | /* 22 | #cgo !windows pkg-config: libzmq 23 | #include 24 | #include 25 | #include 26 | */ 27 | import "C" 28 | import "unsafe" 29 | 30 | const ( 31 | RCVMORE = UInt64SocketOption(C.ZMQ_RCVMORE) 32 | RECOVERY_IVL_MSEC = Int64SocketOption(C.ZMQ_RECOVERY_IVL_MSEC) 33 | SWAP = Int64SocketOption(C.ZMQ_SWAP) 34 | MCAST_LOOP = Int64SocketOption(C.ZMQ_MCAST_LOOP) 35 | HWM = UInt64SocketOption(C.ZMQ_HWM) 36 | NOBLOCK = SendRecvOption(C.ZMQ_NOBLOCK) 37 | 38 | // Forwards-compatible aliases: 39 | DONTWAIT = NOBLOCK 40 | ) 41 | 42 | // Get a context option. 43 | func (c *Context) IOThreads() (int, error) { 44 | return c.iothreads, nil 45 | } 46 | 47 | // Set a context option. 48 | func (c *Context) SetIOThreads(value int) error { 49 | c.iothreads = value 50 | return nil 51 | } 52 | 53 | // Send a message to the socket. 54 | // int zmq_send (void *s, zmq_msg_t *msg, int flags); 55 | func (s *Socket) Send(data []byte, flags SendRecvOption) error { 56 | var m C.zmq_msg_t 57 | // Copy data array into C-allocated buffer. 58 | size := C.size_t(len(data)) 59 | 60 | if rc, err := C.zmq_msg_init_size(&m, size); rc != 0 { 61 | return casterr(err) 62 | } 63 | 64 | if size > 0 { 65 | // FIXME Ideally this wouldn't require a copy. 66 | C.memcpy(C.zmq_msg_data(&m), unsafe.Pointer(&data[0]), size) // XXX I hope this works...(seems to) 67 | } 68 | 69 | if rc, err := C.zmq_send(s.s, &m, C.int(flags)); rc != 0 { 70 | // zmq_send did not take ownership, free message 71 | C.zmq_msg_close(&m) 72 | return casterr(err) 73 | } 74 | return nil 75 | } 76 | 77 | // Receive a message from the socket. 78 | // int zmq_recv (void *s, zmq_msg_t *msg, int flags); 79 | func (s *Socket) Recv(flags SendRecvOption) (data []byte, err error) { 80 | // Allocate and initialise a new zmq_msg_t 81 | var m C.zmq_msg_t 82 | var rc C.int 83 | if rc, err = C.zmq_msg_init(&m); rc != 0 { 84 | err = casterr(err) 85 | return 86 | } 87 | defer C.zmq_msg_close(&m) 88 | // Receive into message 89 | if rc, err = C.zmq_recv(s.s, &m, C.int(flags)); rc != 0 { 90 | err = casterr(err) 91 | return 92 | } 93 | err = nil 94 | // Copy message data into a byte array 95 | // FIXME Ideally this wouldn't require a copy. 96 | size := C.zmq_msg_size(&m) 97 | if size > 0 { 98 | data = C.GoBytes(C.zmq_msg_data(&m), C.int(size)) 99 | } else { 100 | data = nil 101 | } 102 | return 103 | } 104 | 105 | // Portability helper 106 | func (s *Socket) getRcvmore() (more bool, err error) { 107 | value, err := s.GetSockOptUInt64(RCVMORE) 108 | more = value != 0 109 | return 110 | } 111 | -------------------------------------------------------------------------------- /examples/Simple-Example.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Imports" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": 1, 13 | "metadata": { 14 | "collapsed": true 15 | }, 16 | "outputs": [], 17 | "source": [ 18 | "import \"fmt\"" 19 | ] 20 | }, 21 | { 22 | "cell_type": "markdown", 23 | "metadata": {}, 24 | "source": [ 25 | "# Hello World" 26 | ] 27 | }, 28 | { 29 | "cell_type": "code", 30 | "execution_count": 2, 31 | "metadata": { 32 | "collapsed": false 33 | }, 34 | "outputs": [ 35 | { 36 | "data": { 37 | "text/plain": [ 38 | "\u001b[31m\u001b[1m\"\u001b[0m\u001b[31mworld\u001b[0m\u001b[31m\u001b[1m\"\u001b[0m\n" 39 | ] 40 | }, 41 | "execution_count": 2, 42 | "metadata": {}, 43 | "output_type": "execute_result" 44 | } 45 | ], 46 | "source": [ 47 | "world := \"world\"" 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": 3, 53 | "metadata": { 54 | "collapsed": false 55 | }, 56 | "outputs": [ 57 | { 58 | "data": { 59 | "text/plain": [ 60 | "\u001b[31m\u001b[1m\"\u001b[0m\u001b[31mhello world\u001b[0m\u001b[31m\u001b[1m\"\u001b[0m\n" 61 | ] 62 | }, 63 | "execution_count": 3, 64 | "metadata": {}, 65 | "output_type": "execute_result" 66 | } 67 | ], 68 | "source": [ 69 | "fmt.Sprintf(\"hello %s\", world)" 70 | ] 71 | }, 72 | { 73 | "cell_type": "markdown", 74 | "metadata": {}, 75 | "source": [ 76 | "# Channels" 77 | ] 78 | }, 79 | { 80 | "cell_type": "markdown", 81 | "metadata": {}, 82 | "source": [ 83 | "Here is a simple example of a channel. " 84 | ] 85 | }, 86 | { 87 | "cell_type": "code", 88 | "execution_count": 4, 89 | "metadata": { 90 | "collapsed": false 91 | }, 92 | "outputs": [ 93 | { 94 | "data": { 95 | "text/plain": [ 96 | "(\u001b[32mchan string\u001b[0m)(\u001b[34m\u001b[1m0xc4200180c0\u001b[0m)\n" 97 | ] 98 | }, 99 | "execution_count": 4, 100 | "metadata": {}, 101 | "output_type": "execute_result" 102 | } 103 | ], 104 | "source": [ 105 | "messages := make(chan string)" 106 | ] 107 | }, 108 | { 109 | "cell_type": "code", 110 | "execution_count": 5, 111 | "metadata": { 112 | "collapsed": true 113 | }, 114 | "outputs": [], 115 | "source": [ 116 | "go func() { messages <- \"ping\" }()" 117 | ] 118 | }, 119 | { 120 | "cell_type": "code", 121 | "execution_count": 6, 122 | "metadata": { 123 | "collapsed": false 124 | }, 125 | "outputs": [ 126 | { 127 | "data": { 128 | "text/plain": [ 129 | "\u001b[31m\u001b[1m\"\u001b[0m\u001b[31mping\u001b[0m\u001b[31m\u001b[1m\"\u001b[0m\n" 130 | ] 131 | }, 132 | "execution_count": 6, 133 | "metadata": {}, 134 | "output_type": "execute_result" 135 | } 136 | ], 137 | "source": [ 138 | "msg := <- messages" 139 | ] 140 | } 141 | ], 142 | "metadata": { 143 | "kernelspec": { 144 | "display_name": "Golang", 145 | "language": "go", 146 | "name": "gophernotes" 147 | }, 148 | "language_info": { 149 | "name": "go" 150 | } 151 | }, 152 | "nbformat": 4, 153 | "nbformat_minor": 0 154 | } 155 | -------------------------------------------------------------------------------- /vendor/github.com/mitchellh/go-homedir/homedir.go: -------------------------------------------------------------------------------- 1 | package homedir 2 | 3 | import ( 4 | "bytes" 5 | "errors" 6 | "os" 7 | "os/exec" 8 | "path/filepath" 9 | "runtime" 10 | "strconv" 11 | "strings" 12 | "sync" 13 | ) 14 | 15 | // DisableCache will disable caching of the home directory. Caching is enabled 16 | // by default. 17 | var DisableCache bool 18 | 19 | var homedirCache string 20 | var cacheLock sync.RWMutex 21 | 22 | // Dir returns the home directory for the executing user. 23 | // 24 | // This uses an OS-specific method for discovering the home directory. 25 | // An error is returned if a home directory cannot be detected. 26 | func Dir() (string, error) { 27 | if !DisableCache { 28 | cacheLock.RLock() 29 | cached := homedirCache 30 | cacheLock.RUnlock() 31 | if cached != "" { 32 | return cached, nil 33 | } 34 | } 35 | 36 | cacheLock.Lock() 37 | defer cacheLock.Unlock() 38 | 39 | var result string 40 | var err error 41 | if runtime.GOOS == "windows" { 42 | result, err = dirWindows() 43 | } else { 44 | // Unix-like system, so just assume Unix 45 | result, err = dirUnix() 46 | } 47 | 48 | if err != nil { 49 | return "", err 50 | } 51 | homedirCache = result 52 | return result, nil 53 | } 54 | 55 | // Expand expands the path to include the home directory if the path 56 | // is prefixed with `~`. If it isn't prefixed with `~`, the path is 57 | // returned as-is. 58 | func Expand(path string) (string, error) { 59 | if len(path) == 0 { 60 | return path, nil 61 | } 62 | 63 | if path[0] != '~' { 64 | return path, nil 65 | } 66 | 67 | if len(path) > 1 && path[1] != '/' && path[1] != '\\' { 68 | return "", errors.New("cannot expand user-specific home dir") 69 | } 70 | 71 | dir, err := Dir() 72 | if err != nil { 73 | return "", err 74 | } 75 | 76 | return filepath.Join(dir, path[1:]), nil 77 | } 78 | 79 | func dirUnix() (string, error) { 80 | // First prefer the HOME environmental variable 81 | if home := os.Getenv("HOME"); home != "" { 82 | return home, nil 83 | } 84 | 85 | // If that fails, try getent 86 | var stdout bytes.Buffer 87 | cmd := exec.Command("getent", "passwd", strconv.Itoa(os.Getuid())) 88 | cmd.Stdout = &stdout 89 | if err := cmd.Run(); err != nil { 90 | // If "getent" is missing, ignore it 91 | if err != exec.ErrNotFound { 92 | return "", err 93 | } 94 | } else { 95 | if passwd := strings.TrimSpace(stdout.String()); passwd != "" { 96 | // username:password:uid:gid:gecos:home:shell 97 | passwdParts := strings.SplitN(passwd, ":", 7) 98 | if len(passwdParts) > 5 { 99 | return passwdParts[5], nil 100 | } 101 | } 102 | } 103 | 104 | // If all else fails, try the shell 105 | stdout.Reset() 106 | cmd = exec.Command("sh", "-c", "cd && pwd") 107 | cmd.Stdout = &stdout 108 | if err := cmd.Run(); err != nil { 109 | return "", err 110 | } 111 | 112 | result := strings.TrimSpace(stdout.String()) 113 | if result == "" { 114 | return "", errors.New("blank output when reading home directory") 115 | } 116 | 117 | return result, nil 118 | } 119 | 120 | func dirWindows() (string, error) { 121 | drive := os.Getenv("HOMEDRIVE") 122 | path := os.Getenv("HOMEPATH") 123 | home := drive + path 124 | if drive == "" || path == "" { 125 | home = os.Getenv("USERPROFILE") 126 | } 127 | if home == "" { 128 | return "", errors.New("HOMEDRIVE, HOMEPATH, and USERPROFILE are blank") 129 | } 130 | 131 | return home, nil 132 | } 133 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/imports/fastwalk_unix.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build linux darwin freebsd openbsd netbsd 6 | 7 | package imports 8 | 9 | import ( 10 | "bytes" 11 | "fmt" 12 | "os" 13 | "syscall" 14 | "unsafe" 15 | ) 16 | 17 | const blockSize = 8 << 10 18 | 19 | // unknownFileMode is a sentinel (and bogus) os.FileMode 20 | // value used to represent a syscall.DT_UNKNOWN Dirent.Type. 21 | const unknownFileMode os.FileMode = os.ModeNamedPipe | os.ModeSocket | os.ModeDevice 22 | 23 | func readDir(dirName string, fn func(dirName, entName string, typ os.FileMode) error) error { 24 | fd, err := syscall.Open(dirName, 0, 0) 25 | if err != nil { 26 | return err 27 | } 28 | defer syscall.Close(fd) 29 | 30 | // The buffer must be at least a block long. 31 | buf := make([]byte, blockSize) // stack-allocated; doesn't escape 32 | bufp := 0 // starting read position in buf 33 | nbuf := 0 // end valid data in buf 34 | for { 35 | if bufp >= nbuf { 36 | bufp = 0 37 | nbuf, err = syscall.ReadDirent(fd, buf) 38 | if err != nil { 39 | return os.NewSyscallError("readdirent", err) 40 | } 41 | if nbuf <= 0 { 42 | return nil 43 | } 44 | } 45 | consumed, name, typ := parseDirEnt(buf[bufp:nbuf]) 46 | bufp += consumed 47 | if name == "" || name == "." || name == ".." { 48 | continue 49 | } 50 | // Fallback for filesystems (like old XFS) that don't 51 | // support Dirent.Type and have DT_UNKNOWN (0) there 52 | // instead. 53 | if typ == unknownFileMode { 54 | fi, err := os.Lstat(dirName + "/" + name) 55 | if err != nil { 56 | // It got deleted in the meantime. 57 | if os.IsNotExist(err) { 58 | continue 59 | } 60 | return err 61 | } 62 | typ = fi.Mode() & os.ModeType 63 | } 64 | if err := fn(dirName, name, typ); err != nil { 65 | return err 66 | } 67 | } 68 | } 69 | 70 | func parseDirEnt(buf []byte) (consumed int, name string, typ os.FileMode) { 71 | // golang.org/issue/15653 72 | dirent := (*syscall.Dirent)(unsafe.Pointer(&buf[0])) 73 | if v := unsafe.Offsetof(dirent.Reclen) + unsafe.Sizeof(dirent.Reclen); uintptr(len(buf)) < v { 74 | panic(fmt.Sprintf("buf size of %d smaller than dirent header size %d", len(buf), v)) 75 | } 76 | if len(buf) < int(dirent.Reclen) { 77 | panic(fmt.Sprintf("buf size %d < record length %d", len(buf), dirent.Reclen)) 78 | } 79 | consumed = int(dirent.Reclen) 80 | if direntInode(dirent) == 0 { // File absent in directory. 81 | return 82 | } 83 | switch dirent.Type { 84 | case syscall.DT_REG: 85 | typ = 0 86 | case syscall.DT_DIR: 87 | typ = os.ModeDir 88 | case syscall.DT_LNK: 89 | typ = os.ModeSymlink 90 | case syscall.DT_BLK: 91 | typ = os.ModeDevice 92 | case syscall.DT_FIFO: 93 | typ = os.ModeNamedPipe 94 | case syscall.DT_SOCK: 95 | typ = os.ModeSocket 96 | case syscall.DT_UNKNOWN: 97 | typ = unknownFileMode 98 | default: 99 | // Skip weird things. 100 | // It's probably a DT_WHT (http://lwn.net/Articles/325369/) 101 | // or something. Revisit if/when this package is moved outside 102 | // of goimports. goimports only cares about regular files, 103 | // symlinks, and directories. 104 | return 105 | } 106 | 107 | nameBuf := (*[unsafe.Sizeof(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0])) 108 | nameLen := bytes.IndexByte(nameBuf[:], 0) 109 | if nameLen < 0 { 110 | panic("failed to find terminating 0 byte in dirent") 111 | } 112 | 113 | // Special cases for common things: 114 | if nameLen == 1 && nameBuf[0] == '.' { 115 | name = "." 116 | } else if nameLen == 2 && nameBuf[0] == '.' && nameBuf[1] == '.' { 117 | name = ".." 118 | } else { 119 | name = string(nameBuf[:nameLen]) 120 | } 121 | return 122 | } 123 | -------------------------------------------------------------------------------- /vendor/github.com/stretchr/testify/assert/http_assertions.go: -------------------------------------------------------------------------------- 1 | package assert 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | "net/http/httptest" 7 | "net/url" 8 | "strings" 9 | ) 10 | 11 | // httpCode is a helper that returns HTTP code of the response. It returns -1 12 | // if building a new request fails. 13 | func httpCode(handler http.HandlerFunc, method, url string, values url.Values) int { 14 | w := httptest.NewRecorder() 15 | req, err := http.NewRequest(method, url+"?"+values.Encode(), nil) 16 | if err != nil { 17 | return -1 18 | } 19 | handler(w, req) 20 | return w.Code 21 | } 22 | 23 | // HTTPSuccess asserts that a specified handler returns a success status code. 24 | // 25 | // assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil) 26 | // 27 | // Returns whether the assertion was successful (true) or not (false). 28 | func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool { 29 | code := httpCode(handler, method, url, values) 30 | if code == -1 { 31 | return false 32 | } 33 | return code >= http.StatusOK && code <= http.StatusPartialContent 34 | } 35 | 36 | // HTTPRedirect asserts that a specified handler returns a redirect status code. 37 | // 38 | // assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} 39 | // 40 | // Returns whether the assertion was successful (true) or not (false). 41 | func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool { 42 | code := httpCode(handler, method, url, values) 43 | if code == -1 { 44 | return false 45 | } 46 | return code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect 47 | } 48 | 49 | // HTTPError asserts that a specified handler returns an error status code. 50 | // 51 | // assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} 52 | // 53 | // Returns whether the assertion was successful (true) or not (false). 54 | func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool { 55 | code := httpCode(handler, method, url, values) 56 | if code == -1 { 57 | return false 58 | } 59 | return code >= http.StatusBadRequest 60 | } 61 | 62 | // HTTPBody is a helper that returns HTTP body of the response. It returns 63 | // empty string if building a new request fails. 64 | func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string { 65 | w := httptest.NewRecorder() 66 | req, err := http.NewRequest(method, url+"?"+values.Encode(), nil) 67 | if err != nil { 68 | return "" 69 | } 70 | handler(w, req) 71 | return w.Body.String() 72 | } 73 | 74 | // HTTPBodyContains asserts that a specified handler returns a 75 | // body that contains a string. 76 | // 77 | // assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky") 78 | // 79 | // Returns whether the assertion was successful (true) or not (false). 80 | func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}) bool { 81 | body := HTTPBody(handler, method, url, values) 82 | 83 | contains := strings.Contains(body, fmt.Sprint(str)) 84 | if !contains { 85 | Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)) 86 | } 87 | 88 | return contains 89 | } 90 | 91 | // HTTPBodyNotContains asserts that a specified handler returns a 92 | // body that does not contain a string. 93 | // 94 | // assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky") 95 | // 96 | // Returns whether the assertion was successful (true) or not (false). 97 | func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}) bool { 98 | body := HTTPBody(handler, method, url, values) 99 | 100 | contains := strings.Contains(body, fmt.Sprint(str)) 101 | if contains { 102 | Fail(t, "Expected response body for %s to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body) 103 | } 104 | 105 | return !contains 106 | } 107 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/imports/mkindex.go: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | // Copyright 2013 The Go Authors. All rights reserved. 4 | // Use of this source code is governed by a BSD-style 5 | // license that can be found in the LICENSE file. 6 | 7 | // Command mkindex creates the file "pkgindex.go" containing an index of the Go 8 | // standard library. The file is intended to be built as part of the imports 9 | // package, so that the package may be used in environments where a GOROOT is 10 | // not available (such as App Engine). 11 | package main 12 | 13 | import ( 14 | "bytes" 15 | "fmt" 16 | "go/ast" 17 | "go/build" 18 | "go/format" 19 | "go/parser" 20 | "go/token" 21 | "io/ioutil" 22 | "log" 23 | "os" 24 | "path" 25 | "path/filepath" 26 | "strings" 27 | ) 28 | 29 | var ( 30 | pkgIndex = make(map[string][]pkg) 31 | exports = make(map[string]map[string]bool) 32 | ) 33 | 34 | func main() { 35 | // Don't use GOPATH. 36 | ctx := build.Default 37 | ctx.GOPATH = "" 38 | 39 | // Populate pkgIndex global from GOROOT. 40 | for _, path := range ctx.SrcDirs() { 41 | f, err := os.Open(path) 42 | if err != nil { 43 | log.Print(err) 44 | continue 45 | } 46 | children, err := f.Readdir(-1) 47 | f.Close() 48 | if err != nil { 49 | log.Print(err) 50 | continue 51 | } 52 | for _, child := range children { 53 | if child.IsDir() { 54 | loadPkg(path, child.Name()) 55 | } 56 | } 57 | } 58 | // Populate exports global. 59 | for _, ps := range pkgIndex { 60 | for _, p := range ps { 61 | e := loadExports(p.dir) 62 | if e != nil { 63 | exports[p.dir] = e 64 | } 65 | } 66 | } 67 | 68 | // Construct source file. 69 | var buf bytes.Buffer 70 | fmt.Fprint(&buf, pkgIndexHead) 71 | fmt.Fprintf(&buf, "var pkgIndexMaster = %#v\n", pkgIndex) 72 | fmt.Fprintf(&buf, "var exportsMaster = %#v\n", exports) 73 | src := buf.Bytes() 74 | 75 | // Replace main.pkg type name with pkg. 76 | src = bytes.Replace(src, []byte("main.pkg"), []byte("pkg"), -1) 77 | // Replace actual GOROOT with "/go". 78 | src = bytes.Replace(src, []byte(ctx.GOROOT), []byte("/go"), -1) 79 | // Add some line wrapping. 80 | src = bytes.Replace(src, []byte("}, "), []byte("},\n"), -1) 81 | src = bytes.Replace(src, []byte("true, "), []byte("true,\n"), -1) 82 | 83 | var err error 84 | src, err = format.Source(src) 85 | if err != nil { 86 | log.Fatal(err) 87 | } 88 | 89 | // Write out source file. 90 | err = ioutil.WriteFile("pkgindex.go", src, 0644) 91 | if err != nil { 92 | log.Fatal(err) 93 | } 94 | } 95 | 96 | const pkgIndexHead = `package imports 97 | 98 | func init() { 99 | pkgIndexOnce.Do(func() { 100 | pkgIndex.m = pkgIndexMaster 101 | }) 102 | loadExports = func(dir string) map[string]bool { 103 | return exportsMaster[dir] 104 | } 105 | } 106 | ` 107 | 108 | type pkg struct { 109 | importpath string // full pkg import path, e.g. "net/http" 110 | dir string // absolute file path to pkg directory e.g. "/usr/lib/go/src/fmt" 111 | } 112 | 113 | var fset = token.NewFileSet() 114 | 115 | func loadPkg(root, importpath string) { 116 | shortName := path.Base(importpath) 117 | if shortName == "testdata" { 118 | return 119 | } 120 | 121 | dir := filepath.Join(root, importpath) 122 | pkgIndex[shortName] = append(pkgIndex[shortName], pkg{ 123 | importpath: importpath, 124 | dir: dir, 125 | }) 126 | 127 | pkgDir, err := os.Open(dir) 128 | if err != nil { 129 | return 130 | } 131 | children, err := pkgDir.Readdir(-1) 132 | pkgDir.Close() 133 | if err != nil { 134 | return 135 | } 136 | for _, child := range children { 137 | name := child.Name() 138 | if name == "" { 139 | continue 140 | } 141 | if c := name[0]; c == '.' || ('0' <= c && c <= '9') { 142 | continue 143 | } 144 | if child.IsDir() { 145 | loadPkg(root, filepath.Join(importpath, name)) 146 | } 147 | } 148 | } 149 | 150 | func loadExports(dir string) map[string]bool { 151 | exports := make(map[string]bool) 152 | buildPkg, err := build.ImportDir(dir, 0) 153 | if err != nil { 154 | if strings.Contains(err.Error(), "no buildable Go source files in") { 155 | return nil 156 | } 157 | log.Printf("could not import %q: %v", dir, err) 158 | return nil 159 | } 160 | for _, file := range buildPkg.GoFiles { 161 | f, err := parser.ParseFile(fset, filepath.Join(dir, file), nil, 0) 162 | if err != nil { 163 | log.Printf("could not parse %q: %v", file, err) 164 | continue 165 | } 166 | for name := range f.Scope.Objects { 167 | if ast.IsExported(name) { 168 | exports[name] = true 169 | } 170 | } 171 | } 172 | return exports 173 | } 174 | -------------------------------------------------------------------------------- /messages.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/hmac" 5 | "crypto/sha256" 6 | "encoding/hex" 7 | "encoding/json" 8 | "log" 9 | 10 | zmq "github.com/alecthomas/gozmq" 11 | uuid "github.com/nu7hatch/gouuid" 12 | "github.com/pkg/errors" 13 | ) 14 | 15 | // MsgHeader encodes header info for ZMQ messages. 16 | type MsgHeader struct { 17 | MsgID string `json:"msg_id"` 18 | Username string `json:"username"` 19 | Session string `json:"session"` 20 | MsgType string `json:"msg_type"` 21 | } 22 | 23 | // ComposedMsg represents an entire message in a high-level structure. 24 | type ComposedMsg struct { 25 | Header MsgHeader 26 | ParentHeader MsgHeader 27 | Metadata map[string]interface{} 28 | Content interface{} 29 | } 30 | 31 | // InvalidSignatureError is returned when the signature on a received message does not 32 | // validate. 33 | type InvalidSignatureError struct{} 34 | 35 | func (e *InvalidSignatureError) Error() string { 36 | return "A message had an invalid signature" 37 | } 38 | 39 | // WireMsgToComposedMsg translates a multipart ZMQ messages received from a socket into 40 | // a ComposedMsg struct and a slice of return identities. This includes verifying the 41 | // message signature. 42 | func WireMsgToComposedMsg(msgparts [][]byte, signkey []byte) (ComposedMsg, [][]byte, error) { 43 | 44 | i := 0 45 | for string(msgparts[i]) != "" { 46 | i++ 47 | } 48 | identities := msgparts[:i] 49 | 50 | // Validate signature 51 | var msg ComposedMsg 52 | if len(signkey) != 0 { 53 | mac := hmac.New(sha256.New, signkey) 54 | for _, msgpart := range msgparts[i+2 : i+6] { 55 | mac.Write(msgpart) 56 | } 57 | signature := make([]byte, hex.DecodedLen(len(msgparts[i+1]))) 58 | hex.Decode(signature, msgparts[i+1]) 59 | if !hmac.Equal(mac.Sum(nil), signature) { 60 | return msg, nil, &InvalidSignatureError{} 61 | } 62 | } 63 | json.Unmarshal(msgparts[i+2], &msg.Header) 64 | json.Unmarshal(msgparts[i+3], &msg.ParentHeader) 65 | json.Unmarshal(msgparts[i+4], &msg.Metadata) 66 | json.Unmarshal(msgparts[i+5], &msg.Content) 67 | return msg, identities, nil 68 | } 69 | 70 | // ToWireMsg translates a ComposedMsg into a multipart ZMQ message ready to send, and 71 | // signs it. This does not add the return identities or the delimiter. 72 | func (msg ComposedMsg) ToWireMsg(signkey []byte) ([][]byte, error) { 73 | 74 | msgparts := make([][]byte, 5) 75 | header, err := json.Marshal(msg.Header) 76 | if err != nil { 77 | return msgparts, errors.Wrap(err, "Could not marshal message header") 78 | } 79 | msgparts[1] = header 80 | 81 | parentHeader, err := json.Marshal(msg.ParentHeader) 82 | if err != nil { 83 | return msgparts, errors.Wrap(err, "Could not marshal parent header") 84 | } 85 | msgparts[2] = parentHeader 86 | 87 | if msg.Metadata == nil { 88 | msg.Metadata = make(map[string]interface{}) 89 | } 90 | metadata, err := json.Marshal(msg.Metadata) 91 | if err != nil { 92 | return msgparts, errors.Wrap(err, "Could not marshal metadata") 93 | } 94 | msgparts[3] = metadata 95 | 96 | content, err := json.Marshal(msg.Content) 97 | if err != nil { 98 | return msgparts, errors.Wrap(err, "Could not marshal content") 99 | } 100 | msgparts[4] = content 101 | 102 | // Sign the message. 103 | if len(signkey) != 0 { 104 | mac := hmac.New(sha256.New, signkey) 105 | for _, msgpart := range msgparts[1:] { 106 | mac.Write(msgpart) 107 | } 108 | msgparts[0] = make([]byte, hex.EncodedLen(mac.Size())) 109 | hex.Encode(msgparts[0], mac.Sum(nil)) 110 | } 111 | return msgparts, nil 112 | } 113 | 114 | // MsgReceipt represents a received message, its return identities, and the sockets for 115 | // communication. 116 | type MsgReceipt struct { 117 | Msg ComposedMsg 118 | Identities [][]byte 119 | Sockets SocketGroup 120 | } 121 | 122 | // SendResponse sends a message back to return identites of the received message. 123 | func (receipt *MsgReceipt) SendResponse(socket *zmq.Socket, msg ComposedMsg) { 124 | 125 | socket.SendMultipart(receipt.Identities, zmq.SNDMORE) 126 | socket.Send([]byte(""), zmq.SNDMORE) 127 | 128 | msgParts, err := msg.ToWireMsg(receipt.Sockets.Key) 129 | if err != nil { 130 | log.Fatalln(err) 131 | } 132 | socket.SendMultipart(msgParts, 0) 133 | logger.Println("<--", msg.Header.MsgType) 134 | logger.Printf("%+v\n", msg.Content) 135 | } 136 | 137 | // NewMsg creates a new ComposedMsg to respond to a parent message. This includes setting 138 | // up its headers. 139 | func NewMsg(msgType string, parent ComposedMsg) (msg ComposedMsg) { 140 | msg.ParentHeader = parent.Header 141 | msg.Header.Session = parent.Header.Session 142 | msg.Header.Username = parent.Header.Username 143 | msg.Header.MsgType = msgType 144 | u, err := uuid.NewV4() 145 | if err != nil { 146 | log.Fatalln(errors.Wrap(err, "Could not generate UUID")) 147 | } 148 | msg.Header.MsgID = u.String() 149 | return 150 | } 151 | -------------------------------------------------------------------------------- /examples/iris.csv: -------------------------------------------------------------------------------- 1 | 5.1,3.5,1.4,0.2,Iris-setosa 2 | 4.9,3.0,1.4,0.2,Iris-setosa 3 | 4.7,3.2,1.3,0.2,Iris-setosa 4 | 4.6,3.1,1.5,0.2,Iris-setosa 5 | 5.0,3.6,1.4,0.2,Iris-setosa 6 | 5.4,3.9,1.7,0.4,Iris-setosa 7 | 4.6,3.4,1.4,0.3,Iris-setosa 8 | 5.0,3.4,1.5,0.2,Iris-setosa 9 | 4.4,2.9,1.4,0.2,Iris-setosa 10 | 4.9,3.1,1.5,0.1,Iris-setosa 11 | 5.4,3.7,1.5,0.2,Iris-setosa 12 | 4.8,3.4,1.6,0.2,Iris-setosa 13 | 4.8,3.0,1.4,0.1,Iris-setosa 14 | 4.3,3.0,1.1,0.1,Iris-setosa 15 | 5.8,4.0,1.2,0.2,Iris-setosa 16 | 5.7,4.4,1.5,0.4,Iris-setosa 17 | 5.4,3.9,1.3,0.4,Iris-setosa 18 | 5.1,3.5,1.4,0.3,Iris-setosa 19 | 5.7,3.8,1.7,0.3,Iris-setosa 20 | 5.1,3.8,1.5,0.3,Iris-setosa 21 | 5.4,3.4,1.7,0.2,Iris-setosa 22 | 5.1,3.7,1.5,0.4,Iris-setosa 23 | 4.6,3.6,1.0,0.2,Iris-setosa 24 | 5.1,3.3,1.7,0.5,Iris-setosa 25 | 4.8,3.4,1.9,0.2,Iris-setosa 26 | 5.0,3.0,1.6,0.2,Iris-setosa 27 | 5.0,3.4,1.6,0.4,Iris-setosa 28 | 5.2,3.5,1.5,0.2,Iris-setosa 29 | 5.2,3.4,1.4,0.2,Iris-setosa 30 | 4.7,3.2,1.6,0.2,Iris-setosa 31 | 4.8,3.1,1.6,0.2,Iris-setosa 32 | 5.4,3.4,1.5,0.4,Iris-setosa 33 | 5.2,4.1,1.5,0.1,Iris-setosa 34 | 5.5,4.2,1.4,0.2,Iris-setosa 35 | 4.9,3.1,1.5,0.1,Iris-setosa 36 | 5.0,3.2,1.2,0.2,Iris-setosa 37 | 5.5,3.5,1.3,0.2,Iris-setosa 38 | 4.9,3.1,1.5,0.1,Iris-setosa 39 | 4.4,3.0,1.3,0.2,Iris-setosa 40 | 5.1,3.4,1.5,0.2,Iris-setosa 41 | 5.0,3.5,1.3,0.3,Iris-setosa 42 | 4.5,2.3,1.3,0.3,Iris-setosa 43 | 4.4,3.2,1.3,0.2,Iris-setosa 44 | 5.0,3.5,1.6,0.6,Iris-setosa 45 | 5.1,3.8,1.9,0.4,Iris-setosa 46 | 4.8,3.0,1.4,0.3,Iris-setosa 47 | 5.1,3.8,1.6,0.2,Iris-setosa 48 | 4.6,3.2,1.4,0.2,Iris-setosa 49 | 5.3,3.7,1.5,0.2,Iris-setosa 50 | 5.0,3.3,1.4,0.2,Iris-setosa 51 | 7.0,3.2,4.7,1.4,Iris-versicolor 52 | 6.4,3.2,4.5,1.5,Iris-versicolor 53 | 6.9,3.1,4.9,1.5,Iris-versicolor 54 | 5.5,2.3,4.0,1.3,Iris-versicolor 55 | 6.5,2.8,4.6,1.5,Iris-versicolor 56 | 5.7,2.8,4.5,1.3,Iris-versicolor 57 | 6.3,3.3,4.7,1.6,Iris-versicolor 58 | 4.9,2.4,3.3,1.0,Iris-versicolor 59 | 6.6,2.9,4.6,1.3,Iris-versicolor 60 | 5.2,2.7,3.9,1.4,Iris-versicolor 61 | 5.0,2.0,3.5,1.0,Iris-versicolor 62 | 5.9,3.0,4.2,1.5,Iris-versicolor 63 | 6.0,2.2,4.0,1.0,Iris-versicolor 64 | 6.1,2.9,4.7,1.4,Iris-versicolor 65 | 5.6,2.9,3.6,1.3,Iris-versicolor 66 | 6.7,3.1,4.4,1.4,Iris-versicolor 67 | 5.6,3.0,4.5,1.5,Iris-versicolor 68 | 5.8,2.7,4.1,1.0,Iris-versicolor 69 | 6.2,2.2,4.5,1.5,Iris-versicolor 70 | 5.6,2.5,3.9,1.1,Iris-versicolor 71 | 5.9,3.2,4.8,1.8,Iris-versicolor 72 | 6.1,2.8,4.0,1.3,Iris-versicolor 73 | 6.3,2.5,4.9,1.5,Iris-versicolor 74 | 6.1,2.8,4.7,1.2,Iris-versicolor 75 | 6.4,2.9,4.3,1.3,Iris-versicolor 76 | 6.6,3.0,4.4,1.4,Iris-versicolor 77 | 6.8,2.8,4.8,1.4,Iris-versicolor 78 | 6.7,3.0,5.0,1.7,Iris-versicolor 79 | 6.0,2.9,4.5,1.5,Iris-versicolor 80 | 5.7,2.6,3.5,1.0,Iris-versicolor 81 | 5.5,2.4,3.8,1.1,Iris-versicolor 82 | 5.5,2.4,3.7,1.0,Iris-versicolor 83 | 5.8,2.7,3.9,1.2,Iris-versicolor 84 | 6.0,2.7,5.1,1.6,Iris-versicolor 85 | 5.4,3.0,4.5,1.5,Iris-versicolor 86 | 6.0,3.4,4.5,1.6,Iris-versicolor 87 | 6.7,3.1,4.7,1.5,Iris-versicolor 88 | 6.3,2.3,4.4,1.3,Iris-versicolor 89 | 5.6,3.0,4.1,1.3,Iris-versicolor 90 | 5.5,2.5,4.0,1.3,Iris-versicolor 91 | 5.5,2.6,4.4,1.2,Iris-versicolor 92 | 6.1,3.0,4.6,1.4,Iris-versicolor 93 | 5.8,2.6,4.0,1.2,Iris-versicolor 94 | 5.0,2.3,3.3,1.0,Iris-versicolor 95 | 5.6,2.7,4.2,1.3,Iris-versicolor 96 | 5.7,3.0,4.2,1.2,Iris-versicolor 97 | 5.7,2.9,4.2,1.3,Iris-versicolor 98 | 6.2,2.9,4.3,1.3,Iris-versicolor 99 | 5.1,2.5,3.0,1.1,Iris-versicolor 100 | 5.7,2.8,4.1,1.3,Iris-versicolor 101 | 6.3,3.3,6.0,2.5,Iris-virginica 102 | 5.8,2.7,5.1,1.9,Iris-virginica 103 | 7.1,3.0,5.9,2.1,Iris-virginica 104 | 6.3,2.9,5.6,1.8,Iris-virginica 105 | 6.5,3.0,5.8,2.2,Iris-virginica 106 | 7.6,3.0,6.6,2.1,Iris-virginica 107 | 4.9,2.5,4.5,1.7,Iris-virginica 108 | 7.3,2.9,6.3,1.8,Iris-virginica 109 | 6.7,2.5,5.8,1.8,Iris-virginica 110 | 7.2,3.6,6.1,2.5,Iris-virginica 111 | 6.5,3.2,5.1,2.0,Iris-virginica 112 | 6.4,2.7,5.3,1.9,Iris-virginica 113 | 6.8,3.0,5.5,2.1,Iris-virginica 114 | 5.7,2.5,5.0,2.0,Iris-virginica 115 | 5.8,2.8,5.1,2.4,Iris-virginica 116 | 6.4,3.2,5.3,2.3,Iris-virginica 117 | 6.5,3.0,5.5,1.8,Iris-virginica 118 | 7.7,3.8,6.7,2.2,Iris-virginica 119 | 7.7,2.6,6.9,2.3,Iris-virginica 120 | 6.0,2.2,5.0,1.5,Iris-virginica 121 | 6.9,3.2,5.7,2.3,Iris-virginica 122 | 5.6,2.8,4.9,2.0,Iris-virginica 123 | 7.7,2.8,6.7,2.0,Iris-virginica 124 | 6.3,2.7,4.9,1.8,Iris-virginica 125 | 6.7,3.3,5.7,2.1,Iris-virginica 126 | 7.2,3.2,6.0,1.8,Iris-virginica 127 | 6.2,2.8,4.8,1.8,Iris-virginica 128 | 6.1,3.0,4.9,1.8,Iris-virginica 129 | 6.4,2.8,5.6,2.1,Iris-virginica 130 | 7.2,3.0,5.8,1.6,Iris-virginica 131 | 7.4,2.8,6.1,1.9,Iris-virginica 132 | 7.9,3.8,6.4,2.0,Iris-virginica 133 | 6.4,2.8,5.6,2.2,Iris-virginica 134 | 6.3,2.8,5.1,1.5,Iris-virginica 135 | 6.1,2.6,5.6,1.4,Iris-virginica 136 | 7.7,3.0,6.1,2.3,Iris-virginica 137 | 6.3,3.4,5.6,2.4,Iris-virginica 138 | 6.4,3.1,5.5,1.8,Iris-virginica 139 | 6.0,3.0,4.8,1.8,Iris-virginica 140 | 6.9,3.1,5.4,2.1,Iris-virginica 141 | 6.7,3.1,5.6,2.4,Iris-virginica 142 | 6.9,3.1,5.1,2.3,Iris-virginica 143 | 5.8,2.7,5.1,1.9,Iris-virginica 144 | 6.8,3.2,5.9,2.3,Iris-virginica 145 | 6.7,3.3,5.7,2.5,Iris-virginica 146 | 6.7,3.0,5.2,2.3,Iris-virginica 147 | 6.3,2.5,5.0,1.9,Iris-virginica 148 | 6.5,3.0,5.2,2.0,Iris-virginica 149 | 6.2,3.4,5.4,2.3,Iris-virginica 150 | 5.9,3.0,5.1,1.8,Iris-virginica 151 | -------------------------------------------------------------------------------- /examples/Worker-Pools.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Worker Pools" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "In this example we’ll look at how to implement a worker pool using goroutines and channels.\n", 15 | "\n", 16 | "Comments from [Go by Example](https://gobyexample.com)." 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": 1, 22 | "metadata": { 23 | "collapsed": true 24 | }, 25 | "outputs": [], 26 | "source": [ 27 | "import (\n", 28 | " \"fmt\"\n", 29 | " \"time\"\n", 30 | ")" 31 | ] 32 | }, 33 | { 34 | "cell_type": "markdown", 35 | "metadata": {}, 36 | "source": [ 37 | "## Worker Function" 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": {}, 43 | "source": [ 44 | "Here’s the worker, of which we’ll run several concurrent instances. These workers will receive work on the jobs channel and send the corresponding results on results. We’ll sleep a second per job to simulate an expensive task." 45 | ] 46 | }, 47 | { 48 | "cell_type": "code", 49 | "execution_count": 2, 50 | "metadata": { 51 | "collapsed": true 52 | }, 53 | "outputs": [], 54 | "source": [ 55 | "func worker(id int, jobs <-chan int, results chan<- int) {\n", 56 | " for j := range jobs {\n", 57 | " fmt.Println(\"worker\", id, \"processing job\", j)\n", 58 | " time.Sleep(time.Second)\n", 59 | " results <- j * 2\n", 60 | " }\n", 61 | "}" 62 | ] 63 | }, 64 | { 65 | "cell_type": "markdown", 66 | "metadata": {}, 67 | "source": [ 68 | "## Utilize Workers" 69 | ] 70 | }, 71 | { 72 | "cell_type": "markdown", 73 | "metadata": {}, 74 | "source": [ 75 | "In order to use our pool of workers we need to send them work and collect their results. We make 2 channels for this." 76 | ] 77 | }, 78 | { 79 | "cell_type": "code", 80 | "execution_count": 3, 81 | "metadata": { 82 | "collapsed": false 83 | }, 84 | "outputs": [ 85 | { 86 | "data": { 87 | "text/plain": [ 88 | "(\u001b[32mchan int\u001b[0m)(\u001b[34m\u001b[1m0xc42006f500\u001b[0m)\n" 89 | ] 90 | }, 91 | "execution_count": 3, 92 | "metadata": {}, 93 | "output_type": "execute_result" 94 | } 95 | ], 96 | "source": [ 97 | "jobs := make(chan int, 100)\n", 98 | "results := make(chan int, 100)" 99 | ] 100 | }, 101 | { 102 | "cell_type": "markdown", 103 | "metadata": {}, 104 | "source": [ 105 | "Next, start up 3 workers, initially blocked because there are no jobs yet:" 106 | ] 107 | }, 108 | { 109 | "cell_type": "code", 110 | "execution_count": 4, 111 | "metadata": { 112 | "collapsed": false 113 | }, 114 | "outputs": [], 115 | "source": [ 116 | "for w := 1; w <= 3; w++ {\n", 117 | " go worker(w, jobs, results)\n", 118 | "}" 119 | ] 120 | }, 121 | { 122 | "cell_type": "markdown", 123 | "metadata": {}, 124 | "source": [ 125 | "Send 9 jobs and then close that channel to indicate that’s all the work we have:" 126 | ] 127 | }, 128 | { 129 | "cell_type": "code", 130 | "execution_count": 5, 131 | "metadata": { 132 | "collapsed": true 133 | }, 134 | "outputs": [], 135 | "source": [ 136 | "for j := 1; j <= 9; j++ {\n", 137 | " jobs <- j\n", 138 | "}\n", 139 | "close(jobs)" 140 | ] 141 | }, 142 | { 143 | "cell_type": "markdown", 144 | "metadata": {}, 145 | "source": [ 146 | "## Collect Results" 147 | ] 148 | }, 149 | { 150 | "cell_type": "markdown", 151 | "metadata": {}, 152 | "source": [ 153 | "Finally we collect all the results of the work:" 154 | ] 155 | }, 156 | { 157 | "cell_type": "code", 158 | "execution_count": 6, 159 | "metadata": { 160 | "collapsed": false 161 | }, 162 | "outputs": [ 163 | { 164 | "data": { 165 | "text/plain": [ 166 | "worker 3 processing job 1\n", 167 | "worker 1 processing job 2\n", 168 | "worker 2 processing job 3\n", 169 | "worker 3 processing job 5\n", 170 | "worker 1 processing job 6\n", 171 | "worker 2 processing job 4\n", 172 | "worker 2 processing job 7\n", 173 | "worker 1 processing job 8\n", 174 | "worker 3 processing job 9\n" 175 | ] 176 | }, 177 | "execution_count": 6, 178 | "metadata": {}, 179 | "output_type": "execute_result" 180 | } 181 | ], 182 | "source": [ 183 | "for a := 1; a <= 9; a++ {\n", 184 | " <-results\n", 185 | "}" 186 | ] 187 | }, 188 | { 189 | "cell_type": "markdown", 190 | "metadata": {}, 191 | "source": [ 192 | "Our running program shows the 9 jobs being executed by various workers. The program only takes about 3 seconds despite doing about 9 seconds of total work because there are 3 workers operating concurrently." 193 | ] 194 | } 195 | ], 196 | "metadata": { 197 | "kernelspec": { 198 | "display_name": "Golang", 199 | "language": "go", 200 | "name": "gophernotes" 201 | }, 202 | "language_info": { 203 | "name": "go" 204 | } 205 | }, 206 | "nbformat": 4, 207 | "nbformat_minor": 0 208 | } 209 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/imports/fastwalk.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // A faster implementation of filepath.Walk. 6 | // 7 | // filepath.Walk's design necessarily calls os.Lstat on each file, 8 | // even if the caller needs less info. And goimports only need to know 9 | // the type of each file. The kernel interface provides the type in 10 | // the Readdir call but the standard library ignored it. 11 | // fastwalk_unix.go contains a fork of the syscall routines. 12 | // 13 | // See golang.org/issue/16399 14 | 15 | package imports 16 | 17 | import ( 18 | "errors" 19 | "os" 20 | "path/filepath" 21 | "runtime" 22 | ) 23 | 24 | // traverseLink is a sentinel error for fastWalk, similar to filepath.SkipDir. 25 | var traverseLink = errors.New("traverse symlink, assuming target is a directory") 26 | 27 | // fastWalk walks the file tree rooted at root, calling walkFn for 28 | // each file or directory in the tree, including root. 29 | // 30 | // If fastWalk returns filepath.SkipDir, the directory is skipped. 31 | // 32 | // Unlike filepath.Walk: 33 | // * file stat calls must be done by the user. 34 | // The only provided metadata is the file type, which does not include 35 | // any permission bits. 36 | // * multiple goroutines stat the filesystem concurrently. The provided 37 | // walkFn must be safe for concurrent use. 38 | // * fastWalk can follow symlinks if walkFn returns the traverseLink 39 | // sentinel error. It is the walkFn's responsibility to prevent 40 | // fastWalk from going into symlink cycles. 41 | func fastWalk(root string, walkFn func(path string, typ os.FileMode) error) error { 42 | // TODO(bradfitz): make numWorkers configurable? We used a 43 | // minimum of 4 to give the kernel more info about multiple 44 | // things we want, in hopes its I/O scheduling can take 45 | // advantage of that. Hopefully most are in cache. Maybe 4 is 46 | // even too low of a minimum. Profile more. 47 | numWorkers := 4 48 | if n := runtime.NumCPU(); n > numWorkers { 49 | numWorkers = n 50 | } 51 | w := &walker{ 52 | fn: walkFn, 53 | enqueuec: make(chan walkItem, numWorkers), // buffered for performance 54 | workc: make(chan walkItem, numWorkers), // buffered for performance 55 | donec: make(chan struct{}), 56 | 57 | // buffered for correctness & not leaking goroutines: 58 | resc: make(chan error, numWorkers), 59 | } 60 | defer close(w.donec) 61 | // TODO(bradfitz): start the workers as needed? maybe not worth it. 62 | for i := 0; i < numWorkers; i++ { 63 | go w.doWork() 64 | } 65 | todo := []walkItem{{dir: root}} 66 | out := 0 67 | for { 68 | workc := w.workc 69 | var workItem walkItem 70 | if len(todo) == 0 { 71 | workc = nil 72 | } else { 73 | workItem = todo[len(todo)-1] 74 | } 75 | select { 76 | case workc <- workItem: 77 | todo = todo[:len(todo)-1] 78 | out++ 79 | case it := <-w.enqueuec: 80 | todo = append(todo, it) 81 | case err := <-w.resc: 82 | out-- 83 | if err != nil { 84 | return err 85 | } 86 | if out == 0 && len(todo) == 0 { 87 | // It's safe to quit here, as long as the buffered 88 | // enqueue channel isn't also readable, which might 89 | // happen if the worker sends both another unit of 90 | // work and its result before the other select was 91 | // scheduled and both w.resc and w.enqueuec were 92 | // readable. 93 | select { 94 | case it := <-w.enqueuec: 95 | todo = append(todo, it) 96 | default: 97 | return nil 98 | } 99 | } 100 | } 101 | } 102 | } 103 | 104 | // doWork reads directories as instructed (via workc) and runs the 105 | // user's callback function. 106 | func (w *walker) doWork() { 107 | for { 108 | select { 109 | case <-w.donec: 110 | return 111 | case it := <-w.workc: 112 | w.resc <- w.walk(it.dir, !it.callbackDone) 113 | } 114 | } 115 | } 116 | 117 | type walker struct { 118 | fn func(path string, typ os.FileMode) error 119 | 120 | donec chan struct{} // closed on fastWalk's return 121 | workc chan walkItem // to workers 122 | enqueuec chan walkItem // from workers 123 | resc chan error // from workers 124 | } 125 | 126 | type walkItem struct { 127 | dir string 128 | callbackDone bool // callback already called; don't do it again 129 | } 130 | 131 | func (w *walker) enqueue(it walkItem) { 132 | select { 133 | case w.enqueuec <- it: 134 | case <-w.donec: 135 | } 136 | } 137 | 138 | func (w *walker) onDirEnt(dirName, baseName string, typ os.FileMode) error { 139 | joined := dirName + string(os.PathSeparator) + baseName 140 | if typ == os.ModeDir { 141 | w.enqueue(walkItem{dir: joined}) 142 | return nil 143 | } 144 | 145 | err := w.fn(joined, typ) 146 | if typ == os.ModeSymlink { 147 | if err == traverseLink { 148 | // Set callbackDone so we don't call it twice for both the 149 | // symlink-as-symlink and the symlink-as-directory later: 150 | w.enqueue(walkItem{dir: joined, callbackDone: true}) 151 | return nil 152 | } 153 | if err == filepath.SkipDir { 154 | // Permit SkipDir on symlinks too. 155 | return nil 156 | } 157 | } 158 | return err 159 | } 160 | func (w *walker) walk(root string, runUserCallback bool) error { 161 | if runUserCallback { 162 | err := w.fn(root, os.ModeDir) 163 | if err == filepath.SkipDir { 164 | return nil 165 | } 166 | if err != nil { 167 | return err 168 | } 169 | } 170 | 171 | return readDir(root, w.onDirEnt) 172 | } 173 | -------------------------------------------------------------------------------- /vendor/github.com/alecthomas/gozmq/.godocdown.md: -------------------------------------------------------------------------------- 1 | # Go (golang) Bindings for 0mq (zmq, zeromq) 2 | 3 | [![Build Status](https://travis-ci.org/alecthomas/gozmq.png)](https://travis-ci.org/alecthomas/gozmq) 4 | 5 | This package implements [Go](http://golang.org) (golang) bindings for 6 | the [0mq](http://zeromq.org) C API. 7 | 8 | It is licensed under the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0). 9 | 10 | GoZMQ [does not](#zero-copy) support zero-copy. 11 | 12 | A full list of examples is included in the [zguide](https://github.com/imatix/zguide/tree/master/examples/Go). 13 | 14 | Note that this is *not* the same as [this 15 | implementation](http://github.com/boggle/gozero) or [this 16 | implementation](http://code.google.com/p/gozmq/). 17 | 18 | ## Upgrading 19 | 20 | GoZMQ has made some public changes that will break old code. Fortunately, we've also written a tool based on `go fix` that will upgrade your code for you! Here's how to run it over your source (after making a backup of course): 21 | 22 | go get github.com/alecthomas/gozmq/gozmqfix 23 | cd $YOUR_SOURCE_DIR 24 | gozmqfix . 25 | 26 | ## Installing 27 | 28 | GoZMQ currently supports ZMQ 2.1.x, 2.2.x and *basic* support for 3.x. Following are instructions on how to compile against these versions. 29 | 30 | Install gozmq with: 31 | 32 | go get github.com/alecthomas/gozmq 33 | 34 | This implementation works currently against:: ZeroMQ 2.2.x 35 | 36 | ### ZeroMQ 2.1.x 37 | 38 | If you're using ZeroMQ 2.1.x, install with: 39 | 40 | go get -tags zmq_2_1 github.com/alecthomas/gozmq 41 | 42 | ### ZeroMQ 3.x 43 | 44 | There is *basic* support for ZeroMQ 3.x. Install with: 45 | 46 | go get -tags zmq_3_x github.com/alecthomas/gozmq 47 | 48 | ### Troubleshooting 49 | 50 | #### Go can't find ZMQ 51 | 52 | If the go tool can't find zmq and you know it is installed, you may need to override the C compiler/linker flags. 53 | 54 | eg. If you installed zmq into `/opt/zmq` you might try: 55 | 56 | CGO_CFLAGS=-I/opt/zmq/include CGO_LDFLAGS=-L/opt/zmq/lib \ 57 | go get github.com/alecthomas/gozmq 58 | 59 | #### Mismatch in version of ZMQ 60 | 61 | If you get errors like this with 'go get' or 'go build': 62 | 63 | 1: error: 'ZMQ_FOO' undeclared (first use in this function) 64 | 65 | There are two possibilities: 66 | 67 | 1. Your version of zmq is *very* old. In this case you will need to download and build zmq yourself. 68 | 2. You are building gozmq against the wrong version of zmq. See the [installation](#installation) instructions for details on how to target the correct version. 69 | 70 | ## Differences from the C API 71 | 72 | The API implemented by this package does not attempt to expose 73 | `zmq_msg_t` at all. Instead, `Recv()` and `Send()` both operate on byte 74 | slices, allocating and freeing the memory automatically. Currently this 75 | requires copying to/from C malloced memory, but a future implementation 76 | may be able to avoid this to a certain extent. 77 | 78 | All major features are supported: contexts, sockets, devices, and polls. 79 | 80 | ## Example 81 | 82 | Here are direct translations of some of the examples from [this blog 83 | post](http://nichol.as/zeromq-an-introduction). 84 | 85 | A simple echo server: 86 | 87 | ```go 88 | package main 89 | 90 | import zmq "github.com/alecthomas/gozmq" 91 | 92 | func main() { 93 | context, _ := zmq.NewContext() 94 | socket, _ := context.NewSocket(zmq.REP) 95 | socket.Bind("tcp://127.0.0.1:5000") 96 | socket.Bind("tcp://127.0.0.1:6000") 97 | 98 | for { 99 | msg, _ := socket.Recv(0) 100 | println("Got", string(msg)) 101 | socket.Send(msg, 0) 102 | } 103 | } 104 | ``` 105 | 106 | A simple client for the above server: 107 | 108 | ```go 109 | package main 110 | 111 | import "fmt" 112 | import zmq "github.com/alecthomas/gozmq" 113 | 114 | func main() { 115 | context, _ := zmq.NewContext() 116 | socket, _ := context.NewSocket(zmq.REQ) 117 | socket.Connect("tcp://127.0.0.1:5000") 118 | socket.Connect("tcp://127.0.0.1:6000") 119 | 120 | for i := 0; i < 10; i++ { 121 | msg := fmt.Sprintf("msg %d", i) 122 | socket.Send([]byte(msg), 0) 123 | println("Sending", msg) 124 | socket.Recv(0) 125 | } 126 | } 127 | ``` 128 | 129 | ## Caveats 130 | 131 | ### Zero-copy 132 | 133 | GoZMQ does not support zero-copy. 134 | 135 | GoZMQ does not attempt to expose `zmq_msg_t` at all. Instead, `Recv()` and `Send()` 136 | both operate on byte slices, allocating and freeing the memory automatically. 137 | Currently this requires copying to/from C malloced memory, but a future 138 | implementation may be able to avoid this to a certain extent. 139 | 140 | 141 | ### Memory management 142 | 143 | It's not entirely clear from the 0mq documentation how memory for 144 | `zmq_msg_t` and packet data is managed once 0mq takes ownership. After 145 | digging into the source a little, this package operates under the 146 | following (educated) assumptions: 147 | 148 | - References to `zmq_msg_t` structures are not held by the C API 149 | beyond the duration of any function call. 150 | - Packet data is reference counted internally by the C API. The count 151 | is incremented when a packet is queued for delivery to a destination 152 | (the inference being that for delivery to N destinations, the 153 | reference count will be incremented N times) and decremented once 154 | the packet has either been delivered or errored. 155 | 156 | {{ .EmitUsage }} 157 | 158 | *(generated from .[godocdown](https://github.com/robertkrimen/godocdown).md with `godocdown github.com/alecthomas/gozmq > README.md`)* 159 | -------------------------------------------------------------------------------- /vendor/github.com/nu7hatch/gouuid/uuid.go: -------------------------------------------------------------------------------- 1 | // This package provides immutable UUID structs and the functions 2 | // NewV3, NewV4, NewV5 and Parse() for generating versions 3, 4 3 | // and 5 UUIDs as specified in RFC 4122. 4 | // 5 | // Copyright (C) 2011 by Krzysztof Kowalik 6 | package uuid 7 | 8 | import ( 9 | "crypto/md5" 10 | "crypto/rand" 11 | "crypto/sha1" 12 | "encoding/hex" 13 | "errors" 14 | "fmt" 15 | "hash" 16 | "regexp" 17 | ) 18 | 19 | // The UUID reserved variants. 20 | const ( 21 | ReservedNCS byte = 0x80 22 | ReservedRFC4122 byte = 0x40 23 | ReservedMicrosoft byte = 0x20 24 | ReservedFuture byte = 0x00 25 | ) 26 | 27 | // The following standard UUIDs are for use with NewV3() or NewV5(). 28 | var ( 29 | NamespaceDNS, _ = ParseHex("6ba7b810-9dad-11d1-80b4-00c04fd430c8") 30 | NamespaceURL, _ = ParseHex("6ba7b811-9dad-11d1-80b4-00c04fd430c8") 31 | NamespaceOID, _ = ParseHex("6ba7b812-9dad-11d1-80b4-00c04fd430c8") 32 | NamespaceX500, _ = ParseHex("6ba7b814-9dad-11d1-80b4-00c04fd430c8") 33 | ) 34 | 35 | // Pattern used to parse hex string representation of the UUID. 36 | // FIXME: do something to consider both brackets at one time, 37 | // current one allows to parse string with only one opening 38 | // or closing bracket. 39 | const hexPattern = "^(urn\\:uuid\\:)?\\{?([a-z0-9]{8})-([a-z0-9]{4})-" + 40 | "([1-5][a-z0-9]{3})-([a-z0-9]{4})-([a-z0-9]{12})\\}?$" 41 | 42 | var re = regexp.MustCompile(hexPattern) 43 | 44 | // A UUID representation compliant with specification in 45 | // RFC 4122 document. 46 | type UUID [16]byte 47 | 48 | // ParseHex creates a UUID object from given hex string 49 | // representation. Function accepts UUID string in following 50 | // formats: 51 | // 52 | // uuid.ParseHex("6ba7b814-9dad-11d1-80b4-00c04fd430c8") 53 | // uuid.ParseHex("{6ba7b814-9dad-11d1-80b4-00c04fd430c8}") 54 | // uuid.ParseHex("urn:uuid:6ba7b814-9dad-11d1-80b4-00c04fd430c8") 55 | // 56 | func ParseHex(s string) (u *UUID, err error) { 57 | md := re.FindStringSubmatch(s) 58 | if md == nil { 59 | err = errors.New("Invalid UUID string") 60 | return 61 | } 62 | hash := md[2] + md[3] + md[4] + md[5] + md[6] 63 | b, err := hex.DecodeString(hash) 64 | if err != nil { 65 | return 66 | } 67 | u = new(UUID) 68 | copy(u[:], b) 69 | return 70 | } 71 | 72 | // Parse creates a UUID object from given bytes slice. 73 | func Parse(b []byte) (u *UUID, err error) { 74 | if len(b) != 16 { 75 | err = errors.New("Given slice is not valid UUID sequence") 76 | return 77 | } 78 | u = new(UUID) 79 | copy(u[:], b) 80 | return 81 | } 82 | 83 | // Generate a UUID based on the MD5 hash of a namespace identifier 84 | // and a name. 85 | func NewV3(ns *UUID, name []byte) (u *UUID, err error) { 86 | if ns == nil { 87 | err = errors.New("Invalid namespace UUID") 88 | return 89 | } 90 | u = new(UUID) 91 | // Set all bits to MD5 hash generated from namespace and name. 92 | u.setBytesFromHash(md5.New(), ns[:], name) 93 | u.setVariant(ReservedRFC4122) 94 | u.setVersion(3) 95 | return 96 | } 97 | 98 | // Generate a random UUID. 99 | func NewV4() (u *UUID, err error) { 100 | u = new(UUID) 101 | // Set all bits to randomly (or pseudo-randomly) chosen values. 102 | _, err = rand.Read(u[:]) 103 | if err != nil { 104 | return 105 | } 106 | u.setVariant(ReservedRFC4122) 107 | u.setVersion(4) 108 | return 109 | } 110 | 111 | // Generate a UUID based on the SHA-1 hash of a namespace identifier 112 | // and a name. 113 | func NewV5(ns *UUID, name []byte) (u *UUID, err error) { 114 | u = new(UUID) 115 | // Set all bits to truncated SHA1 hash generated from namespace 116 | // and name. 117 | u.setBytesFromHash(sha1.New(), ns[:], name) 118 | u.setVariant(ReservedRFC4122) 119 | u.setVersion(5) 120 | return 121 | } 122 | 123 | // Generate a MD5 hash of a namespace and a name, and copy it to the 124 | // UUID slice. 125 | func (u *UUID) setBytesFromHash(hash hash.Hash, ns, name []byte) { 126 | hash.Write(ns[:]) 127 | hash.Write(name) 128 | copy(u[:], hash.Sum([]byte{})[:16]) 129 | } 130 | 131 | // Set the two most significant bits (bits 6 and 7) of the 132 | // clock_seq_hi_and_reserved to zero and one, respectively. 133 | func (u *UUID) setVariant(v byte) { 134 | switch v { 135 | case ReservedNCS: 136 | u[8] = (u[8] | ReservedNCS) & 0xBF 137 | case ReservedRFC4122: 138 | u[8] = (u[8] | ReservedRFC4122) & 0x7F 139 | case ReservedMicrosoft: 140 | u[8] = (u[8] | ReservedMicrosoft) & 0x3F 141 | } 142 | } 143 | 144 | // Variant returns the UUID Variant, which determines the internal 145 | // layout of the UUID. This will be one of the constants: RESERVED_NCS, 146 | // RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE. 147 | func (u *UUID) Variant() byte { 148 | if u[8]&ReservedNCS == ReservedNCS { 149 | return ReservedNCS 150 | } else if u[8]&ReservedRFC4122 == ReservedRFC4122 { 151 | return ReservedRFC4122 152 | } else if u[8]&ReservedMicrosoft == ReservedMicrosoft { 153 | return ReservedMicrosoft 154 | } 155 | return ReservedFuture 156 | } 157 | 158 | // Set the four most significant bits (bits 12 through 15) of the 159 | // time_hi_and_version field to the 4-bit version number. 160 | func (u *UUID) setVersion(v byte) { 161 | u[6] = (u[6] & 0xF) | (v << 4) 162 | } 163 | 164 | // Version returns a version number of the algorithm used to 165 | // generate the UUID sequence. 166 | func (u *UUID) Version() uint { 167 | return uint(u[6] >> 4) 168 | } 169 | 170 | // Returns unparsed version of the generated UUID sequence. 171 | func (u *UUID) String() string { 172 | return fmt.Sprintf("%x-%x-%x-%x-%x", u[0:4], u[4:6], u[6:8], u[8:10], u[10:]) 173 | } 174 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/imports/sortimports.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Hacked up copy of go/ast/import.go 6 | 7 | package imports 8 | 9 | import ( 10 | "go/ast" 11 | "go/token" 12 | "sort" 13 | "strconv" 14 | ) 15 | 16 | // sortImports sorts runs of consecutive import lines in import blocks in f. 17 | // It also removes duplicate imports when it is possible to do so without data loss. 18 | func sortImports(fset *token.FileSet, f *ast.File) { 19 | for i, d := range f.Decls { 20 | d, ok := d.(*ast.GenDecl) 21 | if !ok || d.Tok != token.IMPORT { 22 | // Not an import declaration, so we're done. 23 | // Imports are always first. 24 | break 25 | } 26 | 27 | if len(d.Specs) == 0 { 28 | // Empty import block, remove it. 29 | f.Decls = append(f.Decls[:i], f.Decls[i+1:]...) 30 | } 31 | 32 | if !d.Lparen.IsValid() { 33 | // Not a block: sorted by default. 34 | continue 35 | } 36 | 37 | // Identify and sort runs of specs on successive lines. 38 | i := 0 39 | specs := d.Specs[:0] 40 | for j, s := range d.Specs { 41 | if j > i && fset.Position(s.Pos()).Line > 1+fset.Position(d.Specs[j-1].End()).Line { 42 | // j begins a new run. End this one. 43 | specs = append(specs, sortSpecs(fset, f, d.Specs[i:j])...) 44 | i = j 45 | } 46 | } 47 | specs = append(specs, sortSpecs(fset, f, d.Specs[i:])...) 48 | d.Specs = specs 49 | 50 | // Deduping can leave a blank line before the rparen; clean that up. 51 | if len(d.Specs) > 0 { 52 | lastSpec := d.Specs[len(d.Specs)-1] 53 | lastLine := fset.Position(lastSpec.Pos()).Line 54 | if rParenLine := fset.Position(d.Rparen).Line; rParenLine > lastLine+1 { 55 | fset.File(d.Rparen).MergeLine(rParenLine - 1) 56 | } 57 | } 58 | } 59 | } 60 | 61 | func importPath(s ast.Spec) string { 62 | t, err := strconv.Unquote(s.(*ast.ImportSpec).Path.Value) 63 | if err == nil { 64 | return t 65 | } 66 | return "" 67 | } 68 | 69 | func importName(s ast.Spec) string { 70 | n := s.(*ast.ImportSpec).Name 71 | if n == nil { 72 | return "" 73 | } 74 | return n.Name 75 | } 76 | 77 | func importComment(s ast.Spec) string { 78 | c := s.(*ast.ImportSpec).Comment 79 | if c == nil { 80 | return "" 81 | } 82 | return c.Text() 83 | } 84 | 85 | // collapse indicates whether prev may be removed, leaving only next. 86 | func collapse(prev, next ast.Spec) bool { 87 | if importPath(next) != importPath(prev) || importName(next) != importName(prev) { 88 | return false 89 | } 90 | return prev.(*ast.ImportSpec).Comment == nil 91 | } 92 | 93 | type posSpan struct { 94 | Start token.Pos 95 | End token.Pos 96 | } 97 | 98 | func sortSpecs(fset *token.FileSet, f *ast.File, specs []ast.Spec) []ast.Spec { 99 | // Can't short-circuit here even if specs are already sorted, 100 | // since they might yet need deduplication. 101 | // A lone import, however, may be safely ignored. 102 | if len(specs) <= 1 { 103 | return specs 104 | } 105 | 106 | // Record positions for specs. 107 | pos := make([]posSpan, len(specs)) 108 | for i, s := range specs { 109 | pos[i] = posSpan{s.Pos(), s.End()} 110 | } 111 | 112 | // Identify comments in this range. 113 | // Any comment from pos[0].Start to the final line counts. 114 | lastLine := fset.Position(pos[len(pos)-1].End).Line 115 | cstart := len(f.Comments) 116 | cend := len(f.Comments) 117 | for i, g := range f.Comments { 118 | if g.Pos() < pos[0].Start { 119 | continue 120 | } 121 | if i < cstart { 122 | cstart = i 123 | } 124 | if fset.Position(g.End()).Line > lastLine { 125 | cend = i 126 | break 127 | } 128 | } 129 | comments := f.Comments[cstart:cend] 130 | 131 | // Assign each comment to the import spec preceding it. 132 | importComment := map[*ast.ImportSpec][]*ast.CommentGroup{} 133 | specIndex := 0 134 | for _, g := range comments { 135 | for specIndex+1 < len(specs) && pos[specIndex+1].Start <= g.Pos() { 136 | specIndex++ 137 | } 138 | s := specs[specIndex].(*ast.ImportSpec) 139 | importComment[s] = append(importComment[s], g) 140 | } 141 | 142 | // Sort the import specs by import path. 143 | // Remove duplicates, when possible without data loss. 144 | // Reassign the import paths to have the same position sequence. 145 | // Reassign each comment to abut the end of its spec. 146 | // Sort the comments by new position. 147 | sort.Sort(byImportSpec(specs)) 148 | 149 | // Dedup. Thanks to our sorting, we can just consider 150 | // adjacent pairs of imports. 151 | deduped := specs[:0] 152 | for i, s := range specs { 153 | if i == len(specs)-1 || !collapse(s, specs[i+1]) { 154 | deduped = append(deduped, s) 155 | } else { 156 | p := s.Pos() 157 | fset.File(p).MergeLine(fset.Position(p).Line) 158 | } 159 | } 160 | specs = deduped 161 | 162 | // Fix up comment positions 163 | for i, s := range specs { 164 | s := s.(*ast.ImportSpec) 165 | if s.Name != nil { 166 | s.Name.NamePos = pos[i].Start 167 | } 168 | s.Path.ValuePos = pos[i].Start 169 | s.EndPos = pos[i].End 170 | for _, g := range importComment[s] { 171 | for _, c := range g.List { 172 | c.Slash = pos[i].End 173 | } 174 | } 175 | } 176 | 177 | sort.Sort(byCommentPos(comments)) 178 | 179 | return specs 180 | } 181 | 182 | type byImportSpec []ast.Spec // slice of *ast.ImportSpec 183 | 184 | func (x byImportSpec) Len() int { return len(x) } 185 | func (x byImportSpec) Swap(i, j int) { x[i], x[j] = x[j], x[i] } 186 | func (x byImportSpec) Less(i, j int) bool { 187 | ipath := importPath(x[i]) 188 | jpath := importPath(x[j]) 189 | 190 | igroup := importGroup(ipath) 191 | jgroup := importGroup(jpath) 192 | if igroup != jgroup { 193 | return igroup < jgroup 194 | } 195 | 196 | if ipath != jpath { 197 | return ipath < jpath 198 | } 199 | iname := importName(x[i]) 200 | jname := importName(x[j]) 201 | 202 | if iname != jname { 203 | return iname < jname 204 | } 205 | return importComment(x[i]) < importComment(x[j]) 206 | } 207 | 208 | type byCommentPos []*ast.CommentGroup 209 | 210 | func (x byCommentPos) Len() int { return len(x) } 211 | func (x byCommentPos) Swap(i, j int) { x[i], x[j] = x[j], x[i] } 212 | func (x byCommentPos) Less(i, j int) bool { return x[i].Pos() < x[j].Pos() } 213 | -------------------------------------------------------------------------------- /vendor/github.com/davecgh/go-spew/spew/bypass.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Dave Collins 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | // NOTE: Due to the following build constraints, this file will only be compiled 16 | // when the code is not running on Google App Engine and "-tags disableunsafe" 17 | // is not added to the go build command line. 18 | // +build !appengine,!disableunsafe 19 | 20 | package spew 21 | 22 | import ( 23 | "reflect" 24 | "unsafe" 25 | ) 26 | 27 | const ( 28 | // UnsafeDisabled is a build-time constant which specifies whether or 29 | // not access to the unsafe package is available. 30 | UnsafeDisabled = false 31 | 32 | // ptrSize is the size of a pointer on the current arch. 33 | ptrSize = unsafe.Sizeof((*byte)(nil)) 34 | ) 35 | 36 | var ( 37 | // offsetPtr, offsetScalar, and offsetFlag are the offsets for the 38 | // internal reflect.Value fields. These values are valid before golang 39 | // commit ecccf07e7f9d which changed the format. The are also valid 40 | // after commit 82f48826c6c7 which changed the format again to mirror 41 | // the original format. Code in the init function updates these offsets 42 | // as necessary. 43 | offsetPtr = uintptr(ptrSize) 44 | offsetScalar = uintptr(0) 45 | offsetFlag = uintptr(ptrSize * 2) 46 | 47 | // flagKindWidth and flagKindShift indicate various bits that the 48 | // reflect package uses internally to track kind information. 49 | // 50 | // flagRO indicates whether or not the value field of a reflect.Value is 51 | // read-only. 52 | // 53 | // flagIndir indicates whether the value field of a reflect.Value is 54 | // the actual data or a pointer to the data. 55 | // 56 | // These values are valid before golang commit 90a7c3c86944 which 57 | // changed their positions. Code in the init function updates these 58 | // flags as necessary. 59 | flagKindWidth = uintptr(5) 60 | flagKindShift = uintptr(flagKindWidth - 1) 61 | flagRO = uintptr(1 << 0) 62 | flagIndir = uintptr(1 << 1) 63 | ) 64 | 65 | func init() { 66 | // Older versions of reflect.Value stored small integers directly in the 67 | // ptr field (which is named val in the older versions). Versions 68 | // between commits ecccf07e7f9d and 82f48826c6c7 added a new field named 69 | // scalar for this purpose which unfortunately came before the flag 70 | // field, so the offset of the flag field is different for those 71 | // versions. 72 | // 73 | // This code constructs a new reflect.Value from a known small integer 74 | // and checks if the size of the reflect.Value struct indicates it has 75 | // the scalar field. When it does, the offsets are updated accordingly. 76 | vv := reflect.ValueOf(0xf00) 77 | if unsafe.Sizeof(vv) == (ptrSize * 4) { 78 | offsetScalar = ptrSize * 2 79 | offsetFlag = ptrSize * 3 80 | } 81 | 82 | // Commit 90a7c3c86944 changed the flag positions such that the low 83 | // order bits are the kind. This code extracts the kind from the flags 84 | // field and ensures it's the correct type. When it's not, the flag 85 | // order has been changed to the newer format, so the flags are updated 86 | // accordingly. 87 | upf := unsafe.Pointer(uintptr(unsafe.Pointer(&vv)) + offsetFlag) 88 | upfv := *(*uintptr)(upf) 89 | flagKindMask := uintptr((1<>flagKindShift != uintptr(reflect.Int) { 91 | flagKindShift = 0 92 | flagRO = 1 << 5 93 | flagIndir = 1 << 6 94 | 95 | // Commit adf9b30e5594 modified the flags to separate the 96 | // flagRO flag into two bits which specifies whether or not the 97 | // field is embedded. This causes flagIndir to move over a bit 98 | // and means that flagRO is the combination of either of the 99 | // original flagRO bit and the new bit. 100 | // 101 | // This code detects the change by extracting what used to be 102 | // the indirect bit to ensure it's set. When it's not, the flag 103 | // order has been changed to the newer format, so the flags are 104 | // updated accordingly. 105 | if upfv&flagIndir == 0 { 106 | flagRO = 3 << 5 107 | flagIndir = 1 << 7 108 | } 109 | } 110 | } 111 | 112 | // unsafeReflectValue converts the passed reflect.Value into a one that bypasses 113 | // the typical safety restrictions preventing access to unaddressable and 114 | // unexported data. It works by digging the raw pointer to the underlying 115 | // value out of the protected value and generating a new unprotected (unsafe) 116 | // reflect.Value to it. 117 | // 118 | // This allows us to check for implementations of the Stringer and error 119 | // interfaces to be used for pretty printing ordinarily unaddressable and 120 | // inaccessible values such as unexported struct fields. 121 | func unsafeReflectValue(v reflect.Value) (rv reflect.Value) { 122 | indirects := 1 123 | vt := v.Type() 124 | upv := unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetPtr) 125 | rvf := *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetFlag)) 126 | if rvf&flagIndir != 0 { 127 | vt = reflect.PtrTo(v.Type()) 128 | indirects++ 129 | } else if offsetScalar != 0 { 130 | // The value is in the scalar field when it's not one of the 131 | // reference types. 132 | switch vt.Kind() { 133 | case reflect.Uintptr: 134 | case reflect.Chan: 135 | case reflect.Func: 136 | case reflect.Map: 137 | case reflect.Ptr: 138 | case reflect.UnsafePointer: 139 | default: 140 | upv = unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + 141 | offsetScalar) 142 | } 143 | } 144 | 145 | pv := reflect.NewAt(vt, upv) 146 | rv = pv 147 | for i := 0; i < indirects; i++ { 148 | rv = rv.Elem() 149 | } 150 | return rv 151 | } 152 | -------------------------------------------------------------------------------- /vendor/github.com/davecgh/go-spew/spew/spew.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Dave Collins 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | package spew 18 | 19 | import ( 20 | "fmt" 21 | "io" 22 | ) 23 | 24 | // Errorf is a wrapper for fmt.Errorf that treats each argument as if it were 25 | // passed with a default Formatter interface returned by NewFormatter. It 26 | // returns the formatted string as a value that satisfies error. See 27 | // NewFormatter for formatting details. 28 | // 29 | // This function is shorthand for the following syntax: 30 | // 31 | // fmt.Errorf(format, spew.NewFormatter(a), spew.NewFormatter(b)) 32 | func Errorf(format string, a ...interface{}) (err error) { 33 | return fmt.Errorf(format, convertArgs(a)...) 34 | } 35 | 36 | // Fprint is a wrapper for fmt.Fprint that treats each argument as if it were 37 | // passed with a default Formatter interface returned by NewFormatter. It 38 | // returns the number of bytes written and any write error encountered. See 39 | // NewFormatter for formatting details. 40 | // 41 | // This function is shorthand for the following syntax: 42 | // 43 | // fmt.Fprint(w, spew.NewFormatter(a), spew.NewFormatter(b)) 44 | func Fprint(w io.Writer, a ...interface{}) (n int, err error) { 45 | return fmt.Fprint(w, convertArgs(a)...) 46 | } 47 | 48 | // Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were 49 | // passed with a default Formatter interface returned by NewFormatter. It 50 | // returns the number of bytes written and any write error encountered. See 51 | // NewFormatter for formatting details. 52 | // 53 | // This function is shorthand for the following syntax: 54 | // 55 | // fmt.Fprintf(w, format, spew.NewFormatter(a), spew.NewFormatter(b)) 56 | func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { 57 | return fmt.Fprintf(w, format, convertArgs(a)...) 58 | } 59 | 60 | // Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it 61 | // passed with a default Formatter interface returned by NewFormatter. See 62 | // NewFormatter for formatting details. 63 | // 64 | // This function is shorthand for the following syntax: 65 | // 66 | // fmt.Fprintln(w, spew.NewFormatter(a), spew.NewFormatter(b)) 67 | func Fprintln(w io.Writer, a ...interface{}) (n int, err error) { 68 | return fmt.Fprintln(w, convertArgs(a)...) 69 | } 70 | 71 | // Print is a wrapper for fmt.Print that treats each argument as if it were 72 | // passed with a default Formatter interface returned by NewFormatter. It 73 | // returns the number of bytes written and any write error encountered. See 74 | // NewFormatter for formatting details. 75 | // 76 | // This function is shorthand for the following syntax: 77 | // 78 | // fmt.Print(spew.NewFormatter(a), spew.NewFormatter(b)) 79 | func Print(a ...interface{}) (n int, err error) { 80 | return fmt.Print(convertArgs(a)...) 81 | } 82 | 83 | // Printf is a wrapper for fmt.Printf that treats each argument as if it were 84 | // passed with a default Formatter interface returned by NewFormatter. It 85 | // returns the number of bytes written and any write error encountered. See 86 | // NewFormatter for formatting details. 87 | // 88 | // This function is shorthand for the following syntax: 89 | // 90 | // fmt.Printf(format, spew.NewFormatter(a), spew.NewFormatter(b)) 91 | func Printf(format string, a ...interface{}) (n int, err error) { 92 | return fmt.Printf(format, convertArgs(a)...) 93 | } 94 | 95 | // Println is a wrapper for fmt.Println that treats each argument as if it were 96 | // passed with a default Formatter interface returned by NewFormatter. It 97 | // returns the number of bytes written and any write error encountered. See 98 | // NewFormatter for formatting details. 99 | // 100 | // This function is shorthand for the following syntax: 101 | // 102 | // fmt.Println(spew.NewFormatter(a), spew.NewFormatter(b)) 103 | func Println(a ...interface{}) (n int, err error) { 104 | return fmt.Println(convertArgs(a)...) 105 | } 106 | 107 | // Sprint is a wrapper for fmt.Sprint that treats each argument as if it were 108 | // passed with a default Formatter interface returned by NewFormatter. It 109 | // returns the resulting string. See NewFormatter for formatting details. 110 | // 111 | // This function is shorthand for the following syntax: 112 | // 113 | // fmt.Sprint(spew.NewFormatter(a), spew.NewFormatter(b)) 114 | func Sprint(a ...interface{}) string { 115 | return fmt.Sprint(convertArgs(a)...) 116 | } 117 | 118 | // Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were 119 | // passed with a default Formatter interface returned by NewFormatter. It 120 | // returns the resulting string. See NewFormatter for formatting details. 121 | // 122 | // This function is shorthand for the following syntax: 123 | // 124 | // fmt.Sprintf(format, spew.NewFormatter(a), spew.NewFormatter(b)) 125 | func Sprintf(format string, a ...interface{}) string { 126 | return fmt.Sprintf(format, convertArgs(a)...) 127 | } 128 | 129 | // Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it 130 | // were passed with a default Formatter interface returned by NewFormatter. It 131 | // returns the resulting string. See NewFormatter for formatting details. 132 | // 133 | // This function is shorthand for the following syntax: 134 | // 135 | // fmt.Sprintln(spew.NewFormatter(a), spew.NewFormatter(b)) 136 | func Sprintln(a ...interface{}) string { 137 | return fmt.Sprintln(convertArgs(a)...) 138 | } 139 | 140 | // convertArgs accepts a slice of arguments and returns a slice of the same 141 | // length with each argument converted to a default spew Formatter interface. 142 | func convertArgs(args []interface{}) (formatters []interface{}) { 143 | formatters = make([]interface{}, len(args)) 144 | for index, arg := range args { 145 | formatters[index] = NewFormatter(arg) 146 | } 147 | return formatters 148 | } 149 | -------------------------------------------------------------------------------- /internal/repl/quickfix.go: -------------------------------------------------------------------------------- 1 | package replpkg 2 | 3 | import ( 4 | "strings" 5 | 6 | "go/ast" 7 | "go/types" 8 | 9 | "golang.org/x/tools/go/ast/astutil" 10 | 11 | "github.com/motemen/go-quickfix" 12 | ) 13 | 14 | // doQuickFix tries to fix the source AST so that it compiles well. 15 | func (s *Session) doQuickFix() error { 16 | const maxAttempts = 10 17 | 18 | s.reset() 19 | 20 | quickFixAttempt: 21 | for i := 0; i < maxAttempts; i++ { 22 | s.TypeInfo = types.Info{ 23 | Types: make(map[ast.Expr]types.TypeAndValue), 24 | } 25 | 26 | files := s.ExtraFiles 27 | files = append(files, s.File) 28 | 29 | config := quickfix.Config{ 30 | Fset: s.Fset, 31 | Files: files, 32 | TypeInfo: &s.TypeInfo, 33 | } 34 | _, err := config.QuickFixOnce() 35 | if err == nil { 36 | break 37 | } 38 | 39 | debugf("quickFix :: err = %#v", err) 40 | 41 | errList, ok := err.(quickfix.ErrorList) 42 | if !ok { 43 | continue 44 | } 45 | 46 | // (try to) fix gore-specific remaining errors 47 | for _, err := range errList { 48 | err, ok := err.(types.Error) 49 | if !ok { 50 | continue 51 | } 52 | 53 | // "... used as value": 54 | // 55 | // convert 56 | // __gore_pp(funcWithSideEffectReturningNoValue()) 57 | // to 58 | // funcWithSideEffectReturningNoValue() 59 | if strings.HasSuffix(err.Msg, " used as value") { 60 | nodepath, _ := astutil.PathEnclosingInterval(s.File, err.Pos, err.Pos) 61 | 62 | for _, node := range nodepath { 63 | stmt, ok := node.(ast.Stmt) 64 | if !ok { 65 | continue 66 | } 67 | 68 | for i := range s.mainBody.List { 69 | if s.mainBody.List[i] != stmt { 70 | continue 71 | } 72 | 73 | exprs := printedExprs(stmt) 74 | 75 | stmts := s.mainBody.List[0:i] 76 | for _, expr := range exprs { 77 | stmts = append(stmts, &ast.ExprStmt{X: expr}) 78 | } 79 | 80 | s.mainBody.List = append(stmts, s.mainBody.List[i+1:]...) 81 | continue quickFixAttempt 82 | } 83 | } 84 | } 85 | } 86 | 87 | debugf("quickFix :: give up: %#v", err) 88 | } 89 | 90 | return nil 91 | } 92 | 93 | func (s *Session) clearQuickFix() { 94 | 95 | // make all import specs explicit (i.e. no "_"). 96 | for _, imp := range s.File.Imports { 97 | imp.Name = nil 98 | } 99 | 100 | for i := 0; i < len(s.mainBody.List); { 101 | stmt := s.mainBody.List[i] 102 | 103 | // remove "_ = x" stmt 104 | if assign, ok := stmt.(*ast.AssignStmt); ok && len(assign.Lhs) == 1 { 105 | if isNamedIdent(assign.Lhs[0], "_") { 106 | s.mainBody.List = append(s.mainBody.List[0:i], s.mainBody.List[i+1:]...) 107 | continue 108 | } 109 | } 110 | 111 | // remove expressions just for printing out 112 | // i.e. what causes "evaluated but not used." 113 | if exprs := printedExprs(stmt); exprs != nil { 114 | allPure := true 115 | for _, expr := range exprs { 116 | if !s.isPureExpr(expr) { 117 | allPure = false 118 | break 119 | } 120 | } 121 | 122 | if allPure { 123 | s.mainBody.List = append(s.mainBody.List[0:i], s.mainBody.List[i+1:]...) 124 | continue 125 | } 126 | 127 | // strip (possibly impure) printing expression to expression 128 | var trailing []ast.Stmt 129 | s.mainBody.List, trailing = s.mainBody.List[0:i], s.mainBody.List[i+1:] 130 | for _, expr := range exprs { 131 | if !isNamedIdent(expr, "_") { 132 | s.mainBody.List = append(s.mainBody.List, &ast.ExprStmt{X: expr}) 133 | } 134 | } 135 | 136 | s.mainBody.List = append(s.mainBody.List, trailing...) 137 | continue 138 | } 139 | 140 | i++ 141 | } 142 | 143 | debugf("clearQuickFix :: %s", showNode(s.Fset, s.mainBody)) 144 | } 145 | 146 | // printedExprs returns arguments of statement stmt of form "p(x...)" 147 | func printedExprs(stmt ast.Stmt) []ast.Expr { 148 | st, ok := stmt.(*ast.ExprStmt) 149 | if !ok { 150 | return nil 151 | } 152 | 153 | // first check whether the expr is p(_) form 154 | call, ok := st.X.(*ast.CallExpr) 155 | if !ok { 156 | return nil 157 | } 158 | 159 | if !isNamedIdent(call.Fun, printerName) { 160 | return nil 161 | } 162 | 163 | return call.Args 164 | } 165 | 166 | var pureBuiltinFuncNames = map[string]bool{ 167 | "append": true, 168 | "cap": true, 169 | "complex": true, 170 | "imag": true, 171 | "len": true, 172 | "make": true, 173 | "new": true, 174 | "real": true, 175 | } 176 | 177 | var pureNotBuiltinFuncNames = map[string]bool{ 178 | "Println": true, 179 | "Printf": true, 180 | } 181 | 182 | // isPureExpr checks if an expression expr is "pure", which means 183 | // removing this expression will no affect the entire program. 184 | // - identifiers ("x") 185 | // - types 186 | // - selectors ("x.y") 187 | // - slices ("a[n:m]") 188 | // - literals ("1") 189 | // - type conversion ("int(1)") 190 | // - type assertion ("x.(int)") 191 | // - call of some built-in functions as listed in pureBuiltinFuncNames 192 | func (s *Session) isPureExpr(expr ast.Expr) bool { 193 | if expr == nil { 194 | return true 195 | } 196 | 197 | switch expr := expr.(type) { 198 | case *ast.Ident: 199 | return true 200 | case *ast.BasicLit: 201 | return true 202 | case *ast.BinaryExpr: 203 | return s.isPureExpr(expr.X) && s.isPureExpr(expr.Y) 204 | case *ast.CallExpr: 205 | tv := s.TypeInfo.Types[expr.Fun] 206 | 207 | //for _, arg := range expr.Args { 208 | // if s.isPureExpr(arg) == false { 209 | // return false 210 | // } 211 | //} 212 | 213 | if tv.IsType() { 214 | return true 215 | } 216 | 217 | if tv.IsBuiltin() { 218 | if ident, ok := expr.Fun.(*ast.Ident); ok { 219 | if pureBuiltinFuncNames[ident.Name] { 220 | return true 221 | } 222 | } 223 | } 224 | 225 | if !tv.IsBuiltin() { 226 | if selectorExpr, ok := expr.Fun.(*ast.SelectorExpr); ok { 227 | if pureNotBuiltinFuncNames[selectorExpr.Sel.Name] { 228 | return true 229 | } 230 | } 231 | } 232 | 233 | return false 234 | case *ast.CompositeLit: 235 | return true 236 | case *ast.FuncLit: 237 | return true 238 | case *ast.IndexExpr: 239 | return s.isPureExpr(expr.X) && s.isPureExpr(expr.Index) 240 | case *ast.SelectorExpr: 241 | return s.isPureExpr(expr.X) 242 | case *ast.SliceExpr: 243 | return s.isPureExpr(expr.Low) && s.isPureExpr(expr.High) && s.isPureExpr(expr.Max) 244 | case *ast.StarExpr: 245 | return s.isPureExpr(expr.X) 246 | case *ast.TypeAssertExpr: 247 | return true 248 | case *ast.UnaryExpr: 249 | return s.isPureExpr(expr.X) 250 | case *ast.ParenExpr: 251 | return s.isPureExpr(expr.X) 252 | 253 | case *ast.InterfaceType: 254 | return true 255 | case *ast.ArrayType: 256 | return true 257 | case *ast.ChanType: 258 | return true 259 | case *ast.KeyValueExpr: 260 | return true 261 | case *ast.MapType: 262 | return true 263 | case *ast.StructType: 264 | return true 265 | case *ast.FuncType: 266 | return true 267 | 268 | case *ast.Ellipsis: 269 | return true 270 | 271 | case *ast.BadExpr: 272 | return false 273 | } 274 | 275 | return false 276 | } 277 | -------------------------------------------------------------------------------- /gophernotes.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io" 7 | "io/ioutil" 8 | "log" 9 | "os" 10 | 11 | zmq "github.com/alecthomas/gozmq" 12 | "github.com/pkg/errors" 13 | ) 14 | 15 | var logger *log.Logger 16 | 17 | // ConnectionInfo stores the contents of the kernel connection file created by Jupyter. 18 | type ConnectionInfo struct { 19 | SignatureScheme string `json:"signature_scheme"` 20 | Transport string `json:"transport"` 21 | StdinPort int `json:"stdin_port"` 22 | ControlPort int `json:"control_port"` 23 | IOPubPort int `json:"iopub_port"` 24 | HBPort int `json:"hb_port"` 25 | ShellPort int `json:"shell_port"` 26 | Key string `json:"key"` 27 | IP string `json:"ip"` 28 | } 29 | 30 | // SocketGroup holds the sockets needed to communicate with the kernel, and 31 | // the key for message signing. 32 | type SocketGroup struct { 33 | ShellSocket *zmq.Socket 34 | ControlSocket *zmq.Socket 35 | StdinSocket *zmq.Socket 36 | IOPubSocket *zmq.Socket 37 | Key []byte 38 | } 39 | 40 | // PrepareSockets sets up the ZMQ sockets through which the kernel will communicate. 41 | func PrepareSockets(connInfo ConnectionInfo) (SocketGroup, error) { 42 | 43 | // Initialize the Socket Group. 44 | context, sg, err := createSockets() 45 | if err != nil { 46 | return sg, errors.Wrap(err, "Could not initialize context and Socket Group") 47 | } 48 | 49 | // Bind the sockets. 50 | address := fmt.Sprintf("%v://%v:%%v", connInfo.Transport, connInfo.IP) 51 | sg.ShellSocket.Bind(fmt.Sprintf(address, connInfo.ShellPort)) 52 | sg.ControlSocket.Bind(fmt.Sprintf(address, connInfo.ControlPort)) 53 | sg.StdinSocket.Bind(fmt.Sprintf(address, connInfo.StdinPort)) 54 | sg.IOPubSocket.Bind(fmt.Sprintf(address, connInfo.IOPubPort)) 55 | 56 | // Message signing key 57 | sg.Key = []byte(connInfo.Key) 58 | 59 | // Start the heartbeat device 60 | HBSocket, err := context.NewSocket(zmq.REP) 61 | if err != nil { 62 | return sg, errors.Wrap(err, "Could not get the Heartbeat device socket") 63 | } 64 | HBSocket.Bind(fmt.Sprintf(address, connInfo.HBPort)) 65 | go zmq.Device(zmq.FORWARDER, HBSocket, HBSocket) 66 | 67 | return sg, nil 68 | } 69 | 70 | // createSockets initializes the sockets for the socket group based on values from zmq. 71 | func createSockets() (*zmq.Context, SocketGroup, error) { 72 | 73 | context, err := zmq.NewContext() 74 | if err != nil { 75 | return context, SocketGroup{}, errors.Wrap(err, "Could not create zmq Context") 76 | } 77 | 78 | var sg SocketGroup 79 | sg.ShellSocket, err = context.NewSocket(zmq.ROUTER) 80 | if err != nil { 81 | return context, sg, errors.Wrap(err, "Could not get Shell Socket") 82 | } 83 | 84 | sg.ControlSocket, err = context.NewSocket(zmq.ROUTER) 85 | if err != nil { 86 | return context, sg, errors.Wrap(err, "Could not get Control Socket") 87 | } 88 | 89 | sg.StdinSocket, err = context.NewSocket(zmq.ROUTER) 90 | if err != nil { 91 | return context, sg, errors.Wrap(err, "Could not get Stdin Socket") 92 | } 93 | 94 | sg.IOPubSocket, err = context.NewSocket(zmq.PUB) 95 | if err != nil { 96 | return context, sg, errors.Wrap(err, "Could not get IOPub Socket") 97 | } 98 | 99 | return context, sg, nil 100 | } 101 | 102 | // HandleShellMsg responds to a message on the shell ROUTER socket. 103 | func HandleShellMsg(receipt MsgReceipt) { 104 | switch receipt.Msg.Header.MsgType { 105 | case "kernel_info_request": 106 | SendKernelInfo(receipt) 107 | case "execute_request": 108 | HandleExecuteRequest(receipt) 109 | case "shutdown_request": 110 | HandleShutdownRequest(receipt) 111 | default: 112 | logger.Println("Unhandled shell message:", receipt.Msg.Header.MsgType) 113 | } 114 | } 115 | 116 | // KernelInfo holds information about the igo kernel, for kernel_info_reply messages. 117 | type KernelInfo struct { 118 | ProtocolVersion []int `json:"protocol_version"` 119 | Language string `json:"language"` 120 | } 121 | 122 | // KernelStatus holds a kernel state, for status broadcast messages. 123 | type KernelStatus struct { 124 | ExecutionState string `json:"execution_state"` 125 | } 126 | 127 | // SendKernelInfo sends a kernel_info_reply message. 128 | func SendKernelInfo(receipt MsgReceipt) { 129 | reply := NewMsg("kernel_info_reply", receipt.Msg) 130 | reply.Content = KernelInfo{[]int{4, 0}, "go"} 131 | receipt.SendResponse(receipt.Sockets.ShellSocket, reply) 132 | } 133 | 134 | // ShutdownReply encodes a boolean indication of stutdown/restart 135 | type ShutdownReply struct { 136 | Restart bool `json:"restart"` 137 | } 138 | 139 | // HandleShutdownRequest sends a "shutdown" message 140 | func HandleShutdownRequest(receipt MsgReceipt) { 141 | reply := NewMsg("shutdown_reply", receipt.Msg) 142 | content := receipt.Msg.Content.(map[string]interface{}) 143 | restart := content["restart"].(bool) 144 | reply.Content = ShutdownReply{restart} 145 | receipt.SendResponse(receipt.Sockets.ShellSocket, reply) 146 | logger.Println("Shutting down in response to shutdown_request") 147 | os.Exit(0) 148 | } 149 | 150 | // RunKernel is the main entry point to start the kernel. 151 | func RunKernel(connectionFile string, logwriter io.Writer) { 152 | 153 | logger = log.New(logwriter, "gophernotes ", log.LstdFlags) 154 | 155 | // Set up the "Session" with the replpkg. 156 | SetupExecutionEnvironment() 157 | 158 | var connInfo ConnectionInfo 159 | bs, err := ioutil.ReadFile(connectionFile) 160 | if err != nil { 161 | log.Fatalln(err) 162 | } 163 | if err = json.Unmarshal(bs, &connInfo); err != nil { 164 | log.Fatalln(err) 165 | } 166 | logger.Printf("%+v\n", connInfo) 167 | 168 | // Set up the ZMQ sockets through which the kernel will communicate. 169 | sockets, err := PrepareSockets(connInfo) 170 | if err != nil { 171 | log.Fatalln(err) 172 | } 173 | 174 | pi := zmq.PollItems{ 175 | zmq.PollItem{Socket: sockets.ShellSocket, Events: zmq.POLLIN}, 176 | zmq.PollItem{Socket: sockets.StdinSocket, Events: zmq.POLLIN}, 177 | zmq.PollItem{Socket: sockets.ControlSocket, Events: zmq.POLLIN}, 178 | } 179 | 180 | // Start a message receiving loop. 181 | var msgparts [][]byte 182 | for { 183 | if _, err = zmq.Poll(pi, -1); err != nil { 184 | log.Fatalln(err) 185 | } 186 | switch { 187 | case pi[0].REvents&zmq.POLLIN != 0: // shell socket 188 | msgparts, _ = pi[0].Socket.RecvMultipart(0) 189 | msg, ids, err := WireMsgToComposedMsg(msgparts, sockets.Key) 190 | if err != nil { 191 | log.Println(err) 192 | return 193 | } 194 | HandleShellMsg(MsgReceipt{msg, ids, sockets}) 195 | case pi[1].REvents&zmq.POLLIN != 0: // stdin socket - not implemented. 196 | pi[1].Socket.RecvMultipart(0) 197 | case pi[2].REvents&zmq.POLLIN != 0: // control socket - treat like shell socket. 198 | msgparts, err = pi[2].Socket.RecvMultipart(0) 199 | if err != nil { 200 | log.Println(err) 201 | return 202 | } 203 | msg, ids, err := WireMsgToComposedMsg(msgparts, sockets.Key) 204 | if err != nil { 205 | log.Println(err) 206 | return 207 | } 208 | HandleShellMsg(MsgReceipt{msg, ids, sockets}) 209 | } 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /vendor/github.com/alecthomas/gozmq/zmq_3_x.go: -------------------------------------------------------------------------------- 1 | // +build zmq_3_x zmq_4_x 2 | 3 | /* 4 | Copyright 2010-2012 Alec Thomas 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | package gozmq 20 | 21 | /* 22 | #cgo !windows pkg-config: libzmq 23 | #include 24 | #include 25 | #include 26 | */ 27 | import "C" 28 | import ( 29 | "errors" 30 | "unsafe" 31 | ) 32 | 33 | const ( 34 | RCVMORE = IntSocketOption(C.ZMQ_RCVMORE) 35 | SNDHWM = IntSocketOption(C.ZMQ_SNDHWM) 36 | RCVHWM = IntSocketOption(C.ZMQ_RCVHWM) 37 | 38 | // TODO Not documented in the man page... 39 | //LAST_ENDPOINT = UInt64SocketOption(C.ZMQ_LAST_ENDPOINT) 40 | DELAY_ATTACH_ON_CONNECT = IntSocketOption(C.ZMQ_DELAY_ATTACH_ON_CONNECT) 41 | FAIL_UNROUTABLE = BoolSocketOption(C.ZMQ_FAIL_UNROUTABLE) 42 | IPV4ONLY = IntSocketOption(C.ZMQ_IPV4ONLY) 43 | MAXMSGSIZE = Int64SocketOption(C.ZMQ_MAXMSGSIZE) 44 | ROUTER_MANDATORY = IntSocketOption(C.ZMQ_ROUTER_MANDATORY) 45 | TCP_KEEPALIVE = IntSocketOption(C.ZMQ_TCP_KEEPALIVE) 46 | TCP_KEEPALIVE_CNT = IntSocketOption(C.ZMQ_TCP_KEEPALIVE_CNT) 47 | TCP_KEEPALIVE_IDLE = IntSocketOption(C.ZMQ_TCP_KEEPALIVE_IDLE) 48 | TCP_KEEPALIVE_INTVL = IntSocketOption(C.ZMQ_TCP_KEEPALIVE_INTVL) 49 | TCP_ACCEPT_FILTER = StringSocketOption(C.ZMQ_TCP_ACCEPT_FILTER) 50 | XPUB_VERBOSE = IntSocketOption(C.ZMQ_XPUB_VERBOSE) 51 | 52 | // Message options 53 | MORE = MessageOption(C.ZMQ_MORE) 54 | 55 | // Send/recv options 56 | DONTWAIT = SendRecvOption(C.ZMQ_DONTWAIT) 57 | 58 | // Deprecated aliases 59 | NOBLOCK = DONTWAIT 60 | ) 61 | 62 | // Socket transport events 63 | type Event int 64 | 65 | const ( 66 | EVENT_CONNECTED = Event(C.ZMQ_EVENT_CONNECTED) 67 | EVENT_CONNECT_DELAYED = Event(C.ZMQ_EVENT_CONNECT_DELAYED) 68 | EVENT_CONNECT_RETRIED = Event(C.ZMQ_EVENT_CONNECT_RETRIED) 69 | 70 | EVENT_LISTENING = Event(C.ZMQ_EVENT_LISTENING) 71 | EVENT_BIND_FAILED = Event(C.ZMQ_EVENT_BIND_FAILED) 72 | 73 | EVENT_ACCEPTED = Event(C.ZMQ_EVENT_ACCEPTED) 74 | EVENT_ACCEPT_FAILED = Event(C.ZMQ_EVENT_ACCEPT_FAILED) 75 | 76 | EVENT_CLOSED = Event(C.ZMQ_EVENT_CLOSED) 77 | EVENT_CLOSE_FAILED = Event(C.ZMQ_EVENT_CLOSE_FAILED) 78 | EVENT_DISCONNECTED = Event(C.ZMQ_EVENT_DISCONNECTED) 79 | 80 | EVENT_ALL = EVENT_CONNECTED | EVENT_CONNECT_DELAYED | 81 | EVENT_CONNECT_RETRIED | EVENT_LISTENING | EVENT_BIND_FAILED | 82 | EVENT_ACCEPTED | EVENT_ACCEPT_FAILED | EVENT_CLOSED | 83 | EVENT_CLOSE_FAILED | EVENT_DISCONNECTED 84 | ) 85 | 86 | // Get a context option. 87 | // int zmq_ctx_get (void *c, int); 88 | func (c *Context) get(option C.int) (int, error) { 89 | if c.init(); c.err != nil { 90 | return -1, c.err 91 | } 92 | var value C.int 93 | var err error 94 | if value, err = C.zmq_ctx_get(c.c, option); err != nil { 95 | return -1, casterr(err) 96 | } 97 | return int(value), nil 98 | } 99 | 100 | // Set a context option. 101 | // int zmq_ctx_set (void *c, int, int); 102 | func (c *Context) set(option C.int, value int) error { 103 | if c.init(); c.err != nil { 104 | return c.err 105 | } 106 | if rc, err := C.zmq_ctx_set(c.c, option, C.int(value)); rc == -1 { 107 | return casterr(err) 108 | } 109 | return nil 110 | } 111 | 112 | func (c *Context) IOThreads() (int, error) { 113 | return c.get(C.ZMQ_IO_THREADS) 114 | } 115 | 116 | func (c *Context) MaxSockets() (int, error) { 117 | return c.get(C.ZMQ_MAX_SOCKETS) 118 | } 119 | 120 | func (c *Context) SetIOThreads(value int) error { 121 | return c.set(C.ZMQ_IO_THREADS, value) 122 | } 123 | 124 | func (c *Context) SetMaxSockets(value int) error { 125 | return c.set(C.ZMQ_MAX_SOCKETS, value) 126 | } 127 | 128 | func (s *Socket) SetHWM(value int) error { 129 | snd := s.SetSndHWM(value) 130 | rcv := s.SetRcvHWM(value) 131 | if snd != nil { 132 | return snd 133 | } 134 | return rcv 135 | } 136 | 137 | func (s *Socket) SetTCPAcceptFilterNil() error { 138 | return s.SetSockOptStringNil(TCP_ACCEPT_FILTER) 139 | } 140 | 141 | // Disconnect the socket from the address. 142 | // int zmq_disconnect (void *s, const char *addr); 143 | func (s *Socket) Disconnect(address string) error { 144 | if s.c == nil { 145 | return ENOTSOCK 146 | } 147 | a := C.CString(address) 148 | defer C.free(unsafe.Pointer(a)) 149 | if rc, err := C.zmq_disconnect(s.s, a); rc != 0 { 150 | return casterr(err) 151 | } 152 | return nil 153 | } 154 | 155 | // Send a message to the socket. 156 | // int zmq_send (void *s, zmq_msg_t *msg, int flags); 157 | func (s *Socket) Send(data []byte, flags SendRecvOption) error { 158 | var m C.zmq_msg_t 159 | // Copy data array into C-allocated buffer. 160 | size := C.size_t(len(data)) 161 | 162 | if rc, err := C.zmq_msg_init_size(&m, size); rc != 0 { 163 | return casterr(err) 164 | } 165 | 166 | if size > 0 { 167 | // FIXME Ideally this wouldn't require a copy. 168 | C.memcpy(C.zmq_msg_data(&m), unsafe.Pointer(&data[0]), size) // XXX I hope this works...(seems to) 169 | } 170 | 171 | if rc, err := C.zmq_sendmsg(s.s, &m, C.int(flags)); rc == -1 { 172 | // zmq_send did not take ownership, free message 173 | C.zmq_msg_close(&m) 174 | return casterr(err) 175 | } 176 | return nil 177 | } 178 | 179 | // Receive a message from the socket. 180 | // int zmq_recv (void *s, zmq_msg_t *msg, int flags); 181 | func (s *Socket) Recv(flags SendRecvOption) (data []byte, err error) { 182 | // Allocate and initialise a new zmq_msg_t 183 | var m C.zmq_msg_t 184 | var rc C.int 185 | if rc, err = C.zmq_msg_init(&m); rc != 0 { 186 | err = casterr(err) 187 | return 188 | } 189 | defer C.zmq_msg_close(&m) 190 | // Receive into message 191 | if rc, err = C.zmq_recvmsg(s.s, &m, C.int(flags)); rc == -1 { 192 | err = casterr(err) 193 | return 194 | } 195 | err = nil 196 | // Copy message data into a byte array 197 | // FIXME Ideally this wouldn't require a copy. 198 | size := C.zmq_msg_size(&m) 199 | if size > 0 { 200 | data = C.GoBytes(C.zmq_msg_data(&m), C.int(size)) 201 | } else { 202 | data = nil 203 | } 204 | return 205 | } 206 | 207 | // Register a monitoring callback endpoint. 208 | // int zmq_socket_monitor (void *s, const char *addr, int events); 209 | func (s *Socket) Monitor(address string, events Event) error { 210 | a := C.CString(address) 211 | defer C.free(unsafe.Pointer(a)) 212 | 213 | rc, err := C.zmq_socket_monitor(s.apiSocket(), a, C.int(events)) 214 | if rc == -1 { 215 | return casterr(err) 216 | } 217 | return nil 218 | } 219 | 220 | // Portability helper 221 | func (s *Socket) getRcvmore() (more bool, err error) { 222 | value, err := s.GetSockOptInt(RCVMORE) 223 | more = value != 0 224 | return 225 | } 226 | 227 | // run a zmq_proxy with in, out and capture sockets 228 | func Proxy(in, out, capture *Socket) error { 229 | var c unsafe.Pointer 230 | if capture != nil { 231 | c = capture.apiSocket() 232 | } 233 | if rc, err := C.zmq_proxy(in.apiSocket(), out.apiSocket(), c); rc != 0 { 234 | return casterr(err) 235 | } 236 | return errors.New("zmq_proxy() returned unexpectedly.") 237 | } 238 | -------------------------------------------------------------------------------- /examples/Pattern-Recognition.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Imports" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": 1, 13 | "metadata": { 14 | "collapsed": true 15 | }, 16 | "outputs": [], 17 | "source": [ 18 | "import (\n", 19 | " \"fmt\"\n", 20 | " \"github.com/sjwhitworth/golearn/base\"\n", 21 | " \"github.com/sjwhitworth/golearn/evaluation\"\n", 22 | " \"github.com/sjwhitworth/golearn/knn\"\n", 23 | ")" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "# Problem/Data Description" 31 | ] 32 | }, 33 | { 34 | "cell_type": "markdown", 35 | "metadata": {}, 36 | "source": [ 37 | "" 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": {}, 43 | "source": [ 44 | "Information about this dataset comes from [here](https://archive.ics.uci.edu/ml/datasets/Iris)" 45 | ] 46 | }, 47 | { 48 | "cell_type": "markdown", 49 | "metadata": {}, 50 | "source": [ 51 | "## Data Set Information:" 52 | ] 53 | }, 54 | { 55 | "cell_type": "markdown", 56 | "metadata": {}, 57 | "source": [ 58 | "This is perhaps the best known database to be found in the pattern recognition literature. Fisher's paper is a classic in the field and is referenced frequently to this day. (See Duda & Hart, for example.) The data set contains 3 classes of 50 instances each, where each class refers to a type of iris plant. One class is linearly separable from the other 2; the latter are NOT linearly separable from each other. \n", 59 | "\n", 60 | "Predicted attribute: class of iris plant. " 61 | ] 62 | }, 63 | { 64 | "cell_type": "markdown", 65 | "metadata": {}, 66 | "source": [ 67 | "## Attribute Information:" 68 | ] 69 | }, 70 | { 71 | "cell_type": "markdown", 72 | "metadata": {}, 73 | "source": [ 74 | "1. sepal length in cm \n", 75 | "2. sepal width in cm \n", 76 | "3. petal length in cm \n", 77 | "4. petal width in cm \n", 78 | "5. class: \n", 79 | "-- Iris Setosa \n", 80 | "-- Iris Versicolour \n", 81 | "-- Iris Virginica" 82 | ] 83 | }, 84 | { 85 | "cell_type": "markdown", 86 | "metadata": {}, 87 | "source": [ 88 | "# Building a Pattern Recognition Model" 89 | ] 90 | }, 91 | { 92 | "cell_type": "markdown", 93 | "metadata": {}, 94 | "source": [ 95 | "This example model comes from the [golearn](https://github.com/sjwhitworth/golearn) documentation." 96 | ] 97 | }, 98 | { 99 | "cell_type": "code", 100 | "execution_count": 2, 101 | "metadata": { 102 | "collapsed": false 103 | }, 104 | "outputs": [ 105 | { 106 | "data": { 107 | "text/plain": [ 108 | "Optimisations are switched off\n", 109 | "KNN: 1.14 % done\n", 110 | "KNN: 2.27 % done\n", 111 | "KNN: 3.41 % done\n", 112 | "KNN: 4.55 % done\n", 113 | "KNN: 5.68 % done\n", 114 | "KNN: 6.82 % done\n", 115 | "KNN: 7.95 % done\n", 116 | "KNN: 9.09 % done\n", 117 | "KNN: 10.23 % done\n", 118 | "KNN: 11.36 % done\n", 119 | "KNN: 12.50 % done\n", 120 | "KNN: 13.64 % done\n", 121 | "KNN: 14.77 % done\n", 122 | "KNN: 15.91 % done\n", 123 | "KNN: 17.05 % done\n", 124 | "KNN: 18.18 % done\n", 125 | "KNN: 19.32 % done\n", 126 | "KNN: 20.45 % done\n", 127 | "KNN: 21.59 % done\n", 128 | "KNN: 22.73 % done\n", 129 | "KNN: 23.86 % done\n", 130 | "KNN: 25.00 % done\n", 131 | "KNN: 26.14 % done\n", 132 | "KNN: 27.27 % done\n", 133 | "KNN: 28.41 % done\n", 134 | "KNN: 29.55 % done\n", 135 | "KNN: 30.68 % done\n", 136 | "KNN: 31.82 % done\n", 137 | "KNN: 32.95 % done\n", 138 | "KNN: 34.09 % done\n", 139 | "KNN: 35.23 % done\n", 140 | "KNN: 36.36 % done\n", 141 | "KNN: 37.50 % done\n", 142 | "KNN: 38.64 % done\n", 143 | "KNN: 39.77 % done\n", 144 | "KNN: 40.91 % done\n", 145 | "KNN: 42.05 % done\n", 146 | "KNN: 43.18 % done\n", 147 | "KNN: 44.32 % done\n", 148 | "KNN: 45.45 % done\n", 149 | "KNN: 46.59 % done\n", 150 | "KNN: 47.73 % done\n", 151 | "KNN: 48.86 % done\n", 152 | "KNN: 50.00 % done\n", 153 | "KNN: 51.14 % done\n", 154 | "KNN: 52.27 % done\n", 155 | "KNN: 53.41 % done\n", 156 | "KNN: 54.55 % done\n", 157 | "KNN: 55.68 % done\n", 158 | "KNN: 56.82 % done\n", 159 | "KNN: 57.95 % done\n", 160 | "KNN: 59.09 % done\n", 161 | "KNN: 60.23 % done\n", 162 | "KNN: 61.36 % done\n", 163 | "KNN: 62.50 % done\n", 164 | "KNN: 63.64 % done\n", 165 | "KNN: 64.77 % done\n", 166 | "KNN: 65.91 % done\n", 167 | "KNN: 67.05 % done\n", 168 | "KNN: 68.18 % done\n", 169 | "KNN: 69.32 % done\n", 170 | "KNN: 70.45 % done\n", 171 | "KNN: 71.59 % done\n", 172 | "KNN: 72.73 % done\n", 173 | "KNN: 73.86 % done\n", 174 | "KNN: 75.00 % done\n", 175 | "KNN: 76.14 % done\n", 176 | "KNN: 77.27 % done\n", 177 | "KNN: 78.41 % done\n", 178 | "KNN: 79.55 % done\n", 179 | "KNN: 80.68 % done\n", 180 | "KNN: 81.82 % done\n", 181 | "KNN: 82.95 % done\n", 182 | "KNN: 84.09 % done\n", 183 | "KNN: 85.23 % done\n", 184 | "KNN: 86.36 % done\n", 185 | "KNN: 87.50 % done\n", 186 | "KNN: 88.64 % done\n", 187 | "KNN: 89.77 % done\n", 188 | "KNN: 90.91 % done\n", 189 | "KNN: 92.05 % done\n", 190 | "KNN: 93.18 % done\n", 191 | "KNN: 94.32 % done\n", 192 | "KNN: 95.45 % done\n", 193 | "KNN: 96.59 % done\n", 194 | "KNN: 97.73 % done\n", 195 | "KNN: 98.86 % done\n", 196 | "Reference Class\tTrue Positives\tFalse Positives\tTrue Negatives\tPrecision\tRecall\tF1 Score\n", 197 | "---------------\t--------------\t---------------\t--------------\t---------\t------\t--------\n", 198 | "Iris-setosa\t30\t\t0\t\t58\t\t1.0000\t\t1.0000\t1.0000\n", 199 | "Iris-virginica\t28\t\t1\t\t58\t\t0.9655\t\t0.9655\t0.9655\n", 200 | "Iris-versicolor\t28\t\t1\t\t58\t\t0.9655\t\t0.9655\t0.9655\n", 201 | "Overall accuracy: 0.9773\n", 202 | "\n" 203 | ] 204 | }, 205 | "execution_count": 2, 206 | "metadata": {}, 207 | "output_type": "execute_result" 208 | } 209 | ], 210 | "source": [ 211 | "// Load in a dataset, with headers. Header attributes will be stored.\n", 212 | "// Think of instances as a Data Frame structure in R or Pandas.\n", 213 | "// You can also create instances from scratch.\n", 214 | "rawData, err := base.ParseCSVToInstances(\"iris.csv\", false)\n", 215 | "\n", 216 | "//Initialises a new KNN classifier\n", 217 | "cls := knn.NewKnnClassifier(\"euclidean\", 2)\n", 218 | "\n", 219 | "//Do a training-test split\n", 220 | "trainData, testData := base.InstancesTrainTestSplit(rawData, 0.50)\n", 221 | "cls.Fit(trainData)\n", 222 | "\n", 223 | "//Calculates the Euclidean distance and returns the most popular label\n", 224 | "predictions := cls.Predict(testData)\n", 225 | "\n", 226 | "// Calculate precision/recall metrics, and summarize results\n", 227 | "confusionMat, err := evaluation.GetConfusionMatrix(testData, predictions)\n", 228 | "fmt.Println(evaluation.GetSummary(confusionMat))" 229 | ] 230 | } 231 | ], 232 | "metadata": { 233 | "kernelspec": { 234 | "display_name": "Golang", 235 | "language": "go", 236 | "name": "gophernotes" 237 | }, 238 | "language_info": { 239 | "name": "go" 240 | } 241 | }, 242 | "nbformat": 4, 243 | "nbformat_minor": 0 244 | } 245 | -------------------------------------------------------------------------------- /examples/Feed-Forward-Recurrent-NN.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": { 7 | "collapsed": true 8 | }, 9 | "outputs": [], 10 | "source": [ 11 | "import (\n", 12 | " \"math/rand\"\n", 13 | " \"github.com/goml/gobrain\"\n", 14 | ")" 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "# Feed Forward vs. Recurrent Neural Networks" 22 | ] 23 | }, 24 | { 25 | "cell_type": "markdown", 26 | "metadata": {}, 27 | "source": [ 28 | "(comments from [wikipedia](https://en.wikipedia.org), examples from the [gobrain](https://github.com/goml/gobrain) documentation)" 29 | ] 30 | }, 31 | { 32 | "cell_type": "markdown", 33 | "metadata": {}, 34 | "source": [ 35 | "## Feed Forward Description:" 36 | ] 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "metadata": {}, 41 | "source": [ 42 | "" 43 | ] 44 | }, 45 | { 46 | "cell_type": "markdown", 47 | "metadata": {}, 48 | "source": [ 49 | "A feedforward neural network is an artificial neural network where connections between the units do not form a cycle. This is different from recurrent neural networks.\n", 50 | "\n", 51 | "The feedforward neural network was the first and simplest type of artificial neural network devised. In this network, the information moves in only one direction, forward, from the input nodes, through the hidden nodes (if any) and to the output nodes. There are no cycles or loops in the network." 52 | ] 53 | }, 54 | { 55 | "cell_type": "markdown", 56 | "metadata": {}, 57 | "source": [ 58 | "## [Gobrain](https://github.com/goml/gobrain) Example - Feed Forward Function" 59 | ] 60 | }, 61 | { 62 | "cell_type": "code", 63 | "execution_count": 2, 64 | "metadata": { 65 | "collapsed": true 66 | }, 67 | "outputs": [], 68 | "source": [ 69 | "// set the random seed to 0\n", 70 | "rand.Seed(0)" 71 | ] 72 | }, 73 | { 74 | "cell_type": "code", 75 | "execution_count": 3, 76 | "metadata": { 77 | "collapsed": false 78 | }, 79 | "outputs": [ 80 | { 81 | "data": { 82 | "text/plain": [ 83 | "&gobrain.\u001b[32mFeedForward\u001b[0m{\n", 84 | " \u001b[33mNInputs\u001b[0m: \u001b[34m\u001b[1m0\u001b[0m,\n", 85 | " \u001b[33mNHiddens\u001b[0m: \u001b[34m\u001b[1m0\u001b[0m,\n", 86 | " \u001b[33mNOutputs\u001b[0m: \u001b[34m\u001b[1m0\u001b[0m,\n", 87 | " \u001b[33mRegression\u001b[0m: \u001b[36m\u001b[1mfalse\u001b[0m,\n", 88 | " \u001b[33mInputActivations\u001b[0m: []\u001b[32mfloat64\u001b[0m{},\n", 89 | " \u001b[33mHiddenActivations\u001b[0m: []\u001b[32mfloat64\u001b[0m{},\n", 90 | " \u001b[33mOutputActivations\u001b[0m: []\u001b[32mfloat64\u001b[0m{},\n", 91 | " \u001b[33mContexts\u001b[0m: []\u001b[32m[]float64\u001b[0m{},\n", 92 | " \u001b[33mInputWeights\u001b[0m: []\u001b[32m[]float64\u001b[0m{},\n", 93 | " \u001b[33mOutputWeights\u001b[0m: []\u001b[32m[]float64\u001b[0m{},\n", 94 | " \u001b[33mInputChanges\u001b[0m: []\u001b[32m[]float64\u001b[0m{},\n", 95 | " \u001b[33mOutputChanges\u001b[0m: []\u001b[32m[]float64\u001b[0m{},\n", 96 | "}\n" 97 | ] 98 | }, 99 | "execution_count": 3, 100 | "metadata": {}, 101 | "output_type": "execute_result" 102 | } 103 | ], 104 | "source": [ 105 | "// create the XOR representation patter to train the network\n", 106 | "patterns := [][][]float64{\n", 107 | " {{0, 0}, {0}},\n", 108 | " {{0, 1}, {1}},\n", 109 | " {{1, 0}, {1}},\n", 110 | " {{1, 1}, {0}},\n", 111 | "}\n", 112 | "\n", 113 | "// instantiate the Feed Forward\n", 114 | "ff := &gobrain.FeedForward{}" 115 | ] 116 | }, 117 | { 118 | "cell_type": "code", 119 | "execution_count": 4, 120 | "metadata": { 121 | "collapsed": true 122 | }, 123 | "outputs": [], 124 | "source": [ 125 | "// initialize the Neural Network;\n", 126 | "// the networks structure will contain:\n", 127 | "// 2 inputs, 2 hidden nodes and 1 output.\n", 128 | "ff.Init(2, 2, 1)" 129 | ] 130 | }, 131 | { 132 | "cell_type": "code", 133 | "execution_count": 5, 134 | "metadata": { 135 | "collapsed": false 136 | }, 137 | "outputs": [ 138 | { 139 | "data": { 140 | "text/plain": [ 141 | "0 0.5524794213542835\n", 142 | "[0 0] -> [0.05750394570844524] : [0]\n", 143 | "[0 1] -> [0.9301006350712102] : [1]\n", 144 | "[1 0] -> [0.927809966227284] : [1]\n", 145 | "[1 1] -> [0.09740879532462095] : [0]\n" 146 | ] 147 | }, 148 | "execution_count": 5, 149 | "metadata": {}, 150 | "output_type": "execute_result" 151 | } 152 | ], 153 | "source": [ 154 | "// train the network using the XOR patterns\n", 155 | "// the training will run for 1000 epochs\n", 156 | "// the learning rate is set to 0.6 and the momentum factor to 0.4\n", 157 | "// use true in the last parameter to receive reports about the learning error\n", 158 | "ff.Train(patterns, 1000, 0.6, 0.4, true)\n", 159 | "ff.Test(patterns)" 160 | ] 161 | }, 162 | { 163 | "cell_type": "markdown", 164 | "metadata": {}, 165 | "source": [ 166 | "Where the first values are the inputs, the values after the arrow `->` are the output values from the network and the values after `:` are the expected outputs." 167 | ] 168 | }, 169 | { 170 | "cell_type": "markdown", 171 | "metadata": {}, 172 | "source": [ 173 | "## Recurrent Description:" 174 | ] 175 | }, 176 | { 177 | "cell_type": "markdown", 178 | "metadata": {}, 179 | "source": [ 180 | "" 181 | ] 182 | }, 183 | { 184 | "cell_type": "markdown", 185 | "metadata": {}, 186 | "source": [ 187 | "A recurrent neural network (RNN) is a class of artificial neural network where connections between units form a directed cycle. This creates an internal state of the network which allows it to exhibit dynamic temporal behavior. Unlike feedforward neural networks, RNNs can use their internal memory to process arbitrary sequences of inputs. This makes them applicable to tasks such as unsegmented connected handwriting recognition or speech recognition." 188 | ] 189 | }, 190 | { 191 | "cell_type": "markdown", 192 | "metadata": {}, 193 | "source": [ 194 | "## [Gobrain](https://github.com/goml/gobrain) - Recurrent Example" 195 | ] 196 | }, 197 | { 198 | "cell_type": "markdown", 199 | "metadata": {}, 200 | "source": [ 201 | "Gobrain implements Elman's Simple Recurrent Network. To take advantage of this, one can use the `SetContexts` function." 202 | ] 203 | }, 204 | { 205 | "cell_type": "code", 206 | "execution_count": 6, 207 | "metadata": { 208 | "collapsed": false 209 | }, 210 | "outputs": [ 211 | { 212 | "data": { 213 | "text/plain": [ 214 | "0 0.5524794213542835\n", 215 | "[0 0] -> [0.05750394570844524] : [0]\n", 216 | "[0 1] -> [0.9301006350712102] : [1]\n", 217 | "[1 0] -> [0.927809966227284] : [1]\n", 218 | "[1 1] -> [0.09740879532462095] : [0]\n" 219 | ] 220 | }, 221 | "execution_count": 6, 222 | "metadata": {}, 223 | "output_type": "execute_result" 224 | } 225 | ], 226 | "source": [ 227 | "ff.SetContexts(1, nil)" 228 | ] 229 | }, 230 | { 231 | "cell_type": "markdown", 232 | "metadata": {}, 233 | "source": [ 234 | "In the example above, a single context will be created initilized with 0.5. " 235 | ] 236 | } 237 | ], 238 | "metadata": { 239 | "kernelspec": { 240 | "display_name": "Golang", 241 | "language": "go", 242 | "name": "gophernotes" 243 | }, 244 | "language_info": { 245 | "name": "go" 246 | } 247 | }, 248 | "nbformat": 4, 249 | "nbformat_minor": 0 250 | } 251 | -------------------------------------------------------------------------------- /examples/Stateful-Goroutines.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Stateful Goroutines" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "To synchronize access to shared state across multiple goroutines, one option is to use the built-in synchronization features of goroutines and channels. This channel-based approach aligns with Go’s ideas of sharing memory by communicating and having each piece of data owned by exactly 1 goroutine.\n", 15 | "\n", 16 | "Comments from [Go by Example](https://gobyexample.com)." 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": 1, 22 | "metadata": { 23 | "collapsed": true 24 | }, 25 | "outputs": [], 26 | "source": [ 27 | "import (\n", 28 | " \"fmt\"\n", 29 | " \"math/rand\"\n", 30 | " \"sync/atomic\"\n", 31 | " \"time\"\n", 32 | ")" 33 | ] 34 | }, 35 | { 36 | "cell_type": "markdown", 37 | "metadata": {}, 38 | "source": [ 39 | "## `structs` to Encapsulate Requests" 40 | ] 41 | }, 42 | { 43 | "cell_type": "markdown", 44 | "metadata": {}, 45 | "source": [ 46 | "In this example our state will be owned by a single goroutine. This will guarantee that the data is never corrupted with concurrent access. In order to read or write that state, other goroutines will send messages to the owning goroutine and receive corresponding replies. These readOp and writeOp structs encapsulate those requests and a way for the owning goroutine to respond." 47 | ] 48 | }, 49 | { 50 | "cell_type": "code", 51 | "execution_count": 2, 52 | "metadata": { 53 | "collapsed": true 54 | }, 55 | "outputs": [], 56 | "source": [ 57 | "type readOp struct {\n", 58 | " key int\n", 59 | " resp chan int\n", 60 | "}" 61 | ] 62 | }, 63 | { 64 | "cell_type": "code", 65 | "execution_count": 3, 66 | "metadata": { 67 | "collapsed": true 68 | }, 69 | "outputs": [], 70 | "source": [ 71 | "type writeOp struct {\n", 72 | " key int\n", 73 | " val int\n", 74 | " resp chan bool\n", 75 | "}" 76 | ] 77 | }, 78 | { 79 | "cell_type": "markdown", 80 | "metadata": {}, 81 | "source": [ 82 | "## Definitions" 83 | ] 84 | }, 85 | { 86 | "cell_type": "markdown", 87 | "metadata": {}, 88 | "source": [ 89 | "Count how many operations we perform." 90 | ] 91 | }, 92 | { 93 | "cell_type": "code", 94 | "execution_count": 4, 95 | "metadata": { 96 | "collapsed": true 97 | }, 98 | "outputs": [], 99 | "source": [ 100 | "var ops int64 = 0" 101 | ] 102 | }, 103 | { 104 | "cell_type": "markdown", 105 | "metadata": {}, 106 | "source": [ 107 | "The reads and writes channels will be used by other goroutines to issue read and write requests, respectively." 108 | ] 109 | }, 110 | { 111 | "cell_type": "code", 112 | "execution_count": 5, 113 | "metadata": { 114 | "collapsed": false 115 | }, 116 | "outputs": [ 117 | { 118 | "data": { 119 | "text/plain": [ 120 | "(chan *main.\u001b[32mwriteOp\u001b[0m)(\u001b[34m\u001b[1m0xc420018120\u001b[0m)\n" 121 | ] 122 | }, 123 | "execution_count": 5, 124 | "metadata": {}, 125 | "output_type": "execute_result" 126 | } 127 | ], 128 | "source": [ 129 | "reads := make(chan *readOp)\n", 130 | "writes := make(chan *writeOp)" 131 | ] 132 | }, 133 | { 134 | "cell_type": "markdown", 135 | "metadata": {}, 136 | "source": [ 137 | "## Goroutines" 138 | ] 139 | }, 140 | { 141 | "cell_type": "markdown", 142 | "metadata": {}, 143 | "source": [ 144 | "Here is the goroutine that owns the state, which is a map as in the previous example but now private to the stateful goroutine. This goroutine repeatedly selects on the reads and writes channels, responding to requests as they arrive. A response is executed by first performing the requested operation and then sending a value on the response channel resp to indicate success (and the desired value in the case of reads)." 145 | ] 146 | }, 147 | { 148 | "cell_type": "code", 149 | "execution_count": 6, 150 | "metadata": { 151 | "collapsed": true 152 | }, 153 | "outputs": [], 154 | "source": [ 155 | "go func() {\n", 156 | " var state = make(map[int]int)\n", 157 | " for {\n", 158 | " select {\n", 159 | " case read := <-reads:\n", 160 | " read.resp <- state[read.key]\n", 161 | " case write := <-writes:\n", 162 | " state[write.key] = write.val\n", 163 | " write.resp <- true\n", 164 | " }\n", 165 | " }\n", 166 | "}()" 167 | ] 168 | }, 169 | { 170 | "cell_type": "markdown", 171 | "metadata": {}, 172 | "source": [ 173 | "This starts 100 goroutines to issue reads to the state-owning goroutine via the reads channel. Each read requires constructing a readOp, sending it over the reads channel, and the receiving the result over the provided resp channel." 174 | ] 175 | }, 176 | { 177 | "cell_type": "code", 178 | "execution_count": 7, 179 | "metadata": { 180 | "collapsed": true 181 | }, 182 | "outputs": [], 183 | "source": [ 184 | "for r := 0; r < 100; r++ {\n", 185 | " go func() {\n", 186 | " for {\n", 187 | " read := &readOp{\n", 188 | " key: rand.Intn(5),\n", 189 | " resp: make(chan int)}\n", 190 | " reads <- read\n", 191 | " <-read.resp\n", 192 | " atomic.AddInt64(&ops, 1)\n", 193 | " }\n", 194 | " }()\n", 195 | "}" 196 | ] 197 | }, 198 | { 199 | "cell_type": "markdown", 200 | "metadata": {}, 201 | "source": [ 202 | "We start 10 writes as well, using a similar approach." 203 | ] 204 | }, 205 | { 206 | "cell_type": "code", 207 | "execution_count": 8, 208 | "metadata": { 209 | "collapsed": true 210 | }, 211 | "outputs": [], 212 | "source": [ 213 | "for w := 0; w < 10; w++ {\n", 214 | " go func() {\n", 215 | " for {\n", 216 | " write := &writeOp{\n", 217 | " key: rand.Intn(5),\n", 218 | " val: rand.Intn(100),\n", 219 | " resp: make(chan bool)}\n", 220 | " writes <- write\n", 221 | " <-write.resp\n", 222 | " atomic.AddInt64(&ops, 1)\n", 223 | " }\n", 224 | " }()\n", 225 | "}\n", 226 | "// let the goroutines work for a second\n", 227 | "time.Sleep(time.Second)" 228 | ] 229 | }, 230 | { 231 | "cell_type": "markdown", 232 | "metadata": {}, 233 | "source": [ 234 | "## Collect the Ops Count" 235 | ] 236 | }, 237 | { 238 | "cell_type": "markdown", 239 | "metadata": {}, 240 | "source": [ 241 | "Let the goroutines work for a second. Finally, capture and report the ops count." 242 | ] 243 | }, 244 | { 245 | "cell_type": "code", 246 | "execution_count": 9, 247 | "metadata": { 248 | "collapsed": false 249 | }, 250 | "outputs": [ 251 | { 252 | "data": { 253 | "text/plain": [ 254 | "\u001b[34m\u001b[1m918893\u001b[0m\n" 255 | ] 256 | }, 257 | "execution_count": 9, 258 | "metadata": {}, 259 | "output_type": "execute_result" 260 | } 261 | ], 262 | "source": [ 263 | "opsFinal := atomic.LoadInt64(&ops)" 264 | ] 265 | }, 266 | { 267 | "cell_type": "markdown", 268 | "metadata": {}, 269 | "source": [ 270 | "Running our program shows that the goroutine-based state management example achieves about 800,000 operations per second." 271 | ] 272 | } 273 | ], 274 | "metadata": { 275 | "kernelspec": { 276 | "display_name": "Golang", 277 | "language": "go", 278 | "name": "gophernotes" 279 | }, 280 | "language_info": { 281 | "name": "go" 282 | } 283 | }, 284 | "nbformat": 4, 285 | "nbformat_minor": 0 286 | } 287 | -------------------------------------------------------------------------------- /vendor/github.com/alecthomas/gozmq/zmqgen_2_1.go: -------------------------------------------------------------------------------- 1 | // +build zmq_2_1 2 | // 3 | 4 | package gozmq 5 | 6 | import ( 7 | "time" 8 | ) 9 | 10 | // This file was generated automatically. Changes made here will be lost. 11 | 12 | // Socket Option Getters 13 | 14 | // ZMQ_TYPE: Retrieve socket type. 15 | // 16 | // See: http://api.zeromq.org/2.1:zmq-getsockopt#toc3 17 | // 18 | func (s *Socket) Type() (SocketType, error) { 19 | value, err := s.GetSockOptUInt64(TYPE) 20 | return SocketType(value), err 21 | } 22 | 23 | // ZMQ_RCVMORE: More message parts to follow. 24 | // 25 | // See: http://api.zeromq.org/2.1:zmq-getsockopt#toc4 26 | // 27 | func (s *Socket) RcvMore() (bool, error) { 28 | value, err := s.GetSockOptUInt64(RCVMORE) 29 | return value != 0, err 30 | } 31 | 32 | // ZMQ_HWM: Retrieve high water mark. 33 | // 34 | // See: http://api.zeromq.org/2.1:zmq-getsockopt#toc5 35 | // 36 | func (s *Socket) HWM() (uint64, error) { 37 | return s.GetSockOptUInt64(HWM) 38 | } 39 | 40 | // ZMQ_SWAP: Retrieve disk offload size. 41 | // 42 | // See: http://api.zeromq.org/2.1:zmq-getsockopt#toc6 43 | // 44 | func (s *Socket) Swap() (int64, error) { 45 | return s.GetSockOptInt64(SWAP) 46 | } 47 | 48 | // ZMQ_AFFINITY: Retrieve I/O thread affinity. 49 | // 50 | // See: http://api.zeromq.org/2.1:zmq-getsockopt#toc7 51 | // 52 | func (s *Socket) Affinity() (uint64, error) { 53 | return s.GetSockOptUInt64(AFFINITY) 54 | } 55 | 56 | // ZMQ_IDENTITY: Retrieve socket identity. 57 | // 58 | // See: http://api.zeromq.org/2.1:zmq-getsockopt#toc8 59 | // 60 | func (s *Socket) Identity() (string, error) { 61 | return s.GetSockOptString(IDENTITY) 62 | } 63 | 64 | // ZMQ_RATE: Retrieve multicast data rate. 65 | // 66 | // See: http://api.zeromq.org/2.1:zmq-getsockopt#toc9 67 | // 68 | func (s *Socket) Rate() (int64, error) { 69 | return s.GetSockOptInt64(RATE) 70 | } 71 | 72 | // ZMQ_RECOVERY_IVL_MSEC: Get multicast recovery interval in milliseconds. 73 | // 74 | // See: http://api.zeromq.org/2.1:zmq-getsockopt#toc11 75 | // 76 | func (s *Socket) RecoveryIvl() (time.Duration, error) { 77 | ms, err := s.GetSockOptInt64(RECOVERY_IVL_MSEC) 78 | return time.Duration(ms) * time.Millisecond, err 79 | } 80 | 81 | // ZMQ_MCAST_LOOP: Control multicast loop-back. 82 | // 83 | // See: http://api.zeromq.org/2.1:zmq-getsockopt#toc12 84 | // 85 | func (s *Socket) McastLoop() (bool, error) { 86 | value, err := s.GetSockOptInt64(MCAST_LOOP) 87 | return value != 0, err 88 | } 89 | 90 | // ZMQ_SNDBUF: Retrieve kernel transmit buffer size. 91 | // 92 | // See: http://api.zeromq.org/2.1:zmq-getsockopt#toc13 93 | // 94 | func (s *Socket) SndBuf() (uint64, error) { 95 | return s.GetSockOptUInt64(SNDBUF) 96 | } 97 | 98 | // ZMQ_RCVBUF: Retrieve kernel receive buffer size. 99 | // 100 | // See: http://api.zeromq.org/2.1:zmq-getsockopt#toc14 101 | // 102 | func (s *Socket) RcvBuf() (uint64, error) { 103 | return s.GetSockOptUInt64(RCVBUF) 104 | } 105 | 106 | // ZMQ_LINGER: Retrieve linger period for socket shutdown. 107 | // 108 | // See: http://api.zeromq.org/2.1:zmq-getsockopt#toc15 109 | // 110 | func (s *Socket) Linger() (time.Duration, error) { 111 | ms, err := s.GetSockOptInt(LINGER) 112 | return time.Duration(ms) * time.Millisecond, err 113 | } 114 | 115 | // ZMQ_RECONNECT_IVL: Retrieve reconnection interval. 116 | // 117 | // See: http://api.zeromq.org/2.1:zmq-getsockopt#toc16 118 | // 119 | func (s *Socket) ReconnectIvl() (time.Duration, error) { 120 | ms, err := s.GetSockOptInt(RECONNECT_IVL) 121 | return time.Duration(ms) * time.Millisecond, err 122 | } 123 | 124 | // ZMQ_RECONNECT_IVL_MAX: Retrieve maximum reconnection interval. 125 | // 126 | // See: http://api.zeromq.org/2.1:zmq-getsockopt#toc17 127 | // 128 | func (s *Socket) ReconnectIvlMax() (time.Duration, error) { 129 | ms, err := s.GetSockOptInt(RECONNECT_IVL_MAX) 130 | return time.Duration(ms) * time.Millisecond, err 131 | } 132 | 133 | // ZMQ_BACKLOG: Retrieve maximum length of the queue of outstanding connections. 134 | // 135 | // See: http://api.zeromq.org/2.1:zmq-getsockopt#toc18 136 | // 137 | func (s *Socket) Backlog() (int, error) { 138 | return s.GetSockOptInt(BACKLOG) 139 | } 140 | 141 | // ZMQ_EVENTS: Retrieve socket event state. 142 | // 143 | // See: http://api.zeromq.org/2.1:zmq-getsockopt#toc20 144 | // 145 | func (s *Socket) Events() (uint64, error) { 146 | return s.GetSockOptUInt64(EVENTS) 147 | } 148 | 149 | // Socket Option Setters 150 | 151 | // ZMQ_HWM: Set high water mark. 152 | // 153 | // See: http://api.zeromq.org/2.1:zmq-setsockopt#toc3 154 | // 155 | func (s *Socket) SetHWM(value uint64) error { 156 | return s.SetSockOptUInt64(HWM, value) 157 | } 158 | 159 | // ZMQ_SWAP: Set disk offload size. 160 | // 161 | // See: http://api.zeromq.org/2.1:zmq-setsockopt#toc4 162 | // 163 | func (s *Socket) SetSwap(value int64) error { 164 | return s.SetSockOptInt64(SWAP, value) 165 | } 166 | 167 | // ZMQ_AFFINITY: Set I/O thread affinity. 168 | // 169 | // See: http://api.zeromq.org/2.1:zmq-setsockopt#toc5 170 | // 171 | func (s *Socket) SetAffinity(value uint64) error { 172 | return s.SetSockOptUInt64(AFFINITY, value) 173 | } 174 | 175 | // ZMQ_IDENTITY: Set socket identity. 176 | // 177 | // See: http://api.zeromq.org/2.1:zmq-setsockopt#toc6 178 | // 179 | func (s *Socket) SetIdentity(value string) error { 180 | return s.SetSockOptString(IDENTITY, value) 181 | } 182 | 183 | // ZMQ_SUBSCRIBE: Establish message filter. 184 | // 185 | // See: http://api.zeromq.org/2.1:zmq-setsockopt#toc7 186 | // 187 | func (s *Socket) SetSubscribe(value string) error { 188 | return s.SetSockOptString(SUBSCRIBE, value) 189 | } 190 | 191 | // ZMQ_UNSUBSCRIBE: Remove message filter. 192 | // 193 | // See: http://api.zeromq.org/2.1:zmq-setsockopt#toc8 194 | // 195 | func (s *Socket) SetUnsubscribe(value string) error { 196 | return s.SetSockOptString(UNSUBSCRIBE, value) 197 | } 198 | 199 | // ZMQ_RATE: Set multicast data rate. 200 | // 201 | // See: http://api.zeromq.org/2.1:zmq-setsockopt#toc9 202 | // 203 | func (s *Socket) SetRate(value int64) error { 204 | return s.SetSockOptInt64(RATE, value) 205 | } 206 | 207 | // ZMQ_RECOVERY_IVL_MSEC: Set multicast recovery interval in milliseconds. 208 | // 209 | // See: http://api.zeromq.org/2.1:zmq-setsockopt#toc11 210 | // 211 | func (s *Socket) SetRecoveryIvl(value time.Duration) error { 212 | return s.SetSockOptInt64(RECOVERY_IVL_MSEC, int64(value/time.Millisecond)) 213 | } 214 | 215 | // ZMQ_MCAST_LOOP: Control multicast loop-back. 216 | // 217 | // See: http://api.zeromq.org/2.1:zmq-setsockopt#toc12 218 | // 219 | func (s *Socket) SetMcastLoop(value bool) error { 220 | if value { 221 | return s.SetSockOptInt64(MCAST_LOOP, 1) 222 | } 223 | return s.SetSockOptInt64(MCAST_LOOP, 0) 224 | } 225 | 226 | // ZMQ_SNDBUF: Set kernel transmit buffer size. 227 | // 228 | // See: http://api.zeromq.org/2.1:zmq-setsockopt#toc13 229 | // 230 | func (s *Socket) SetSndBuf(value uint64) error { 231 | return s.SetSockOptUInt64(SNDBUF, value) 232 | } 233 | 234 | // ZMQ_RCVBUF: Set kernel receive buffer size. 235 | // 236 | // See: http://api.zeromq.org/2.1:zmq-setsockopt#toc14 237 | // 238 | func (s *Socket) SetRcvBuf(value uint64) error { 239 | return s.SetSockOptUInt64(RCVBUF, value) 240 | } 241 | 242 | // ZMQ_LINGER: Set linger period for socket shutdown. 243 | // 244 | // See: http://api.zeromq.org/2.1:zmq-setsockopt#toc15 245 | // 246 | func (s *Socket) SetLinger(value time.Duration) error { 247 | return s.SetSockOptInt(LINGER, int(value/time.Millisecond)) 248 | } 249 | 250 | // ZMQ_RECONNECT_IVL: Set reconnection interval. 251 | // 252 | // See: http://api.zeromq.org/2.1:zmq-setsockopt#toc16 253 | // 254 | func (s *Socket) SetReconnectIvl(value time.Duration) error { 255 | return s.SetSockOptInt(RECONNECT_IVL, int(value/time.Millisecond)) 256 | } 257 | 258 | // ZMQ_RECONNECT_IVL_MAX: Set maximum reconnection interval. 259 | // 260 | // See: http://api.zeromq.org/2.1:zmq-setsockopt#toc17 261 | // 262 | func (s *Socket) SetReconnectIvlMax(value time.Duration) error { 263 | return s.SetSockOptInt(RECONNECT_IVL_MAX, int(value/time.Millisecond)) 264 | } 265 | 266 | // ZMQ_BACKLOG: Set maximum length of the queue of outstanding connections. 267 | // 268 | // See: http://api.zeromq.org/2.1:zmq-setsockopt#toc18 269 | // 270 | func (s *Socket) SetBacklog(value int) error { 271 | return s.SetSockOptInt(BACKLOG, value) 272 | } 273 | -------------------------------------------------------------------------------- /vendor/github.com/davecgh/go-spew/spew/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Dave Collins 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | /* 18 | Package spew implements a deep pretty printer for Go data structures to aid in 19 | debugging. 20 | 21 | A quick overview of the additional features spew provides over the built-in 22 | printing facilities for Go data types are as follows: 23 | 24 | * Pointers are dereferenced and followed 25 | * Circular data structures are detected and handled properly 26 | * Custom Stringer/error interfaces are optionally invoked, including 27 | on unexported types 28 | * Custom types which only implement the Stringer/error interfaces via 29 | a pointer receiver are optionally invoked when passing non-pointer 30 | variables 31 | * Byte arrays and slices are dumped like the hexdump -C command which 32 | includes offsets, byte values in hex, and ASCII output (only when using 33 | Dump style) 34 | 35 | There are two different approaches spew allows for dumping Go data structures: 36 | 37 | * Dump style which prints with newlines, customizable indentation, 38 | and additional debug information such as types and all pointer addresses 39 | used to indirect to the final value 40 | * A custom Formatter interface that integrates cleanly with the standard fmt 41 | package and replaces %v, %+v, %#v, and %#+v to provide inline printing 42 | similar to the default %v while providing the additional functionality 43 | outlined above and passing unsupported format verbs such as %x and %q 44 | along to fmt 45 | 46 | Quick Start 47 | 48 | This section demonstrates how to quickly get started with spew. See the 49 | sections below for further details on formatting and configuration options. 50 | 51 | To dump a variable with full newlines, indentation, type, and pointer 52 | information use Dump, Fdump, or Sdump: 53 | spew.Dump(myVar1, myVar2, ...) 54 | spew.Fdump(someWriter, myVar1, myVar2, ...) 55 | str := spew.Sdump(myVar1, myVar2, ...) 56 | 57 | Alternatively, if you would prefer to use format strings with a compacted inline 58 | printing style, use the convenience wrappers Printf, Fprintf, etc with 59 | %v (most compact), %+v (adds pointer addresses), %#v (adds types), or 60 | %#+v (adds types and pointer addresses): 61 | spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2) 62 | spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) 63 | spew.Fprintf(someWriter, "myVar1: %v -- myVar2: %+v", myVar1, myVar2) 64 | spew.Fprintf(someWriter, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) 65 | 66 | Configuration Options 67 | 68 | Configuration of spew is handled by fields in the ConfigState type. For 69 | convenience, all of the top-level functions use a global state available 70 | via the spew.Config global. 71 | 72 | It is also possible to create a ConfigState instance that provides methods 73 | equivalent to the top-level functions. This allows concurrent configuration 74 | options. See the ConfigState documentation for more details. 75 | 76 | The following configuration options are available: 77 | * Indent 78 | String to use for each indentation level for Dump functions. 79 | It is a single space by default. A popular alternative is "\t". 80 | 81 | * MaxDepth 82 | Maximum number of levels to descend into nested data structures. 83 | There is no limit by default. 84 | 85 | * DisableMethods 86 | Disables invocation of error and Stringer interface methods. 87 | Method invocation is enabled by default. 88 | 89 | * DisablePointerMethods 90 | Disables invocation of error and Stringer interface methods on types 91 | which only accept pointer receivers from non-pointer variables. 92 | Pointer method invocation is enabled by default. 93 | 94 | * ContinueOnMethod 95 | Enables recursion into types after invoking error and Stringer interface 96 | methods. Recursion after method invocation is disabled by default. 97 | 98 | * SortKeys 99 | Specifies map keys should be sorted before being printed. Use 100 | this to have a more deterministic, diffable output. Note that 101 | only native types (bool, int, uint, floats, uintptr and string) 102 | and types which implement error or Stringer interfaces are 103 | supported with other types sorted according to the 104 | reflect.Value.String() output which guarantees display 105 | stability. Natural map order is used by default. 106 | 107 | * SpewKeys 108 | Specifies that, as a last resort attempt, map keys should be 109 | spewed to strings and sorted by those strings. This is only 110 | considered if SortKeys is true. 111 | 112 | Dump Usage 113 | 114 | Simply call spew.Dump with a list of variables you want to dump: 115 | 116 | spew.Dump(myVar1, myVar2, ...) 117 | 118 | You may also call spew.Fdump if you would prefer to output to an arbitrary 119 | io.Writer. For example, to dump to standard error: 120 | 121 | spew.Fdump(os.Stderr, myVar1, myVar2, ...) 122 | 123 | A third option is to call spew.Sdump to get the formatted output as a string: 124 | 125 | str := spew.Sdump(myVar1, myVar2, ...) 126 | 127 | Sample Dump Output 128 | 129 | See the Dump example for details on the setup of the types and variables being 130 | shown here. 131 | 132 | (main.Foo) { 133 | unexportedField: (*main.Bar)(0xf84002e210)({ 134 | flag: (main.Flag) flagTwo, 135 | data: (uintptr) 136 | }), 137 | ExportedField: (map[interface {}]interface {}) (len=1) { 138 | (string) (len=3) "one": (bool) true 139 | } 140 | } 141 | 142 | Byte (and uint8) arrays and slices are displayed uniquely like the hexdump -C 143 | command as shown. 144 | ([]uint8) (len=32 cap=32) { 145 | 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 |............... | 146 | 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0| 147 | 00000020 31 32 |12| 148 | } 149 | 150 | Custom Formatter 151 | 152 | Spew provides a custom formatter that implements the fmt.Formatter interface 153 | so that it integrates cleanly with standard fmt package printing functions. The 154 | formatter is useful for inline printing of smaller data types similar to the 155 | standard %v format specifier. 156 | 157 | The custom formatter only responds to the %v (most compact), %+v (adds pointer 158 | addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb 159 | combinations. Any other verbs such as %x and %q will be sent to the the 160 | standard fmt package for formatting. In addition, the custom formatter ignores 161 | the width and precision arguments (however they will still work on the format 162 | specifiers not handled by the custom formatter). 163 | 164 | Custom Formatter Usage 165 | 166 | The simplest way to make use of the spew custom formatter is to call one of the 167 | convenience functions such as spew.Printf, spew.Println, or spew.Printf. The 168 | functions have syntax you are most likely already familiar with: 169 | 170 | spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2) 171 | spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) 172 | spew.Println(myVar, myVar2) 173 | spew.Fprintf(os.Stderr, "myVar1: %v -- myVar2: %+v", myVar1, myVar2) 174 | spew.Fprintf(os.Stderr, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) 175 | 176 | See the Index for the full list convenience functions. 177 | 178 | Sample Formatter Output 179 | 180 | Double pointer to a uint8: 181 | %v: <**>5 182 | %+v: <**>(0xf8400420d0->0xf8400420c8)5 183 | %#v: (**uint8)5 184 | %#+v: (**uint8)(0xf8400420d0->0xf8400420c8)5 185 | 186 | Pointer to circular struct with a uint8 field and a pointer to itself: 187 | %v: <*>{1 <*>} 188 | %+v: <*>(0xf84003e260){ui8:1 c:<*>(0xf84003e260)} 189 | %#v: (*main.circular){ui8:(uint8)1 c:(*main.circular)} 190 | %#+v: (*main.circular)(0xf84003e260){ui8:(uint8)1 c:(*main.circular)(0xf84003e260)} 191 | 192 | See the Printf example for details on the setup of variables being shown 193 | here. 194 | 195 | Errors 196 | 197 | Since it is possible for custom Stringer/error interfaces to panic, spew 198 | detects them and handles them internally by printing the panic information 199 | inline with the output. Since spew is intended to provide deep pretty printing 200 | capabilities on structures, it intentionally does not return any errors. 201 | */ 202 | package spew 203 | -------------------------------------------------------------------------------- /examples/Time-Formatting-Parsing.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Time Formatting / Parsing" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "Go supports time formatting and parsing via pattern-based layouts. Comments from [Go by Example](https://gobyexample.com)." 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "## Imports" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": 1, 27 | "metadata": { 28 | "collapsed": true 29 | }, 30 | "outputs": [], 31 | "source": [ 32 | "import (\n", 33 | " \"fmt\"\n", 34 | " \"time\"\n", 35 | ")" 36 | ] 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "metadata": {}, 41 | "source": [ 42 | "## Basic Time Formatting" 43 | ] 44 | }, 45 | { 46 | "cell_type": "markdown", 47 | "metadata": {}, 48 | "source": [ 49 | "Here’s a basic example of formatting a time according to RFC3339, using the corresponding layout constant." 50 | ] 51 | }, 52 | { 53 | "cell_type": "code", 54 | "execution_count": 2, 55 | "metadata": { 56 | "collapsed": false 57 | }, 58 | "outputs": [ 59 | { 60 | "data": { 61 | "text/plain": [ 62 | "\u001b[34m\u001b[1m2016\u001b[0m-\u001b[34m\u001b[1m09\u001b[0m-\u001b[34m\u001b[1m08\u001b[0m \u001b[34m\u001b[1m07\u001b[0m:\u001b[34m\u001b[1m04\u001b[0m:\u001b[34m\u001b[1m48\u001b[0m \u001b[34m\u001b[1mLocal\u001b[0m\n" 63 | ] 64 | }, 65 | "execution_count": 2, 66 | "metadata": {}, 67 | "output_type": "execute_result" 68 | } 69 | ], 70 | "source": [ 71 | "t := time.Now()" 72 | ] 73 | }, 74 | { 75 | "cell_type": "code", 76 | "execution_count": 3, 77 | "metadata": { 78 | "collapsed": false 79 | }, 80 | "outputs": [ 81 | { 82 | "data": { 83 | "text/plain": [ 84 | "\u001b[31m\u001b[1m\"\u001b[0m\u001b[31m2016-09-08T07:04:49-05:00\u001b[0m\u001b[31m\u001b[1m\"\u001b[0m\n" 85 | ] 86 | }, 87 | "execution_count": 3, 88 | "metadata": {}, 89 | "output_type": "execute_result" 90 | } 91 | ], 92 | "source": [ 93 | "t.Format(time.RFC3339)" 94 | ] 95 | }, 96 | { 97 | "cell_type": "markdown", 98 | "metadata": {}, 99 | "source": [ 100 | "## Time Parsing" 101 | ] 102 | }, 103 | { 104 | "cell_type": "markdown", 105 | "metadata": {}, 106 | "source": [ 107 | "Time parsing uses the same layout values as Format." 108 | ] 109 | }, 110 | { 111 | "cell_type": "code", 112 | "execution_count": 4, 113 | "metadata": { 114 | "collapsed": false 115 | }, 116 | "outputs": [ 117 | { 118 | "data": { 119 | "text/plain": [ 120 | "\u001b[34m\u001b[1m2012\u001b[0m-\u001b[34m\u001b[1m11\u001b[0m-\u001b[34m\u001b[1m01\u001b[0m \u001b[34m\u001b[1m22\u001b[0m:\u001b[34m\u001b[1m08\u001b[0m:\u001b[34m\u001b[1m41\u001b[0m \u001b[34m\u001b[1m\u001b[0m\n" 121 | ] 122 | }, 123 | "execution_count": 4, 124 | "metadata": {}, 125 | "output_type": "execute_result" 126 | } 127 | ], 128 | "source": [ 129 | "t1, _ := time.Parse(time.RFC3339, \"2012-11-01T22:08:41+00:00\")" 130 | ] 131 | }, 132 | { 133 | "cell_type": "markdown", 134 | "metadata": {}, 135 | "source": [ 136 | "Parse will return an error on malformed input explaining the parsing problem." 137 | ] 138 | }, 139 | { 140 | "cell_type": "code", 141 | "execution_count": 5, 142 | "metadata": { 143 | "collapsed": false 144 | }, 145 | "outputs": [ 146 | { 147 | "data": { 148 | "text/plain": [ 149 | "&time.\u001b[32mParseError\u001b[0m{\n", 150 | " \u001b[33mLayout\u001b[0m: \u001b[31m\u001b[1m\"\u001b[0m\u001b[31mMon Jan _2 15:04:05 2006\u001b[0m\u001b[31m\u001b[1m\"\u001b[0m,\n", 151 | " \u001b[33mValue\u001b[0m: \u001b[31m\u001b[1m\"\u001b[0m\u001b[31m8:41PM\u001b[0m\u001b[31m\u001b[1m\"\u001b[0m,\n", 152 | " \u001b[33mLayoutElem\u001b[0m: \u001b[31m\u001b[1m\"\u001b[0m\u001b[31mMon\u001b[0m\u001b[31m\u001b[1m\"\u001b[0m,\n", 153 | " \u001b[33mValueElem\u001b[0m: \u001b[31m\u001b[1m\"\u001b[0m\u001b[31m8:41PM\u001b[0m\u001b[31m\u001b[1m\"\u001b[0m,\n", 154 | " \u001b[33mMessage\u001b[0m: \u001b[31m\u001b[1m\"\u001b[0m\u001b[31m\u001b[1m\"\u001b[0m,\n", 155 | "}\n" 156 | ] 157 | }, 158 | "execution_count": 5, 159 | "metadata": {}, 160 | "output_type": "execute_result" 161 | } 162 | ], 163 | "source": [ 164 | "ansic := \"Mon Jan _2 15:04:05 2006\"\n", 165 | "_, e := time.Parse(ansic, \"8:41PM\")" 166 | ] 167 | }, 168 | { 169 | "cell_type": "markdown", 170 | "metadata": {}, 171 | "source": [ 172 | "## Custom Layouts" 173 | ] 174 | }, 175 | { 176 | "cell_type": "markdown", 177 | "metadata": {}, 178 | "source": [ 179 | "Format and Parse use example-based layouts. Usually you’ll use a constant from time for these layouts, but you can also supply custom layouts. Layouts must use the reference time Mon Jan 2 15:04:05 MST 2006 to show the pattern with which to format/parse a given time/string. The example time must be exactly as shown: the year 2006, 15 for the hour, Monday for the day of the week, etc." 180 | ] 181 | }, 182 | { 183 | "cell_type": "code", 184 | "execution_count": 6, 185 | "metadata": { 186 | "collapsed": false 187 | }, 188 | "outputs": [ 189 | { 190 | "data": { 191 | "text/plain": [ 192 | "\u001b[31m\u001b[1m\"\u001b[0m\u001b[31m7:05AM\u001b[0m\u001b[31m\u001b[1m\"\u001b[0m\n" 193 | ] 194 | }, 195 | "execution_count": 6, 196 | "metadata": {}, 197 | "output_type": "execute_result" 198 | } 199 | ], 200 | "source": [ 201 | "t.Format(\"3:04PM\")" 202 | ] 203 | }, 204 | { 205 | "cell_type": "code", 206 | "execution_count": 7, 207 | "metadata": { 208 | "collapsed": false 209 | }, 210 | "outputs": [ 211 | { 212 | "data": { 213 | "text/plain": [ 214 | "\u001b[31m\u001b[1m\"\u001b[0m\u001b[31mThu Sep 8 07:05:16 2016\u001b[0m\u001b[31m\u001b[1m\"\u001b[0m\n" 215 | ] 216 | }, 217 | "execution_count": 7, 218 | "metadata": {}, 219 | "output_type": "execute_result" 220 | } 221 | ], 222 | "source": [ 223 | "t.Format(\"Mon Jan _2 15:04:05 2006\")" 224 | ] 225 | }, 226 | { 227 | "cell_type": "code", 228 | "execution_count": 8, 229 | "metadata": { 230 | "collapsed": false 231 | }, 232 | "outputs": [ 233 | { 234 | "data": { 235 | "text/plain": [ 236 | "\u001b[31m\u001b[1m\"\u001b[0m\u001b[31m2016-09-08T07:05:17.689228-05:00\u001b[0m\u001b[31m\u001b[1m\"\u001b[0m\n" 237 | ] 238 | }, 239 | "execution_count": 8, 240 | "metadata": {}, 241 | "output_type": "execute_result" 242 | } 243 | ], 244 | "source": [ 245 | "t.Format(\"2006-01-02T15:04:05.999999-07:00\")" 246 | ] 247 | }, 248 | { 249 | "cell_type": "code", 250 | "execution_count": 9, 251 | "metadata": { 252 | "collapsed": false 253 | }, 254 | "outputs": [ 255 | { 256 | "data": { 257 | "text/plain": [ 258 | "\u001b[34m\u001b[1m0\u001b[0m-\u001b[34m\u001b[1m01\u001b[0m-\u001b[34m\u001b[1m01\u001b[0m \u001b[34m\u001b[1m20\u001b[0m:\u001b[34m\u001b[1m41\u001b[0m:\u001b[34m\u001b[1m00\u001b[0m \u001b[34m\u001b[1mUTC\u001b[0m\n" 259 | ] 260 | }, 261 | "execution_count": 9, 262 | "metadata": {}, 263 | "output_type": "execute_result" 264 | } 265 | ], 266 | "source": [ 267 | "form := \"3 04 PM\"\n", 268 | "t2, _ := time.Parse(form, \"8 41 PM\")" 269 | ] 270 | }, 271 | { 272 | "cell_type": "markdown", 273 | "metadata": {}, 274 | "source": [ 275 | "## String Formatting" 276 | ] 277 | }, 278 | { 279 | "cell_type": "markdown", 280 | "metadata": {}, 281 | "source": [ 282 | "For purely numeric representations you can also use standard string formatting with the extracted components of the time value." 283 | ] 284 | }, 285 | { 286 | "cell_type": "code", 287 | "execution_count": 10, 288 | "metadata": { 289 | "collapsed": false 290 | }, 291 | "outputs": [ 292 | { 293 | "data": { 294 | "text/plain": [ 295 | "2016-09-08T07:05:21-00:00\n", 296 | "\u001b[34m\u001b[1m26\u001b[0m\n", 297 | "\u001b[36m\u001b[1mnil\u001b[0m\n" 298 | ] 299 | }, 300 | "execution_count": 10, 301 | "metadata": {}, 302 | "output_type": "execute_result" 303 | } 304 | ], 305 | "source": [ 306 | "fmt.Printf(\"%d-%02d-%02dT%02d:%02d:%02d-00:00\\n\",\n", 307 | " t.Year(), t.Month(), t.Day(),\n", 308 | " t.Hour(), t.Minute(), t.Second())" 309 | ] 310 | } 311 | ], 312 | "metadata": { 313 | "kernelspec": { 314 | "display_name": "Golang", 315 | "language": "go", 316 | "name": "gophernotes" 317 | }, 318 | "language_info": { 319 | "name": "go" 320 | } 321 | }, 322 | "nbformat": 4, 323 | "nbformat_minor": 0 324 | } 325 | -------------------------------------------------------------------------------- /vendor/golang.org/x/tools/imports/imports.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:generate go run mkstdlib.go 6 | 7 | // Package imports implements a Go pretty-printer (like package "go/format") 8 | // that also adds or removes import statements as necessary. 9 | package imports 10 | 11 | import ( 12 | "bufio" 13 | "bytes" 14 | "fmt" 15 | "go/ast" 16 | "go/format" 17 | "go/parser" 18 | "go/printer" 19 | "go/token" 20 | "io" 21 | "regexp" 22 | "strconv" 23 | "strings" 24 | 25 | "golang.org/x/tools/go/ast/astutil" 26 | ) 27 | 28 | // Options specifies options for processing files. 29 | type Options struct { 30 | Fragment bool // Accept fragment of a source file (no package statement) 31 | AllErrors bool // Report all errors (not just the first 10 on different lines) 32 | 33 | Comments bool // Print comments (true if nil *Options provided) 34 | TabIndent bool // Use tabs for indent (true if nil *Options provided) 35 | TabWidth int // Tab width (8 if nil *Options provided) 36 | 37 | FormatOnly bool // Disable the insertion and deletion of imports 38 | } 39 | 40 | // Process formats and adjusts imports for the provided file. 41 | // If opt is nil the defaults are used. 42 | // 43 | // Note that filename's directory influences which imports can be chosen, 44 | // so it is important that filename be accurate. 45 | // To process data ``as if'' it were in filename, pass the data as a non-nil src. 46 | func Process(filename string, src []byte, opt *Options) ([]byte, error) { 47 | if opt == nil { 48 | opt = &Options{Comments: true, TabIndent: true, TabWidth: 8} 49 | } 50 | 51 | fileSet := token.NewFileSet() 52 | file, adjust, err := parse(fileSet, filename, src, opt) 53 | if err != nil { 54 | return nil, err 55 | } 56 | 57 | if !opt.FormatOnly { 58 | _, err = fixImports(fileSet, file, filename) 59 | if err != nil { 60 | return nil, err 61 | } 62 | } 63 | 64 | sortImports(fileSet, file) 65 | imps := astutil.Imports(fileSet, file) 66 | 67 | var spacesBefore []string // import paths we need spaces before 68 | for _, impSection := range imps { 69 | // Within each block of contiguous imports, see if any 70 | // import lines are in different group numbers. If so, 71 | // we'll need to put a space between them so it's 72 | // compatible with gofmt. 73 | lastGroup := -1 74 | for _, importSpec := range impSection { 75 | importPath, _ := strconv.Unquote(importSpec.Path.Value) 76 | groupNum := importGroup(importPath) 77 | if groupNum != lastGroup && lastGroup != -1 { 78 | spacesBefore = append(spacesBefore, importPath) 79 | } 80 | lastGroup = groupNum 81 | } 82 | 83 | } 84 | 85 | printerMode := printer.UseSpaces 86 | if opt.TabIndent { 87 | printerMode |= printer.TabIndent 88 | } 89 | printConfig := &printer.Config{Mode: printerMode, Tabwidth: opt.TabWidth} 90 | 91 | var buf bytes.Buffer 92 | err = printConfig.Fprint(&buf, fileSet, file) 93 | if err != nil { 94 | return nil, err 95 | } 96 | out := buf.Bytes() 97 | if adjust != nil { 98 | out = adjust(src, out) 99 | } 100 | if len(spacesBefore) > 0 { 101 | out = addImportSpaces(bytes.NewReader(out), spacesBefore) 102 | } 103 | 104 | out, err = format.Source(out) 105 | if err != nil { 106 | return nil, err 107 | } 108 | return out, nil 109 | } 110 | 111 | // parse parses src, which was read from filename, 112 | // as a Go source file or statement list. 113 | func parse(fset *token.FileSet, filename string, src []byte, opt *Options) (*ast.File, func(orig, src []byte) []byte, error) { 114 | parserMode := parser.Mode(0) 115 | if opt.Comments { 116 | parserMode |= parser.ParseComments 117 | } 118 | if opt.AllErrors { 119 | parserMode |= parser.AllErrors 120 | } 121 | 122 | // Try as whole source file. 123 | file, err := parser.ParseFile(fset, filename, src, parserMode) 124 | if err == nil { 125 | return file, nil, nil 126 | } 127 | // If the error is that the source file didn't begin with a 128 | // package line and we accept fragmented input, fall through to 129 | // try as a source fragment. Stop and return on any other error. 130 | if !opt.Fragment || !strings.Contains(err.Error(), "expected 'package'") { 131 | return nil, nil, err 132 | } 133 | 134 | // If this is a declaration list, make it a source file 135 | // by inserting a package clause. 136 | // Insert using a ;, not a newline, so that the line numbers 137 | // in psrc match the ones in src. 138 | psrc := append([]byte("package main;"), src...) 139 | file, err = parser.ParseFile(fset, filename, psrc, parserMode) 140 | if err == nil { 141 | // If a main function exists, we will assume this is a main 142 | // package and leave the file. 143 | if containsMainFunc(file) { 144 | return file, nil, nil 145 | } 146 | 147 | adjust := func(orig, src []byte) []byte { 148 | // Remove the package clause. 149 | // Gofmt has turned the ; into a \n. 150 | src = src[len("package main\n"):] 151 | return matchSpace(orig, src) 152 | } 153 | return file, adjust, nil 154 | } 155 | // If the error is that the source file didn't begin with a 156 | // declaration, fall through to try as a statement list. 157 | // Stop and return on any other error. 158 | if !strings.Contains(err.Error(), "expected declaration") { 159 | return nil, nil, err 160 | } 161 | 162 | // If this is a statement list, make it a source file 163 | // by inserting a package clause and turning the list 164 | // into a function body. This handles expressions too. 165 | // Insert using a ;, not a newline, so that the line numbers 166 | // in fsrc match the ones in src. 167 | fsrc := append(append([]byte("package p; func _() {"), src...), '}') 168 | file, err = parser.ParseFile(fset, filename, fsrc, parserMode) 169 | if err == nil { 170 | adjust := func(orig, src []byte) []byte { 171 | // Remove the wrapping. 172 | // Gofmt has turned the ; into a \n\n. 173 | src = src[len("package p\n\nfunc _() {"):] 174 | src = src[:len(src)-len("}\n")] 175 | // Gofmt has also indented the function body one level. 176 | // Remove that indent. 177 | src = bytes.Replace(src, []byte("\n\t"), []byte("\n"), -1) 178 | return matchSpace(orig, src) 179 | } 180 | return file, adjust, nil 181 | } 182 | 183 | // Failed, and out of options. 184 | return nil, nil, err 185 | } 186 | 187 | // containsMainFunc checks if a file contains a function declaration with the 188 | // function signature 'func main()' 189 | func containsMainFunc(file *ast.File) bool { 190 | for _, decl := range file.Decls { 191 | if f, ok := decl.(*ast.FuncDecl); ok { 192 | if f.Name.Name != "main" { 193 | continue 194 | } 195 | 196 | if len(f.Type.Params.List) != 0 { 197 | continue 198 | } 199 | 200 | if f.Type.Results != nil && len(f.Type.Results.List) != 0 { 201 | continue 202 | } 203 | 204 | return true 205 | } 206 | } 207 | 208 | return false 209 | } 210 | 211 | func cutSpace(b []byte) (before, middle, after []byte) { 212 | i := 0 213 | for i < len(b) && (b[i] == ' ' || b[i] == '\t' || b[i] == '\n') { 214 | i++ 215 | } 216 | j := len(b) 217 | for j > 0 && (b[j-1] == ' ' || b[j-1] == '\t' || b[j-1] == '\n') { 218 | j-- 219 | } 220 | if i <= j { 221 | return b[:i], b[i:j], b[j:] 222 | } 223 | return nil, nil, b[j:] 224 | } 225 | 226 | // matchSpace reformats src to use the same space context as orig. 227 | // 1) If orig begins with blank lines, matchSpace inserts them at the beginning of src. 228 | // 2) matchSpace copies the indentation of the first non-blank line in orig 229 | // to every non-blank line in src. 230 | // 3) matchSpace copies the trailing space from orig and uses it in place 231 | // of src's trailing space. 232 | func matchSpace(orig []byte, src []byte) []byte { 233 | before, _, after := cutSpace(orig) 234 | i := bytes.LastIndex(before, []byte{'\n'}) 235 | before, indent := before[:i+1], before[i+1:] 236 | 237 | _, src, _ = cutSpace(src) 238 | 239 | var b bytes.Buffer 240 | b.Write(before) 241 | for len(src) > 0 { 242 | line := src 243 | if i := bytes.IndexByte(line, '\n'); i >= 0 { 244 | line, src = line[:i+1], line[i+1:] 245 | } else { 246 | src = nil 247 | } 248 | if len(line) > 0 && line[0] != '\n' { // not blank 249 | b.Write(indent) 250 | } 251 | b.Write(line) 252 | } 253 | b.Write(after) 254 | return b.Bytes() 255 | } 256 | 257 | var impLine = regexp.MustCompile(`^\s+(?:[\w\.]+\s+)?"(.+)"`) 258 | 259 | func addImportSpaces(r io.Reader, breaks []string) []byte { 260 | var out bytes.Buffer 261 | sc := bufio.NewScanner(r) 262 | inImports := false 263 | done := false 264 | for sc.Scan() { 265 | s := sc.Text() 266 | 267 | if !inImports && !done && strings.HasPrefix(s, "import") { 268 | inImports = true 269 | } 270 | if inImports && (strings.HasPrefix(s, "var") || 271 | strings.HasPrefix(s, "func") || 272 | strings.HasPrefix(s, "const") || 273 | strings.HasPrefix(s, "type")) { 274 | done = true 275 | inImports = false 276 | } 277 | if inImports && len(breaks) > 0 { 278 | if m := impLine.FindStringSubmatch(s); m != nil { 279 | if m[1] == string(breaks[0]) { 280 | out.WriteByte('\n') 281 | breaks = breaks[1:] 282 | } 283 | } 284 | } 285 | 286 | fmt.Fprintln(&out, s) 287 | } 288 | return out.Bytes() 289 | } 290 | -------------------------------------------------------------------------------- /vendor/github.com/alecthomas/gozmq/zmqgen_2_2.go: -------------------------------------------------------------------------------- 1 | // +build !zmq_2_1,!zmq_3_x,!zmq_4_x 2 | // 3 | 4 | package gozmq 5 | 6 | import ( 7 | "time" 8 | ) 9 | 10 | // This file was generated automatically. Changes made here will be lost. 11 | 12 | // Socket Option Getters 13 | 14 | // ZMQ_TYPE: Retrieve socket type. 15 | // 16 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc3 17 | // 18 | func (s *Socket) Type() (SocketType, error) { 19 | value, err := s.GetSockOptUInt64(TYPE) 20 | return SocketType(value), err 21 | } 22 | 23 | // ZMQ_RCVMORE: More message parts to follow. 24 | // 25 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc4 26 | // 27 | func (s *Socket) RcvMore() (bool, error) { 28 | value, err := s.GetSockOptUInt64(RCVMORE) 29 | return value != 0, err 30 | } 31 | 32 | // ZMQ_HWM: Retrieve high water mark. 33 | // 34 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc5 35 | // 36 | func (s *Socket) HWM() (uint64, error) { 37 | return s.GetSockOptUInt64(HWM) 38 | } 39 | 40 | // ZMQ_RCVTIMEO: Maximum time before a socket operation returns with EAGAIN. 41 | // 42 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc6 43 | // 44 | func (s *Socket) RcvTimeout() (time.Duration, error) { 45 | ms, err := s.GetSockOptInt(RCVTIMEO) 46 | return time.Duration(ms) * time.Millisecond, err 47 | } 48 | 49 | // ZMQ_SNDTIMEO: Maximum time before a socket operation returns with EAGAIN. 50 | // 51 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc7 52 | // 53 | func (s *Socket) SndTimeout() (time.Duration, error) { 54 | ms, err := s.GetSockOptInt(SNDTIMEO) 55 | return time.Duration(ms) * time.Millisecond, err 56 | } 57 | 58 | // ZMQ_SWAP: Retrieve disk offload size. 59 | // 60 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc8 61 | // 62 | func (s *Socket) Swap() (int64, error) { 63 | return s.GetSockOptInt64(SWAP) 64 | } 65 | 66 | // ZMQ_AFFINITY: Retrieve I/O thread affinity. 67 | // 68 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc9 69 | // 70 | func (s *Socket) Affinity() (uint64, error) { 71 | return s.GetSockOptUInt64(AFFINITY) 72 | } 73 | 74 | // ZMQ_IDENTITY: Retrieve socket identity. 75 | // 76 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc10 77 | // 78 | func (s *Socket) Identity() (string, error) { 79 | return s.GetSockOptString(IDENTITY) 80 | } 81 | 82 | // ZMQ_RATE: Retrieve multicast data rate. 83 | // 84 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc11 85 | // 86 | func (s *Socket) Rate() (int64, error) { 87 | return s.GetSockOptInt64(RATE) 88 | } 89 | 90 | // ZMQ_RECOVERY_IVL_MSEC: Get multicast recovery interval in milliseconds. 91 | // 92 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc13 93 | // 94 | func (s *Socket) RecoveryIvl() (time.Duration, error) { 95 | ms, err := s.GetSockOptInt64(RECOVERY_IVL_MSEC) 96 | return time.Duration(ms) * time.Millisecond, err 97 | } 98 | 99 | // ZMQ_MCAST_LOOP: Control multicast loop-back. 100 | // 101 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc14 102 | // 103 | func (s *Socket) McastLoop() (bool, error) { 104 | value, err := s.GetSockOptInt64(MCAST_LOOP) 105 | return value != 0, err 106 | } 107 | 108 | // ZMQ_SNDBUF: Retrieve kernel transmit buffer size. 109 | // 110 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc15 111 | // 112 | func (s *Socket) SndBuf() (uint64, error) { 113 | return s.GetSockOptUInt64(SNDBUF) 114 | } 115 | 116 | // ZMQ_RCVBUF: Retrieve kernel receive buffer size. 117 | // 118 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc16 119 | // 120 | func (s *Socket) RcvBuf() (uint64, error) { 121 | return s.GetSockOptUInt64(RCVBUF) 122 | } 123 | 124 | // ZMQ_LINGER: Retrieve linger period for socket shutdown. 125 | // 126 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc17 127 | // 128 | func (s *Socket) Linger() (time.Duration, error) { 129 | ms, err := s.GetSockOptInt(LINGER) 130 | return time.Duration(ms) * time.Millisecond, err 131 | } 132 | 133 | // ZMQ_RECONNECT_IVL: Retrieve reconnection interval. 134 | // 135 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc18 136 | // 137 | func (s *Socket) ReconnectIvl() (time.Duration, error) { 138 | ms, err := s.GetSockOptInt(RECONNECT_IVL) 139 | return time.Duration(ms) * time.Millisecond, err 140 | } 141 | 142 | // ZMQ_RECONNECT_IVL_MAX: Retrieve maximum reconnection interval. 143 | // 144 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc19 145 | // 146 | func (s *Socket) ReconnectIvlMax() (time.Duration, error) { 147 | ms, err := s.GetSockOptInt(RECONNECT_IVL_MAX) 148 | return time.Duration(ms) * time.Millisecond, err 149 | } 150 | 151 | // ZMQ_BACKLOG: Retrieve maximum length of the queue of outstanding connections. 152 | // 153 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc20 154 | // 155 | func (s *Socket) Backlog() (int, error) { 156 | return s.GetSockOptInt(BACKLOG) 157 | } 158 | 159 | // ZMQ_EVENTS: Retrieve socket event state. 160 | // 161 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc22 162 | // 163 | func (s *Socket) Events() (uint64, error) { 164 | return s.GetSockOptUInt64(EVENTS) 165 | } 166 | 167 | // Socket Option Setters 168 | 169 | // ZMQ_HWM: Set high water mark. 170 | // 171 | // See: http://api.zeromq.org/2.2:zmq-setsockopt#toc3 172 | // 173 | func (s *Socket) SetHWM(value uint64) error { 174 | return s.SetSockOptUInt64(HWM, value) 175 | } 176 | 177 | // ZMQ_SWAP: Set disk offload size. 178 | // 179 | // See: http://api.zeromq.org/2.2:zmq-setsockopt#toc4 180 | // 181 | func (s *Socket) SetSwap(value int64) error { 182 | return s.SetSockOptInt64(SWAP, value) 183 | } 184 | 185 | // ZMQ_AFFINITY: Set I/O thread affinity. 186 | // 187 | // See: http://api.zeromq.org/2.2:zmq-setsockopt#toc5 188 | // 189 | func (s *Socket) SetAffinity(value uint64) error { 190 | return s.SetSockOptUInt64(AFFINITY, value) 191 | } 192 | 193 | // ZMQ_IDENTITY: Set socket identity. 194 | // 195 | // See: http://api.zeromq.org/2.2:zmq-setsockopt#toc6 196 | // 197 | func (s *Socket) SetIdentity(value string) error { 198 | return s.SetSockOptString(IDENTITY, value) 199 | } 200 | 201 | // ZMQ_SUBSCRIBE: Establish message filter. 202 | // 203 | // See: http://api.zeromq.org/2.2:zmq-setsockopt#toc7 204 | // 205 | func (s *Socket) SetSubscribe(value string) error { 206 | return s.SetSockOptString(SUBSCRIBE, value) 207 | } 208 | 209 | // ZMQ_UNSUBSCRIBE: Remove message filter. 210 | // 211 | // See: http://api.zeromq.org/2.2:zmq-setsockopt#toc8 212 | // 213 | func (s *Socket) SetUnsubscribe(value string) error { 214 | return s.SetSockOptString(UNSUBSCRIBE, value) 215 | } 216 | 217 | // ZMQ_RCVTIMEO: Maximum time before a recv operation returns with EAGAIN. 218 | // 219 | // See: http://api.zeromq.org/2.2:zmq-setsockopt#toc9 220 | // 221 | func (s *Socket) SetRcvTimeout(value time.Duration) error { 222 | return s.SetSockOptInt(RCVTIMEO, int(value/time.Millisecond)) 223 | } 224 | 225 | // ZMQ_SNDTIMEO: Maximum time before a send operation returns with EAGAIN. 226 | // 227 | // See: http://api.zeromq.org/2.2:zmq-setsockopt#toc10 228 | // 229 | func (s *Socket) SetSndTimeout(value time.Duration) error { 230 | return s.SetSockOptInt(SNDTIMEO, int(value/time.Millisecond)) 231 | } 232 | 233 | // ZMQ_RATE: Set multicast data rate. 234 | // 235 | // See: http://api.zeromq.org/2.2:zmq-setsockopt#toc11 236 | // 237 | func (s *Socket) SetRate(value int64) error { 238 | return s.SetSockOptInt64(RATE, value) 239 | } 240 | 241 | // ZMQ_RECOVERY_IVL_MSEC: Set multicast recovery interval in milliseconds. 242 | // 243 | // See: http://api.zeromq.org/2.2:zmq-setsockopt#toc13 244 | // 245 | func (s *Socket) SetRecoveryIvl(value time.Duration) error { 246 | return s.SetSockOptInt64(RECOVERY_IVL_MSEC, int64(value/time.Millisecond)) 247 | } 248 | 249 | // ZMQ_MCAST_LOOP: Control multicast loop-back. 250 | // 251 | // See: http://api.zeromq.org/2.2:zmq-setsockopt#toc14 252 | // 253 | func (s *Socket) SetMcastLoop(value bool) error { 254 | if value { 255 | return s.SetSockOptInt64(MCAST_LOOP, 1) 256 | } 257 | return s.SetSockOptInt64(MCAST_LOOP, 0) 258 | } 259 | 260 | // ZMQ_SNDBUF: Set kernel transmit buffer size. 261 | // 262 | // See: http://api.zeromq.org/2.2:zmq-setsockopt#toc15 263 | // 264 | func (s *Socket) SetSndBuf(value uint64) error { 265 | return s.SetSockOptUInt64(SNDBUF, value) 266 | } 267 | 268 | // ZMQ_RCVBUF: Set kernel receive buffer size. 269 | // 270 | // See: http://api.zeromq.org/2.2:zmq-setsockopt#toc16 271 | // 272 | func (s *Socket) SetRcvBuf(value uint64) error { 273 | return s.SetSockOptUInt64(RCVBUF, value) 274 | } 275 | 276 | // ZMQ_LINGER: Set linger period for socket shutdown. 277 | // 278 | // See: http://api.zeromq.org/2.2:zmq-setsockopt#toc17 279 | // 280 | func (s *Socket) SetLinger(value time.Duration) error { 281 | return s.SetSockOptInt(LINGER, int(value/time.Millisecond)) 282 | } 283 | 284 | // ZMQ_RECONNECT_IVL: Set reconnection interval. 285 | // 286 | // See: http://api.zeromq.org/2.2:zmq-setsockopt#toc18 287 | // 288 | func (s *Socket) SetReconnectIvl(value time.Duration) error { 289 | return s.SetSockOptInt(RECONNECT_IVL, int(value/time.Millisecond)) 290 | } 291 | 292 | // ZMQ_RECONNECT_IVL_MAX: Set maximum reconnection interval. 293 | // 294 | // See: http://api.zeromq.org/2.2:zmq-setsockopt#toc19 295 | // 296 | func (s *Socket) SetReconnectIvlMax(value time.Duration) error { 297 | return s.SetSockOptInt(RECONNECT_IVL_MAX, int(value/time.Millisecond)) 298 | } 299 | 300 | // ZMQ_BACKLOG: Set maximum length of the queue of outstanding connections. 301 | // 302 | // See: http://api.zeromq.org/2.2:zmq-setsockopt#toc20 303 | // 304 | func (s *Socket) SetBacklog(value int) error { 305 | return s.SetSockOptInt(BACKLOG, value) 306 | } 307 | -------------------------------------------------------------------------------- /internal/repl/commands.go: -------------------------------------------------------------------------------- 1 | package replpkg 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "os" 7 | "os/exec" 8 | "path" 9 | "path/filepath" 10 | "runtime" 11 | "strings" 12 | "text/tabwriter" 13 | "time" 14 | 15 | "go/ast" 16 | "go/build" 17 | "go/importer" 18 | "go/types" 19 | 20 | "golang.org/x/tools/go/ast/astutil" 21 | ) 22 | 23 | type command struct { 24 | name string 25 | action func(*Session, string) (string, error) 26 | complete func(*Session, string) []string 27 | arg string 28 | document string 29 | } 30 | 31 | // TODO 32 | // - :edit 33 | // - :undo 34 | // - :reset 35 | // - :type 36 | var commands []command 37 | 38 | func init() { 39 | commands = []command{ 40 | { 41 | name: "import", 42 | action: actionImport, 43 | complete: completeImport, 44 | arg: "", 45 | document: "import a package", 46 | }, 47 | { 48 | name: "print", 49 | action: actionPrint, 50 | document: "print current source", 51 | }, 52 | { 53 | name: "write", 54 | action: actionWrite, 55 | complete: nil, // TODO implement 56 | arg: "[]", 57 | document: "write out current source", 58 | }, 59 | { 60 | name: "help", 61 | action: actionHelp, 62 | document: "show this help", 63 | }, 64 | { 65 | name: "quit", 66 | action: actionQuit, 67 | document: "quit the session", 68 | }, 69 | { 70 | name: "containerize", 71 | action: actionContainerize, 72 | document: "containerize go binary", 73 | }, 74 | } 75 | } 76 | 77 | func actionImport(s *Session, arg string) (string, error) { 78 | if arg == "" { 79 | return "", fmt.Errorf("arg required") 80 | } 81 | 82 | path := strings.Trim(arg, `"`) 83 | 84 | // check if the package specified by path is importable 85 | _, err := importer.Default().Import(path) 86 | if err != nil { 87 | return "", err 88 | } 89 | 90 | astutil.AddImport(s.Fset, s.File, path) 91 | 92 | return "", nil 93 | } 94 | 95 | var gorootSrc = filepath.Join(filepath.Clean(runtime.GOROOT()), "src") 96 | 97 | func completeImport(s *Session, prefix string) []string { 98 | result := []string{} 99 | seen := map[string]bool{} 100 | 101 | d, fn := path.Split(prefix) 102 | for _, srcDir := range build.Default.SrcDirs() { 103 | dir := filepath.Join(srcDir, d) 104 | 105 | if fi, err := os.Stat(dir); err != nil || !fi.IsDir() { 106 | if err != nil && !os.IsNotExist(err) { 107 | errorf("Stat %s: %s", dir, err.Error()) 108 | } 109 | continue 110 | } 111 | 112 | entries, err := ioutil.ReadDir(dir) 113 | if err != nil { 114 | errorf("ReadDir %s: %s", dir, err.Error()) 115 | continue 116 | } 117 | for _, fi := range entries { 118 | if !fi.IsDir() { 119 | continue 120 | } 121 | 122 | name := fi.Name() 123 | if strings.HasPrefix(name, ".") || strings.HasPrefix(name, "_") || name == "testdata" { 124 | continue 125 | } 126 | 127 | if strings.HasPrefix(name, fn) { 128 | r := path.Join(d, name) 129 | if srcDir != gorootSrc { 130 | // append "/" if this directory is not a repository 131 | // e.g. does not have VCS directory such as .git or .hg 132 | // TODO: do not append "/" to subdirectories of repos 133 | var isRepo bool 134 | for _, vcsDir := range []string{".git", ".hg", ".svn", ".bzr"} { 135 | _, err := os.Stat(filepath.Join(srcDir, filepath.FromSlash(r), vcsDir)) 136 | if err == nil { 137 | isRepo = true 138 | break 139 | } 140 | } 141 | if !isRepo { 142 | r = r + "/" 143 | } 144 | } 145 | 146 | if !seen[r] { 147 | result = append(result, r) 148 | seen[r] = true 149 | } 150 | } 151 | } 152 | } 153 | 154 | return result 155 | } 156 | 157 | func actionPrint(s *Session, _ string) (string, error) { 158 | source, err := s.source(true) 159 | 160 | if err == nil { 161 | fmt.Println(source) 162 | } 163 | 164 | return source, err 165 | } 166 | 167 | func actionWrite(s *Session, filename string) (string, error) { 168 | source, err := s.source(false) 169 | if err != nil { 170 | return "", err 171 | } 172 | 173 | if filename == "" { 174 | filename = fmt.Sprintf("gore_session_%s.go", time.Now().Format("20060102_150405")) 175 | } 176 | 177 | err = ioutil.WriteFile(filename, []byte(source), 0644) 178 | if err != nil { 179 | return "", err 180 | } 181 | 182 | infof("Source wrote to %s", filename) 183 | 184 | return "", nil 185 | } 186 | 187 | func actionDoc(s *Session, in string) (string, error) { 188 | s.clearQuickFix() 189 | 190 | s.storeMainBody() 191 | defer s.restoreMainBody() 192 | 193 | expr, err := s.evalExpr(in) 194 | if err != nil { 195 | return "", err 196 | } 197 | 198 | s.TypeInfo = types.Info{ 199 | Types: make(map[ast.Expr]types.TypeAndValue), 200 | Uses: make(map[*ast.Ident]types.Object), 201 | Defs: make(map[*ast.Ident]types.Object), 202 | Scopes: make(map[ast.Node]*types.Scope), 203 | } 204 | _, err = s.Types.Check("_tmp", s.Fset, []*ast.File{s.File}, &s.TypeInfo) 205 | if err != nil { 206 | debugf("typecheck error (ignored): %s", err) 207 | } 208 | 209 | // :doc patterns: 210 | // - "json" -> "encoding/json" (package name) 211 | // - "json.Encoder" -> "encoding/json", "Encoder" (package member) 212 | // - "json.NewEncoder(nil).Encode" -> "encoding/json", "Decode" (package type member) 213 | var docObj types.Object 214 | if sel, ok := expr.(*ast.SelectorExpr); ok { 215 | // package member, package type member 216 | docObj = s.TypeInfo.ObjectOf(sel.Sel) 217 | } else if t := s.TypeInfo.TypeOf(expr); t != nil && t != types.Typ[types.Invalid] { 218 | for { 219 | if pt, ok := t.(*types.Pointer); ok { 220 | t = pt.Elem() 221 | } else { 222 | break 223 | } 224 | } 225 | switch t := t.(type) { 226 | case *types.Named: 227 | docObj = t.Obj() 228 | case *types.Basic: 229 | // builtin types 230 | docObj = types.Universe.Lookup(t.Name()) 231 | } 232 | } else if ident, ok := expr.(*ast.Ident); ok { 233 | // package name 234 | mainScope := s.TypeInfo.Scopes[s.mainFunc().Type] 235 | _, docObj = mainScope.LookupParent(ident.Name, ident.NamePos) 236 | } 237 | 238 | if docObj == nil { 239 | return "", fmt.Errorf("cannot determine the document location") 240 | } 241 | 242 | debugf("doc :: obj=%#v", docObj) 243 | 244 | var pkgPath, objName string 245 | if pkgName, ok := docObj.(*types.PkgName); ok { 246 | pkgPath = pkgName.Imported().Path() 247 | } else { 248 | if pkg := docObj.Pkg(); pkg != nil { 249 | pkgPath = pkg.Path() 250 | } else { 251 | pkgPath = "builtin" 252 | } 253 | objName = docObj.Name() 254 | } 255 | 256 | debugf("doc :: %q %q", pkgPath, objName) 257 | 258 | args := []string{pkgPath} 259 | if objName != "" { 260 | args = append(args, objName) 261 | } 262 | 263 | godoc := exec.Command("godoc", args...) 264 | godoc.Stderr = os.Stderr 265 | 266 | // TODO just use PAGER? 267 | if pagerCmd := os.Getenv("GORE_PAGER"); pagerCmd != "" { 268 | r, err := godoc.StdoutPipe() 269 | if err != nil { 270 | return "", err 271 | } 272 | 273 | pager := exec.Command(pagerCmd) 274 | pager.Stdin = r 275 | pager.Stdout = os.Stdout 276 | pager.Stderr = os.Stderr 277 | 278 | err = pager.Start() 279 | if err != nil { 280 | return "", err 281 | } 282 | 283 | err = godoc.Run() 284 | if err != nil { 285 | return "", err 286 | } 287 | 288 | return "", pager.Wait() 289 | } 290 | 291 | godoc.Stdout = os.Stdout 292 | return "", godoc.Run() 293 | 294 | } 295 | 296 | func actionHelp(s *Session, _ string) (string, error) { 297 | w := tabwriter.NewWriter(os.Stdout, 0, 8, 4, ' ', 0) 298 | for _, command := range commands { 299 | cmd := ":" + command.name 300 | if command.arg != "" { 301 | cmd = cmd + " " + command.arg 302 | } 303 | w.Write([]byte(" " + cmd + "\t" + command.document + "\n")) 304 | } 305 | w.Flush() 306 | 307 | return "", nil 308 | } 309 | 310 | func actionQuit(s *Session, _ string) (string, error) { 311 | return "", ErrQuit 312 | } 313 | 314 | func actionContainerize(s *Session, _ string) (string, error) { 315 | 316 | // get the source code 317 | source, err := s.source(true) 318 | if err != nil { 319 | return "", err 320 | } 321 | 322 | // create tmp directory in GOPATH 323 | gopath := os.Getenv("GOPATH") 324 | os.Mkdir(gopath+"/src/tmpcontainerize", 0777) 325 | 326 | d := []byte(source) 327 | err = ioutil.WriteFile(gopath+"/src/tmpcontainerize/containerize.go", d, 0777) 328 | if err != nil { 329 | return "", err 330 | } 331 | 332 | cmd := exec.Command("go", "install", "tmpcontainerize") 333 | err = cmd.Run() 334 | if err != nil { 335 | panic(err) 336 | } 337 | 338 | // dockerize 339 | dockerfile := ` 340 | FROM scratch 341 | ADD tmpcontainerize /tmpcontainerize 342 | CMD ["/tmpcontainerize"] 343 | ` 344 | d = []byte(dockerfile) 345 | err = ioutil.WriteFile(gopath+"/bin/Dockerfile", d, 0777) 346 | 347 | out, err := exec.Command("uuidgen").Output() 348 | containerid := string(out) 349 | containerid = containerid[0 : len(containerid)-1] 350 | if err != nil { 351 | return "", err 352 | } 353 | 354 | fmt.Println("Dockerizing") 355 | cmd = exec.Command("docker", "build", "-t", containerid, gopath+"/bin/") 356 | err = cmd.Run() 357 | if err != nil { 358 | fmt.Println(err) 359 | panic(err) 360 | } 361 | 362 | fmt.Println("removing src") 363 | // now that we have the binary, remove the tmp src 364 | err = os.RemoveAll(gopath + "/src/tmpcontainerize/") 365 | if err != nil { 366 | return "", err 367 | } 368 | fmt.Println("removing docker image") 369 | err = os.Remove(gopath + "/bin/Dockerfile") 370 | if err != nil { 371 | return "", err 372 | } 373 | 374 | return "", nil 375 | } 376 | --------------------------------------------------------------------------------