-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 1dbaf51
Showing
9 changed files
with
390 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
dist: xenial | ||
language: go | ||
|
||
# Force-enable Go modules. Also force go to use the code in vendor/ | ||
# These will both be unnecessary when Go 1.13 lands. | ||
env: | ||
global: | ||
- GO111MODULE=on | ||
|
||
go: | ||
- "1.12.x" | ||
|
||
git: | ||
depth: 1 | ||
|
||
# Skip the install step. Don't `go get` dependencies. Only build with the code | ||
# in vendor/ | ||
install: true | ||
|
||
# Anything in before_script that returns a nonzero exit code will flunk the | ||
# build and immediately stop. It's sorta like having set -e enabled in bash. | ||
# Make sure golangci-lint is vendored. | ||
before_script: | ||
- go install github.com/golangci/golangci-lint/cmd/golangci-lint | ||
|
||
script: | ||
- golangci-lint run # run a bunch of code checkers/linters in parallel | ||
- go test -race -coverpkg ./... -coverprofile coverage.txt ./... | ||
|
||
after_success: | ||
- bash <(curl -s https://codecov.io/bash) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
BSD 2-Clause License | ||
|
||
Copyright (c) 2019, James Bowes | ||
All rights reserved. | ||
|
||
Redistribution and use in source and binary forms, with or without | ||
modification, are permitted provided that the following conditions are met: | ||
|
||
1. Redistributions of source code must retain the above copyright notice, this | ||
list of conditions and the following disclaimer. | ||
|
||
2. Redistributions in binary form must reproduce the above copyright notice, | ||
this list of conditions and the following disclaimer in the documentation | ||
and/or other materials provided with the distribution. | ||
|
||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | ||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | ||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
<!-- | ||
Attractive html formatting for rendering in github. sorry text editor | ||
readers! Besides the header and section links, everything should be clean and | ||
readable. | ||
--> | ||
<h1 align="center">cling</h1> | ||
<p align="center"><i>Clear and obvious error wrapping for <a href="https://golang.org">Go</a> errors</i></p> | ||
|
||
<div align="center"> | ||
<a href="https://godoc.org/github.com/jbowes/cling"><img src="https://godoc.org/github.com/jbowes/cling?status.svg" alt="GoDoc"></a> | ||
<img alt="Alpha Quality" src="https://img.shields.io/badge/status-ALPHA-orange.svg" > | ||
<a href="https://travis-ci.org/jbowes/cling"><img alt="Build Status" src="https://travis-ci.org/jbowes/cling.svg?branch=master"></a> | ||
<a href="https://github.com/jbowes/cling/releases/latest"><img alt="GitHub release" src="https://img.shields.io/github/release/jbowes/cling.svg"></a> | ||
<a href="./LICENSE"><img alt="BSD license" src="https://img.shields.io/badge/license-BSD-blue.svg"></a> | ||
<a href="https://codecov.io/gh/jbowes/cling"><img alt="codecov" src="https://img.shields.io/codecov/c/github/jbowes/cling.svg"></a> | ||
<a href="https://goreportcard.com/report/github.com/jbowes/cling"><img alt="Go Report Card" src="https://goreportcard.com/badge/github.com/jbowes/cling"></a> | ||
</div><br /><br /> | ||
|
||
|
||
## Introduction | ||
Introduction | [Examples] | [Contributing] <br /><br /> | ||
|
||
🚧 ___Disclaimer___: _`cling` is alpha quality software. The API may change | ||
without warning between revisions._ 🚧 | ||
|
||
`cling` provides a clear and obvious error wrapping API for the new [Go] 2/1.13+ | ||
[errors](https://godoc.org/golang.org/x/xerrors) package. If you prefer a | ||
specific function over a [formatting directive](https://godoc.org/golang.org/x/xerrors#Errorf), | ||
and an API that returns a nil error when the error to wrap is nil, then `cling` | ||
is for you. | ||
|
||
|
||
## Examples | ||
[Introduction] | Examples | [Contributing] <br /><br /> | ||
|
||
For complete examples and usage, see the [GoDoc documentation](https://godoc.org/github.com/jbowes/cling). | ||
|
||
_Wrapping an error_ | ||
```go | ||
err := errors.New("an error") | ||
wrapped := cling.Wrap(err, "wrapped") | ||
|
||
// Wrapped errors can be programatically inspected | ||
fmt.Print(xerrors.Is(wrapped, err)) // true | ||
``` | ||
|
||
_Sealing an error_ | ||
```go | ||
err := errors.New("an error") | ||
sealed := cling.Wrap(err, "sealed") | ||
|
||
// Sealed errors cannot be programatically inspected | ||
fmt.Print(xerrors.Is(sealed, err)) // false | ||
``` | ||
|
||
Both `Wrap` and `Seal` provide format specifier versions(`Wrapf`, `Sealf`), | ||
as well. | ||
|
||
### Building APIs on `cling` | ||
|
||
`cling/skip` implements the `cling` API with an additional `skip` argument, | ||
allowing creation of APIs on top of `cling` that will no report themselves in | ||
error caller frames. | ||
|
||
|
||
## Contributing | ||
[Introduction] | [Examples] | [Usage] | Contributing <br /><br /> | ||
|
||
I would love your help! | ||
|
||
`cling` is still a work in progress. You can help by: | ||
|
||
- Trying `oag` against different [OpenAPI] documents, and [reporting bugs][bug] | ||
when the generated code is broken, or [suggesting improvements][enhancement] | ||
to the generated code. | ||
- Opening a pull request to resolve an [open issue][issues]. | ||
- Adding a feature or enhancement of your own! If it might be big, please | ||
[open an issue][enhancement] first so we can discuss it. | ||
- Improving this `README` or adding other documentation to `cling`. | ||
- Letting [me] know if you're using `cling`. | ||
|
||
|
||
<!-- Section link definitions --> | ||
[introduction]: #introduction | ||
[examples]: #examples | ||
[usage]: #usage | ||
[contributing]: #contributing | ||
|
||
<!-- Other links --> | ||
[go]: https://golang.org | ||
|
||
[issues]: ./issues | ||
[bug]: ./issues/new?labels=bug | ||
[enhancement]: ./issues/new?labels=enhancement | ||
|
||
[me]: https://twitter.com/jrbowes |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package cling // import "github.com/jbowes/cling" | ||
|
||
import "github.com/jbowes/cling/skip" | ||
|
||
// Wrap returns an error wrapping err with the supplied message, and a frame | ||
// from the caller's stack. The argument skip is the number of frames to skip | ||
// over. Caller(0) returns the frame for the caller of Wrap. If err is nil, Wrap | ||
// returns nil. | ||
// | ||
// The error returned implments the Unwrap method, for programatically | ||
// extracting the error chain. | ||
// | ||
// This func is intended to be used for implementing APIs on top of cling. | ||
func Wrap(err error, message string) error { return skip.Wrap(err, 1, message) } | ||
|
||
// Wrapf returns an error wrapping err with the supplied format specifier, and a | ||
// frame from the caller's stack. The argument skip is the number of frames to | ||
// skip over. Caller(0) returns the frame for the caller of Wrap. If err is nil, | ||
// Wrapf returns nil. | ||
// | ||
// The error returned implments the Unwrap method, for programatically | ||
// extracting the error chain. | ||
func Wrapf(err error, format string, a ...interface{}) error { return skip.Wrapf(err, 1, format, a...) } | ||
|
||
// Seal returns an error wrapping err with the supplied message, and a frame | ||
// from the caller's stack. The argument skip is the number of frames to skip | ||
// over. Caller(0) returns the frame for the caller of Wrap. If err is nil, Wrap | ||
// returns nil. | ||
// | ||
// The error returned does not implement Unwrap; the error chain is available | ||
// only for printing. | ||
func Seal(err error, message string) error { return skip.Seal(err, 1, message) } | ||
|
||
// Sealf returns an error wrapping err with the supplied format specifier, and a | ||
// frame from the caller's stack. The argument skip is the number of frames to | ||
// skip over. Caller(0) returns the frame for the caller of Wrap. If err is nil, | ||
// Wrap returns nil. | ||
// | ||
// The error returned does not implement Unwrap; the error chain is available | ||
// only for printing. | ||
func Sealf(err error, format string, a ...interface{}) error { return skip.Sealf(err, 1, format, a...) } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
/* | ||
Package cling provides a clear and obvious error wrapping API for Go 2/1.13+ | ||
error values. | ||
*/ | ||
package cling |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package cling_test | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
|
||
"golang.org/x/xerrors" | ||
|
||
"github.com/jbowes/cling" | ||
) | ||
|
||
func Example() { | ||
// All funcs in this package print error chains | ||
err := errors.New("an error") | ||
wrapped := cling.Wrap(err, "wrapped") | ||
rewrapped := cling.Wrap(wrapped, "re-wrapped") | ||
fmt.Printf("%v", rewrapped) // or use %+v to print the stack frames | ||
// Output: re-wrapped: wrapped: an error | ||
} | ||
|
||
func Example_nil() { | ||
// All funcs in this package return nil when passed a nil error. | ||
err := error(nil) | ||
wrapped := cling.Wrap(err, "wrapped") | ||
fmt.Print(wrapped) | ||
// Output: <nil> | ||
} | ||
|
||
func ExampleWrap() { | ||
err := errors.New("an error") | ||
wrapped := cling.Wrap(err, "wrapped") | ||
fmt.Print(wrapped) | ||
// Output: wrapped: an error | ||
} | ||
|
||
func ExampleWrap_is() { | ||
err := errors.New("an error") | ||
wrapped := cling.Wrap(err, "wrapped") | ||
|
||
// Wrapped errors can be programatically inspected | ||
fmt.Print(xerrors.Is(wrapped, err)) | ||
// Output: true | ||
} | ||
|
||
func ExampleWrapf() { | ||
err := errors.New("an error") | ||
wrapped := cling.Wrapf(err, "wrapped, especially for %s", "you") | ||
fmt.Print(wrapped) | ||
// Output: wrapped, especially for you: an error | ||
} | ||
|
||
func ExampleSeal() { | ||
err := errors.New("an error") | ||
sealed := cling.Seal(err, "sealed") | ||
fmt.Print(sealed) | ||
// Output: sealed: an error | ||
} | ||
|
||
func ExampleSeal_is() { | ||
err := errors.New("an error") | ||
sealed := cling.Seal(err, "sealed") | ||
|
||
// Sealed errors are opaque for programmatic inspection | ||
fmt.Print(xerrors.Is(sealed, err)) | ||
// Output: false | ||
} | ||
|
||
func ExampleSealf() { | ||
err := errors.New("an error") | ||
sealed := cling.Sealf(err, "sealed, especially for %s", "you") | ||
fmt.Print(sealed) | ||
// Output: sealed, especially for you: an error | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
module github.com/jbowes/cling | ||
|
||
go 1.12 | ||
|
||
require golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522 h1:bhOzK9QyoD0ogCnFro1m2mz41+Ib0oOhfJnBp5MR4K4= | ||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
package skip | ||
|
||
import ( | ||
"fmt" | ||
|
||
"golang.org/x/xerrors" | ||
) | ||
|
||
// Wrap returns an error wrapping err with the supplied message, and a frame | ||
// from the caller's stack. The argument skip is the number of frames to skip | ||
// over. Caller(0) returns the frame for the caller of Wrap. If err is nil, Wrap | ||
// returns nil. | ||
// | ||
// The error returned implments the Unwrap method, for programatically | ||
// extracting the error chain. | ||
// | ||
// This func is intended to be used for implementing APIs on top of cling. | ||
func Wrap(err error, skip uint, message string) error { | ||
if err == nil { | ||
return nil | ||
} | ||
|
||
return &wrapError{sealError{ | ||
msg: message, | ||
err: err, | ||
frame: xerrors.Caller(int(skip + 1)), | ||
}} | ||
} | ||
|
||
// Wrapf returns an error wrapping err with the supplied format specifier, and a | ||
// frame from the caller's stack. The argument skip is the number of frames to | ||
// skip over. Caller(0) returns the frame for the caller of Wrap. If err is nil, | ||
// Wrapf returns nil. | ||
// | ||
// The error returned implments the Unwrap method, for programatically | ||
// extracting the error chain. | ||
// | ||
// This func is intended to be used for implementing APIs on top of cling. | ||
func Wrapf(err error, skip uint, format string, a ...interface{}) error { | ||
if err == nil { | ||
return nil | ||
} | ||
|
||
return &wrapError{sealError{ | ||
msg: fmt.Sprintf(format, a...), | ||
err: err, | ||
frame: xerrors.Caller(int(skip + 1)), | ||
}} | ||
} | ||
|
||
// Seal returns an error wrapping err with the supplied message, and a frame | ||
// from the caller's stack. The argument skip is the number of frames to skip | ||
// over. Caller(0) returns the frame for the caller of Wrap. If err is nil, Wrap | ||
// returns nil. | ||
// | ||
// The error returned does not implement Unwrap; the error chain is available | ||
// only for printing. | ||
// | ||
// This func is intended to be used for implementing APIs on top of cling. | ||
func Seal(err error, skip uint, message string) error { | ||
if err == nil { | ||
return nil | ||
} | ||
|
||
return &sealError{ | ||
msg: message, | ||
err: err, | ||
frame: xerrors.Caller(int(skip + 1)), | ||
} | ||
} | ||
|
||
// Sealf returns an error wrapping err with the supplied format specifier, and a | ||
// frame from the caller's stack. The argument skip is the number of frames to | ||
// skip over. Caller(0) returns the frame for the caller of Wrap. If err is nil, | ||
// Wrap returns nil. | ||
// | ||
// The error returned does not implement Unwrap; the error chain is available | ||
// only for printing. | ||
// | ||
// This func is intended to be used for implementing APIs on top of cling. | ||
func Sealf(err error, skip uint, format string, a ...interface{}) error { | ||
if err == nil { | ||
return nil | ||
} | ||
|
||
return &sealError{ | ||
msg: fmt.Sprintf(format, a...), | ||
err: err, | ||
frame: xerrors.Caller(int(skip + 1)), | ||
} | ||
} | ||
|
||
type sealError struct { | ||
msg string | ||
err error | ||
frame xerrors.Frame | ||
} | ||
|
||
func (e *sealError) Error() string { return fmt.Sprint(e) } | ||
func (e *sealError) Format(s fmt.State, v rune) { xerrors.FormatError(e, s, v) } | ||
|
||
func (e *sealError) FormatError(p xerrors.Printer) (next error) { | ||
p.Print(e.msg) | ||
e.frame.Format(p) | ||
return e.err | ||
} | ||
|
||
type wrapError struct { | ||
sealError | ||
} | ||
|
||
func (e *wrapError) Unwrap() error { return e.err } |