seguims con los errores

master
DEV 3 years ago
parent 70814fe835
commit 0d0e220350

@ -139,6 +139,21 @@ func UnwrapCause(err error) error {
}
func UnwrapCauses (err error) []error {
if err == nil {
return nil
}
if al,is := err.(Causers); is {
return al.Causes()
}
var l ErrorList
e := err
for e!= nil {
l = append(l,e)
e = Unwrap(e)
}
return l
}
func UnwrapList(err error) ErrorList {

@ -32,7 +32,6 @@ type (
Cause () error
}
CauseFnc func () error
)

@ -0,0 +1,41 @@
// ------------------------------------------------------------------------
// Project active2
// Active Thing (activething.com) git.activething.com/go
//
// File name causer.go
// Created by DEV
// Modified 20/03/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------
package errs
type (
Causers interface {
Causes () []error
}
CausesFnc func () []error
)
func (f CausesFnc) Causes() []error {
return f() }

@ -95,23 +95,23 @@ func DefaultFormatter () *ErrTextFormatter {
}),
WithSectionFormat(HeadSection, func (sec *SectionFormat) {
sec.BuildBefore = func (b fmts.Builder) {
b.AddString("**********************************************************")
b.AddText("**********************************************************")
}
sec.BuildAfter = sec.BuildBefore
}),
WithSectionFormat(CauseSection, func (sec *SectionFormat) {
sec.BuildBefore = func (b fmts.Builder) {
b.AddString("- Prev Cause ---------------")
b.AddText("- Prev Cause ---------------")
}
}),
WithSectionFormat(TraceSection, func (sec *SectionFormat) {
sec.BuildBefore = func(b fmts.Builder) {
b.AddString("--------------------------------------------------------")
b.AddString(" Stack Trace Information ")
b.AddString("--------------------------------------------------------")
b.AddText("--------------------------------------------------------")
b.AddText(" Stack Trace Information ")
b.AddText("--------------------------------------------------------")
}
sec.BuildAfter = func (b fmts.Builder) {
b.AddString("--------------------------------------------------------")
b.AddText("--------------------------------------------------------")
}
*/
@ -145,6 +145,6 @@ func DefaultFrameBuilder (builder erfmt.Builder, frame stack.Frame, num int) {
if e == nil {
builder.AddString(c3.Sprintf(" %s\n", f))
} else {
//builder.AddString(c3.Sprintf(" error %s\n", e.Error()))
//builder.AddText(c3.Sprintf(" error %s\n", e.Error()))
}
}

@ -31,7 +31,7 @@ type (
Builder interface {
AddHead (code, errType string)
AddHead (errStr, errType string)
AddFieldString (name string, value string )
AddFieldInt (name string, value int )
@ -40,7 +40,7 @@ type (
AddFieldTime (name string, value time.Time)
AddFieldDate (name string, value time.Time)
AddString(str string)
AddText (str string)
}
)

@ -0,0 +1,44 @@
// ------------------------------------------------------------------------
// Project active2
// Active Thing (activething.com) git.activething.com/go
//
// File name builder_fallback.go
// Created by DEV
// Modified 13/04/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------
package err_fmt
import (
"fmt"
"reflect"
)
type (
BuilderErrorFallback func (err error) string
)
func MakeErrorFallback (message string) BuilderErrorFallback {
return func(err error) string {
return fmt.Sprintf(message,err,reflect.TypeOf(err).String())
}
}

@ -0,0 +1,71 @@
// ------------------------------------------------------------------------
// Project active2
// Active Thing (activething.com) git.activething.com/go
//
// File name active.go
// Created by DEV
// Modified 12/04/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------
package fmx
import (
"ansi"
"errs/err_fmt"
"errs/stack"
"fmt"
"strings"
)
const (
fbBuildError string = "Error building error format for type '%v'. Check formatter configuration or consider handling unsupported error types gracefully. Error: %s"
fbUnwrapError string = "Error building error from wrapped error. Encountered type '%v'. Consider handling this type explicitly or providing a generic fallback message. Error: %s"
fbCauseError string = "Error formatting cause error. Encountered type '%v'. Review formatter logic for handling cause errors or provide a generic fallback message. Error: %s"
)
func defaultFrameBuilder(builder err_fmt.Builder, frame stack.Frame, num int) {
if strings.Index(frame.Package,"runtime") != -1 {
return
}
var c1, c2, c3, c4 ansi.Code
/*
if builder.Options().ShowAnsi(){
c1 = c1.SetFgColor(ansi.ColorBlue).SetBgColor(ansi.ColorHWhite)
c2 = c2.SetFgColor(ansi.ColorMagenta)
c3 = c3.SetFgColor(ansi.ColorWhite)
c4 = c3.SetStyle(ansi.StyleBold).SetFgColor(ansi.ColorHWhite)
}
*/
nm := c4.Sprintf(" %d ",num)
ln := c1.Sprintf(fmt.Sprintf("%-60s",fmt.Sprintf(" %s.%s", frame.Package, frame.FuncName)))
builder.AddText(fmt.Sprint(nm,ln))
builder.AddText(c2.Sprintf(" %.90s:%d", frame.File, frame.LineNumber))
f, e := frame.SourceLine()
if e == nil {
builder.AddText(c3.Sprintf(" %s\n", f))
} else {
//builder.AddText(c3.Sprintf(" error %s\n", e.Error()))
}
}

@ -0,0 +1,51 @@
// ------------------------------------------------------------------------
// Project active2
// Active Thing (activething.com) git.activething.com/go
//
// File name field_format.go
// Created by DEV
// Modified 04/04/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------
package fmx
import (
"ansi"
"atypes/astrings"
)
type (
fieldFormat struct {
NameAnsi ansi.Code
ValueAnsi ansi.Code
NameTrans astrings.Transformers
ValueTrans astrings.Transformers
}
)
func (f fieldFormat) clone() fieldFormat {
return fieldFormat{
NameAnsi: f.NameAnsi,
ValueAnsi: f.ValueAnsi,
NameTrans: append(astrings.Transformers(nil),f.NameTrans...),
ValueTrans: append(astrings.Transformers(nil),f.ValueTrans...),
}
}

@ -23,23 +23,75 @@
package fmx
import (
"atypes/astrings"
"errs/err_fmt"
)
type (
TextErrorFormatter struct {}
TextFmt struct {
options err_fmt.BuilderOption
vLayouts layouts
sections sections
defField fieldFormat
fields map[string]*fieldFormat
stringTrans astrings.Transformers
fbOnError ,
fbOnUnwrap,
fbOnCause err_fmt.BuilderErrorFallback
frameBuilder err_fmt.FrameBuilder
}
TextFmtFnc func(f *TextFmt)
)
func (f *TextErrorFormatter) Format (err error) []byte {
func NewTextFmt (options ...TextFmtFnc) *TextFmt {
fm := &TextFmt{
options : err_fmt.BuilderOption(0).SetDefaults(),
vLayouts : *newLayouts(),
sections : sections{},
fbOnError : err_fmt.MakeErrorFallback(fbBuildError),
fbOnUnwrap: err_fmt.MakeErrorFallback(fbUnwrapError),
fbOnCause : err_fmt.MakeErrorFallback(fbUnwrapError),
frameBuilder: err_fmt.BuildFrameFnc(defaultFrameBuilder),
}
for _,o := range options {
o(fm)
}
return fm
}
func (f *TextFmt) Format (err error) []byte {
if err == nil {
return nil
}
st := &state{
f : f,
}
er :=
fe := st.writeError(err,f.options.ShowWrapped(),f.options.ShowCause(),f.options.ShowTrace(),0)
if fe == nil {
return st.b.Bytes()
}
st.reset()
if fe = st.writeError(fe,false,true,false,0); fe == nil{
return st.b.Bytes()
}
return []byte(f.fbOnError(err))
}

@ -0,0 +1,87 @@
// ------------------------------------------------------------------------
// Project active2
// Active Thing (activething.com) git.activething.com/go
//
// File name fmt_ops.go
// Created by DEV
// Modified 13/04/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------
package fmx
func WithLayout (name, layout string) TextFmtFnc {
return func(f *TextFmt) {
switch name {
case "time":
f.vLayouts.timeLayout = layout
case "date":
f.vLayouts.dateLayout = layout
case "int":
f.vLayouts.intLayout = layout
case "float":
f.vLayouts.floatLayout = layout
case "bool":
f.vLayouts.boolLayout = layout
}
}
}
/*
func WithShowOptions (option erfmt.BuilderOption,enabled bool) FmtTextFnc {
return func(f *ErrTextFormatter) {
if enabled {
f.options |= option
return
}
f.options &^=option
}
}
func WithSectionFormat(id int, config func (s *SectionFormat)) FmtTextFnc {
if id < DefaultSection && id > TraceSection {
return func(_ *ErrTextFormatter){}
}
return func(f *ErrTextFormatter) {
config(&f.secs[id])
}
}
func WithFieldFormat(field string, config func(format *FieldFormat)) FmtTextFnc {
return func(f *ErrTextFormatter) {
if field == "" || field == "*" {
config(&f.defFieldFormat)
return
}
if f.fieldsFormat == nil {
f.fieldsFormat = make(map[string]FieldFormat)
}
fm := FieldFormat{}
config(&fm)
if strings.Index(field,",") == -1 {
f.fieldsFormat[field]=fm
return
}
for _,fn := range strings.SplitAfter(field,",") {
f.fieldsFormat[fn]=fm
}
}
}
*/

@ -0,0 +1,55 @@
// ------------------------------------------------------------------------
// Project active2
// Active Thing (activething.com) git.activething.com/go
//
// File name layouts.go
// Created by DEV
// Modified 13/04/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------
package fmx
import (
"time"
)
type (
layouts struct {
sep string
indent string
timeLayout string
dateLayout string
intLayout string
floatLayout string
boolLayout string
}
)
func newLayouts () *layouts {
return &layouts{
indent : " ",
sep : " : ",
timeLayout : time.RFC822Z,
dateLayout : time.RFC822Z,
intLayout : "%d",
floatLayout : "%-10s: %.2f",
}
}

@ -2,7 +2,7 @@
// Project active2
// Active Thing (activething.com) git.activething.com/go
//
// File name section.go
// File name sectionFormat.go
// Created by DEV
// Modified 12/04/2024
//
@ -30,8 +30,8 @@ import (
type (
section struct {
code ansi.Code
sectionFormat struct {
ansi ansi.Code
before err_fmt.BuildFnc
after err_fmt.BuildFnc
@ -39,11 +39,11 @@ type (
)
func (s *section) doBefore (b err_fmt.Builder) {
func (s *sectionFormat) doBefore (b err_fmt.Builder) {
if s != nil && s.before != nil {
s.before.Build(b) } }
func (s *section) doAfter (b err_fmt.Builder) {
func (s *sectionFormat) doAfter (b err_fmt.Builder) {
if s != nil && s.after != nil {
s.after.Build(b) } }

@ -2,9 +2,9 @@
// Project active2
// Active Thing (activething.com) git.activething.com/go
//
// File name field.go
// File name sections.go
// Created by DEV
// Modified 12/04/2024
// Modified 13/04/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
@ -24,14 +24,14 @@
package fmx
type (
field struct {
n string
v string
f
sections struct {
err,
head,
fields,
cause,
trace sectionFormat
}
)

@ -24,39 +24,62 @@
package fmx
import (
"ansi"
"bytes"
"errors"
"errs/err_fmt"
"errs/stack"
"fmt"
"reflect"
)
const (
secHead uint8 = iota
secFields
secCause
)
type (
state struct {
f *TextErrorFormatter
f *TextFmt
b bytes.Buffer
secs []*section
flds []field
cses []error
trace stack.Trace
fDone bool // se ha añadido la seccion de fields
curSec uint8 // actual seccion del formato
ansi ansi.Code
}
)
func newState (f *TextErrorFormatter) *state {
return &state {
f : f,
}
}
func newState (f *TextFmt) *state {
return &state { f : f }}
func (s *state) format (err error, unwrapping bool) (fe error) {
func (s *state) reset () *state {
s.curSec = 0
s.ansi = 0
s.b.Reset()
return s
}
func (s *state) writeError(err error, addUnwrap, addCause, addTrace bool, level int) (fe error) {
d := false
defer func(st *state, dn *bool, er *error){
if !(*dn) {
if rc := recover(); fe != nil {
ec,is := rc.(error)
if !is {
ec = fmt.Errorf("%#v",rc)
}
*er = *err_fmt.NewErrBuilderFormat(ec,reflect.TypeOf(er),true)
}
}
}(s,&d,&fe)
if fe,is := err.(err_fmt.Buildable); is {
fe.Build(s)
@ -73,39 +96,165 @@ func (s *state) format (err error, unwrapping bool) (fe error) {
err_fmt.SetErrorTypeBuilder(rt,eb)
}
}
if unwrapping {
if addUnwrap {
return fe
}
s.writeUnwrap(err,level)
if addCause {
s.writeCause(err,level)
}
if addTrace {
s.writeTrace (err)
}
d = true
return nil
}
func (s *state) unwrapError (err error) {
func (s *state) writeUnwrap(err error, level int) {
uw := errors.Unwrap(err)
for uw != nil {
if ue := s.format(uw,true); ue != nil {
if ue := s.writeError(uw,true,false,false, level); ue != nil {
// llamamos al fallback del formateador
s.AddText(s.f.fbOnUnwrap(uw))
}
uw = errors.Unwrap(uw)
}
}
func (s *state) writeCause(err error, level int ) {
if s.fDone {
s.fDone = false
s.f.sections.fields.doAfter(s)
}
nx := err
dn := false
for nx != nil {
if cs, is := err.(interface{ Cause() error }); is {
if ce := cs.Cause(); ce != nil {
if s.curSec == 1 {
s.curSec = 2
s.f.sections.cause.doBefore(s)
s.setAnsi(s.f.sections.cause.ansi)
dn = true
}
if fe := s.writeError(ce, false, true, false, level+1); fe != nil {
// llamamos al fallback del formateador
s.AddText(s.f.fbOnError(ce))
}
}
return
}
var lc []error
if cs, is := err.(interface{ Causes() []error }); is {
lc = cs.Causes()
} else if me, ok := err.(interface{ Unwrap() []error }); ok {
lc = me.Unwrap()
}
if len(lc) > 0 {
if s.curSec == 1 {
s.curSec = 2
s.setAnsi(s.f.sections.cause.ansi)
s.f.sections.cause.doBefore(s)
dn = true
}
for _, e := range lc {
if fe := s.writeError(e, false, false, false, level); fe != nil {
s.AddText(fmt.Sprintf(fbCauseError, reflect.TypeOf(e), fe.Error()))
}
}
return
}
nx = errors.Unwrap(nx)
}
if dn {
s.f.sections.cause.doAfter(s)
}
}
func (s *state) writeTrace(err error) {
if s.fDone {
s.fDone = false
s.f.sections.fields.doAfter(s)
}
tc := stack.UnwrapTrace(err,true)
if tc == nil {
return
}
s.f.sections.trace.doBefore(s)
s.setAnsi(s.f.sections.trace.ansi)
for n,f := range tc.Frames() {
s.f.frameBuilder.BuildFrame(s,f,n)
}
defer s.f.sections.trace.doAfter(s)
}
func (s *state) writeField(name, value string) {
if !s.fDone {
s.fDone = true
s.setAnsi(s.f.sections.fields.ansi)
s.f.sections.fields.doBefore(s)
}
var cv, cn ansi.Code
n := s.f.defField.NameTrans.Apply(name)
v := s.f.defField.ValueTrans.Apply(value)
if s.f.options.ShowAnsi() {
cn = s.f.defField.NameAnsi
cv = s.f.defField.ValueAnsi
}
if ff,hs := s.f.fields[name]; hs {
n = ff.NameTrans.Apply (n)
v = ff.ValueTrans.Apply(v)
if s.f.options.ShowAnsi() {
cn = ff.NameAnsi
cv = ff.ValueAnsi
}
}
s.b.WriteString(s.f.vLayouts.indent)
s.b.WriteString(cn.Sprint(n))
s.b.WriteString(cn.Sprint(s.f.vLayouts.sep))
s.b.WriteString(cv.Sprint(v))
s.b.WriteByte('\n')
}
func (s *state) writeString (str string) {
str = s.f.stringTrans.Apply(str)
s.b.WriteString(s.ansi.Sprintf(str))
}
func (s *state) setAnsi (ansi ansi.Code) {
if s.f.options.ShowAnsi() {
s.ansi = ansi
}
}

@ -0,0 +1,91 @@
// ------------------------------------------------------------------------
// Project active2
// Active Thing (activething.com) git.activething.com/go
//
// File name state_builder.go
// Created by DEV
// Modified 12/04/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------
package fmx
import (
"errs/err_fmt"
"fmt"
"time"
)
func (s *state) AddText(str string) {}
func (s *state) AddHead(errStr, errType string) {
if s.curSec > 0 {
return
}
s.f.sections.head.doBefore(s)
s.curSec = 1
s.ansi = s.f.sections.head.ansi
s.writeField(err_fmt.FieldNameError,errStr)
s.writeField(err_fmt.FieldNameType ,errType)
s.f.sections.head.doAfter (s)
}
func (s *state) AddFieldString (name string, value string ) {
if s.curSec != 1 {
return
}
s.writeField(name,value)
}
func (s *state) AddFieldInt (name string, value int ) {
if s.curSec != 1 {
return
}
s.writeField(name,fmt.Sprintf(s.f.vLayouts.intLayout,value))
}
func (s *state) AddFieldFloat (name string, value float64 ) {
if s.curSec != 1 {
return
}
s.writeField(name,fmt.Sprintf(s.f.vLayouts.floatLayout,value))
}
func (s *state) AddFieldBool (name string, value bool ) {
if s.curSec != 1 {
return
}
s.writeField(name,fmt.Sprintf(s.f.vLayouts.boolLayout,value))
}
func (s *state) AddFieldTime (name string, value time.Time) {
if s.curSec != 1 {
return
}
s.writeField(name,value.Format(s.f.vLayouts.timeLayout))
}
func (s *state) AddFieldDate (name string, value time.Time) {
if s.curSec != 1 {
return
}
s.writeField(name,value.Format(s.f.vLayouts.dateLayout))
}

@ -126,7 +126,7 @@ func (s *state) checkField (name string) bool {
}
func (s *state) AddString(str string) {}
func (s *state) AddText(str string) {}
@ -175,6 +175,7 @@ func (s *state) format (err error, level int, isWrapped, addWrap, addCause, addT
// añadimos un field fmt-(nombre del tipo de error) con el code
// o mensaje de error
rt := reflect.TypeOf(ne).String()
s.AddText(s.f.)
s.addField(fmt.Sprintf(err_fmt.fmtFieldFormatError,rt),fmt.Sprintf(err_fmt.fmtErrorFormatUnwrap,rt))
}
}

@ -46,7 +46,10 @@ func (e ErrMulti) Error () string {
func (e ErrMulti) Unwrap() []error {
return e.ErrorList.Clean() }
return e.ErrorList }
func (e ErrMulti) Causes() []error {
return e.ErrorList }

Loading…
Cancel
Save

Powered by TurnKey Linux.