Upadte vendored dependencies

This commit is contained in:
Alexander Neumann
2017-10-22 10:07:36 +02:00
parent 315b7f282f
commit 8d37b723ca
380 changed files with 136539 additions and 78530 deletions
+5
View File
@@ -0,0 +1,5 @@
### Please give general description of the problem
### Please provide code snippets to reproduce the problem described above
### Do you have any suggestion to fix the problem?
+3
View File
@@ -0,0 +1,3 @@
### What problem should be fixed?
### Have you added test cases to catch the problem?
+1
View File
@@ -3,3 +3,4 @@ ini.sublime-project
ini.sublime-workspace
testdata/conf_reflect.ini
.idea
/.vscode
+1 -2
View File
@@ -1,12 +1,11 @@
sudo: false
language: go
go:
- 1.4.x
- 1.5.x
- 1.6.x
- 1.7.x
- 1.8.x
- master
- 1.9.x
script:
- go get golang.org/x/tools/cmd/cover
+1 -1
View File
@@ -176,7 +176,7 @@ recommend that a file or class name and description of purpose be included on
the same "printed page" as the copyright notice for easier identification within
third-party archives.
Copyright [yyyy] [name of copyright owner]
Copyright 2014 Unknwon
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
+23 -6
View File
@@ -101,7 +101,7 @@ skip-name-resolve
By default, this is considered as missing value. But if you know you're going to deal with those cases, you can assign advanced load options:
```go
cfg, err := LoadSources(LoadOptions{AllowBooleanKeys: true}, "my.cnf"))
cfg, err := ini.LoadSources(ini.LoadOptions{AllowBooleanKeys: true}, "my.cnf"))
```
The value of those keys are always `true`, and when you save to a file, it will keep in the same foramt as you read.
@@ -125,7 +125,7 @@ If you want to save a value with `#` or `;`, please quote them with ``` ` ``` or
Alternatively, you can use following `LoadOptions` to completely ignore inline comments:
```go
cfg, err := LoadSources(LoadOptions{IgnoreInlineComment: true}, "app.ini"))
cfg, err := ini.LoadSources(ini.LoadOptions{IgnoreInlineComment: true}, "app.ini"))
```
### Working with sections
@@ -329,6 +329,20 @@ foo = "some value" // foo: some value
bar = 'some value' // bar: some value
```
Sometimes you downloaded file from [Crowdin](https://crowdin.com/) has values like the following (value is surrounded by double quotes and quotes in the value are escaped):
```ini
create_repo="created repository <a href=\"%s\">%s</a>"
```
How do you transform this to regular format automatically?
```go
cfg, err := ini.LoadSources(ini.LoadOptions{UnescapeValueDoubleQuotes: true}, "en-US.ini"))
cfg.Section("<name of your section>").Key("create_repo").String()
// You got: created repository <a href="%s">%s</a>
```
That's all? Hmm, no.
#### Helper methods of working with values
@@ -480,7 +494,7 @@ cfg.Section("package.sub").ParentKeys() // ["CLONE_URL"]
Sometimes, you have sections that do not contain key-value pairs but raw content, to handle such case, you can use `LoadOptions.UnparsableSections`:
```go
cfg, err := LoadSources(LoadOptions{UnparseableSections: []string{"COMMENTS"}}, `[COMMENTS]
cfg, err := ini.LoadSources(ini.LoadOptions{UnparseableSections: []string{"COMMENTS"}}, `[COMMENTS]
<1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>`))
body := cfg.Section("COMMENTS").Body()
@@ -573,7 +587,7 @@ Why not?
```go
type Embeded struct {
Dates []time.Time `delim:"|"`
Dates []time.Time `delim:"|" comment:"Time data"`
Places []string `ini:"places,omitempty"`
None []int `ini:",omitempty"`
}
@@ -581,10 +595,10 @@ type Embeded struct {
type Author struct {
Name string `ini:"NAME"`
Male bool
Age int
Age int `comment:"Author's age"`
GPA float64
NeverMind string `ini:"-"`
*Embeded
*Embeded `comment:"Embeded section"`
}
func main() {
@@ -605,10 +619,13 @@ So, what do I get?
```ini
NAME = Unknwon
Male = true
; Author's age
Age = 21
GPA = 2.8
; Embeded section
[Embeded]
; Time data
Dates = 2015-08-07T22:14:22+08:00|2015-08-07T22:14:22+08:00
places = HangZhou,Boston
```
+23 -6
View File
@@ -94,7 +94,7 @@ skip-name-resolve
默认情况下这被认为是缺失值而无法完成解析,但可以通过高级的加载选项对它们进行处理:
```go
cfg, err := LoadSources(LoadOptions{AllowBooleanKeys: true}, "my.cnf"))
cfg, err := ini.LoadSources(ini.LoadOptions{AllowBooleanKeys: true}, "my.cnf"))
```
这些键的值永远为 `true`,且在保存到文件时也只会输出键名。
@@ -118,7 +118,7 @@ key, err := sec.NewBooleanKey("skip-host-cache")
除此之外,您还可以通过 `LoadOptions` 完全忽略行内注释:
```go
cfg, err := LoadSources(LoadOptions{IgnoreInlineComment: true}, "app.ini"))
cfg, err := ini.LoadSources(ini.LoadOptions{IgnoreInlineComment: true}, "app.ini"))
```
### 操作分区(Section)
@@ -322,6 +322,20 @@ foo = "some value" // foo: some value
bar = 'some value' // bar: some value
```
有时您会获得像从 [Crowdin](https://crowdin.com/) 网站下载的文件那样具有特殊格式的值(值使用双引号括起来,内部的双引号被转义):
```ini
create_repo="创建了仓库 <a href=\"%s\">%s</a>"
```
那么,怎么自动地将这类值进行处理呢?
```go
cfg, err := ini.LoadSources(ini.LoadOptions{UnescapeValueDoubleQuotes: true}, "en-US.ini"))
cfg.Section("<name of your section>").Key("create_repo").String()
// You got: 创建了仓库 <a href="%s">%s</a>
```
这就是全部了?哈哈,当然不是。
#### 操作键值的辅助方法
@@ -473,7 +487,7 @@ cfg.Section("package.sub").ParentKeys() // ["CLONE_URL"]
如果遇到一些比较特殊的分区,它们不包含常见的键值对,而是没有固定格式的纯文本,则可以使用 `LoadOptions.UnparsableSections` 进行处理:
```go
cfg, err := LoadSources(LoadOptions{UnparseableSections: []string{"COMMENTS"}}, `[COMMENTS]
cfg, err := LoadSources(ini.LoadOptions{UnparseableSections: []string{"COMMENTS"}}, `[COMMENTS]
<1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>`))
body := cfg.Section("COMMENTS").Body()
@@ -564,7 +578,7 @@ p := &Person{
```go
type Embeded struct {
Dates []time.Time `delim:"|"`
Dates []time.Time `delim:"|" comment:"Time data"`
Places []string `ini:"places,omitempty"`
None []int `ini:",omitempty"`
}
@@ -572,10 +586,10 @@ type Embeded struct {
type Author struct {
Name string `ini:"NAME"`
Male bool
Age int
Age int `comment:"Author's age"`
GPA float64
NeverMind string `ini:"-"`
*Embeded
*Embeded `comment:"Embeded section"`
}
func main() {
@@ -596,10 +610,13 @@ func main() {
```ini
NAME = Unknwon
Male = true
; Author's age
Age = 21
GPA = 2.8
; Embeded section
[Embeded]
; Time data
Dates = 2015-08-07T22:14:22+08:00|2015-08-07T22:14:22+08:00
places = HangZhou,Boston
```
+7 -1
View File
@@ -35,7 +35,7 @@ const (
// Maximum allowed depth when recursively substituing variable names.
_DEPTH_VALUES = 99
_VERSION = "1.28.2"
_VERSION = "1.30.0"
)
// Version returns current package version literal.
@@ -181,6 +181,8 @@ type LoadOptions struct {
AllowBooleanKeys bool
// AllowShadows indicates whether to keep track of keys with same name under same section.
AllowShadows bool
// UnescapeValueDoubleQuotes indicates whether to unescape double quotes inside value to regular format when value is surrounded by double quotes, e.g. key="a \"value\"" => key=a "value"
UnescapeValueDoubleQuotes bool
// Some INI formats allow group blocks that store a block of raw content that doesn't otherwise
// conform to key/value pairs. Specify the names of those blocks here.
UnparseableSections []string
@@ -409,6 +411,8 @@ func (f *File) writeToBuffer(indent string) (*bytes.Buffer, error) {
if len(sec.Comment) > 0 {
if sec.Comment[0] != '#' && sec.Comment[0] != ';' {
sec.Comment = "; " + sec.Comment
} else {
sec.Comment = sec.Comment[:1] + " " + strings.TrimSpace(sec.Comment[1:])
}
if _, err := buf.WriteString(sec.Comment + LineBreak); err != nil {
return nil, err
@@ -463,6 +467,8 @@ func (f *File) writeToBuffer(indent string) (*bytes.Buffer, error) {
}
if key.Comment[0] != '#' && key.Comment[0] != ';' {
key.Comment = "; " + key.Comment
} else {
key.Comment = key.Comment[:1] + " " + strings.TrimSpace(key.Comment[1:])
}
if _, err := buf.WriteString(key.Comment + LineBreak); err != nil {
return nil, err
+28 -1
View File
@@ -87,6 +87,14 @@ key = "value"
key2 = "value2" ; This is a comment for key2
key3 = "one", "two", "three"
[string escapes]
key1 = value1, value2, value3
key2 = value1\, value2
key3 = val\ue1, value2
key4 = value1\\, value\\\\2
key5 = value1\,, value2
key6 = aaa bbb\ and\ space ccc
[advance]
value with quotes = "some value"
value quote2 again = 'some value'
@@ -241,7 +249,7 @@ key5`))
// there is always a trailing \n at the end of the section
So(buf.String(), ShouldEqual, `key1 = hello
key2
#key3
# key3
key4
key5
`)
@@ -294,6 +302,17 @@ func Test_LooseLoad(t *testing.T) {
}
func Test_LoadOptions_UnescapeValueDoubleQuotes(t *testing.T) {
Convey("Load with option UnescapeValueDoubleQuotes enabled", t, func() {
cfg, err := LoadSources(LoadOptions{UnescapeValueDoubleQuotes: true},
[]byte(`create_repo="创建了仓库 <a href=\"%s\">%s</a>"`))
So(err, ShouldBeNil)
So(cfg, ShouldNotBeNil)
So(cfg.Section("").Key("create_repo").String(), ShouldEqual, `创建了仓库 <a href="%s">%s</a>`)
})
}
func Test_File_Append(t *testing.T) {
Convey("Append data sources", t, func() {
cfg, err := Load([]byte(""))
@@ -397,6 +416,14 @@ Good man.
key2 = value2
key3 = "one", "two", "three"
[string escapes]
key1 = value1, value2, value3
key2 = value1\, value2
key3 = val\ue1, value2
key4 = value1\\, value\\\\2
key5 = value1\,, value2
key6 = aaa bbb\ and\ space ccc
[advance]
value with quotes = some value
value quote2 again = some value
+33 -4
View File
@@ -15,6 +15,7 @@
package ini
import (
"bytes"
"errors"
"fmt"
"strconv"
@@ -444,11 +445,39 @@ func (k *Key) Strings(delim string) []string {
return []string{}
}
vals := strings.Split(str, delim)
for i := range vals {
// vals[i] = k.transformValue(strings.TrimSpace(vals[i]))
vals[i] = strings.TrimSpace(vals[i])
runes := []rune(str)
vals := make([]string, 0, 2)
var buf bytes.Buffer
escape := false
idx := 0
for {
if escape {
escape = false
if runes[idx] != '\\' && !strings.HasPrefix(string(runes[idx:]), delim) {
buf.WriteRune('\\')
}
buf.WriteRune(runes[idx])
} else {
if runes[idx] == '\\' {
escape = true
} else if strings.HasPrefix(string(runes[idx:]), delim) {
idx += len(delim) - 1
vals = append(vals, strings.TrimSpace(buf.String()))
buf.Reset()
} else {
buf.WriteRune(runes[idx])
}
}
idx += 1
if idx == len(runes) {
break
}
}
if buf.Len() > 0 {
vals = append(vals, strings.TrimSpace(buf.String()))
}
return vals
}
+11 -1
View File
@@ -73,7 +73,7 @@ func Test_Key(t *testing.T) {
Convey("Get sections", func() {
sections := cfg.Sections()
for i, name := range []string{DEFAULT_SECTION, "author", "package", "package.sub", "features", "types", "array", "note", "comments", "advance"} {
for i, name := range []string{DEFAULT_SECTION, "author", "package", "package.sub", "features", "types", "array", "note", "comments", "string escapes", "advance"} {
So(sections[i].Name(), ShouldEqual, name)
}
})
@@ -243,6 +243,16 @@ func Test_Key(t *testing.T) {
timesEqual(vals6, t, t, t)
})
Convey("Test string slice escapes", func() {
sec := cfg.Section("string escapes")
So(sec.Key("key1").Strings(","), ShouldResemble, []string{"value1", "value2", "value3"})
So(sec.Key("key2").Strings(","), ShouldResemble, []string{"value1, value2"})
So(sec.Key("key3").Strings(","), ShouldResemble, []string{`val\ue1`, "value2"})
So(sec.Key("key4").Strings(","), ShouldResemble, []string{`value1\`, `value\\2`})
So(sec.Key("key5").Strings(",,"), ShouldResemble, []string{"value1,, value2"})
So(sec.Key("key6").Strings(" "), ShouldResemble, []string{"aaa", "bbb and space", "ccc"})
})
Convey("Get valid values into slice", func() {
sec := cfg.Section("array")
vals1 := sec.Key("FLOAT64S").ValidFloat64s(",")
+15 -4
View File
@@ -193,7 +193,7 @@ func hasSurroundedQuote(in string, quote byte) bool {
strings.IndexByte(in[1:], quote) == len(in)-2
}
func (p *parser) readValue(in []byte, ignoreContinuation, ignoreInlineComment bool) (string, error) {
func (p *parser) readValue(in []byte, ignoreContinuation, ignoreInlineComment, unescapeValueDoubleQuotes bool) (string, error) {
line := strings.TrimLeftFunc(string(in), unicode.IsSpace)
if len(line) == 0 {
return "", nil
@@ -204,6 +204,8 @@ func (p *parser) readValue(in []byte, ignoreContinuation, ignoreInlineComment bo
valQuote = `"""`
} else if line[0] == '`' {
valQuote = "`"
} else if unescapeValueDoubleQuotes && line[0] == '"' {
valQuote = `"`
}
if len(valQuote) > 0 {
@@ -214,6 +216,9 @@ func (p *parser) readValue(in []byte, ignoreContinuation, ignoreInlineComment bo
return p.readMultilines(line, line[startIdx:], valQuote)
}
if unescapeValueDoubleQuotes && valQuote == `"` {
return strings.Replace(line[startIdx:pos+startIdx], `\"`, `"`, -1), nil
}
return line[startIdx : pos+startIdx], nil
}
@@ -234,7 +239,7 @@ func (p *parser) readValue(in []byte, ignoreContinuation, ignoreInlineComment bo
}
}
// Trim single quotes
// Trim single and double quotes
if hasSurroundedQuote(line, '\'') ||
hasSurroundedQuote(line, '"') {
line = line[1 : len(line)-1]
@@ -321,7 +326,10 @@ func (f *File) parse(reader io.Reader) (err error) {
if err != nil {
// Treat as boolean key when desired, and whole line is key name.
if IsErrDelimiterNotFound(err) && f.options.AllowBooleanKeys {
kname, err := p.readValue(line, f.options.IgnoreContinuation, f.options.IgnoreInlineComment)
kname, err := p.readValue(line,
f.options.IgnoreContinuation,
f.options.IgnoreInlineComment,
f.options.UnescapeValueDoubleQuotes)
if err != nil {
return err
}
@@ -344,7 +352,10 @@ func (f *File) parse(reader io.Reader) (err error) {
p.count++
}
value, err := p.readValue(line[offset:], f.options.IgnoreContinuation, f.options.IgnoreInlineComment)
value, err := p.readValue(line[offset:],
f.options.IgnoreContinuation,
f.options.IgnoreInlineComment,
f.options.UnescapeValueDoubleQuotes)
if err != nil {
return err
}
+3 -3
View File
@@ -28,7 +28,7 @@ func Test_Section(t *testing.T) {
So(cfg, ShouldNotBeNil)
Convey("Get section strings", func() {
So(strings.Join(cfg.SectionStrings(), ","), ShouldEqual, "DEFAULT,author,package,package.sub,features,types,array,note,comments,advance")
So(strings.Join(cfg.SectionStrings(), ","), ShouldEqual, "DEFAULT,author,package,package.sub,features,types,array,note,comments,string escapes,advance")
})
Convey("Delete a section", func() {
@@ -50,7 +50,7 @@ func Test_SectionRaw(t *testing.T) {
Convey("Test section raw string", t, func() {
cfg, err := LoadSources(
LoadOptions{
Insensitive: true,
Insensitive: true,
UnparseableSections: []string{"core_lesson", "comments"},
},
"testdata/aicc.ini")
@@ -72,4 +72,4 @@ func Test_SectionRaw(t *testing.T) {
111111111111111111100000000000111000000000 – end my lesson state data`)
})
})
}
}
+13 -1
View File
@@ -113,7 +113,7 @@ func setSliceWithProperType(key *Key, field reflect.Value, delim string, allowSh
default:
return fmt.Errorf("unsupported type '[]%s'", sliceOf)
}
if isStrict {
if err != nil && isStrict {
return err
}
@@ -450,6 +450,12 @@ func (s *Section) reflectFrom(val reflect.Value) error {
// Note: fieldName can never be empty here, ignore error.
sec, _ = s.f.NewSection(fieldName)
}
// Add comment from comment tag
if len(sec.Comment) == 0 {
sec.Comment = tpField.Tag.Get("comment")
}
if err = sec.reflectFrom(field); err != nil {
return fmt.Errorf("error reflecting field (%s): %v", fieldName, err)
}
@@ -461,6 +467,12 @@ func (s *Section) reflectFrom(val reflect.Value) error {
if err != nil {
key, _ = s.NewKey(fieldName, "")
}
// Add comment from comment tag
if len(key.Comment) == 0 {
key.Comment = tpField.Tag.Get("comment")
}
if err = reflectWithProperType(tpField.Type, key, field, parseDelim(tpField.Tag.Get("delim"))); err != nil {
return fmt.Errorf("error reflecting field (%s): %v", fieldName, err)
}
+20 -3
View File
@@ -244,9 +244,23 @@ age=a30`))
So(cfg.Section("").StrictMapTo(s), ShouldNotBeNil)
})
Convey("Map slice in strict mode", t, func() {
cfg, err := Load([]byte(`
names=alice, bruce`))
So(err, ShouldBeNil)
type Strict struct {
Names []string `ini:"names"`
}
s := new(Strict)
So(cfg.Section("").StrictMapTo(s), ShouldBeNil)
So(fmt.Sprint(s.Names), ShouldEqual, "[alice bruce]")
})
Convey("Reflect from struct", t, func() {
type Embeded struct {
Dates []time.Time `delim:"|"`
Dates []time.Time `delim:"|" comment:"Time data"`
Places []string
Years []int
Numbers []int64
@@ -258,12 +272,12 @@ age=a30`))
type Author struct {
Name string `ini:"NAME"`
Male bool
Age int
Age int `comment:"Author's age"`
Height uint
GPA float64
Date time.Time
NeverMind string `ini:"-"`
*Embeded `ini:"infos"`
*Embeded `ini:"infos" comment:"Embeded section"`
}
t, err := time.Parse(time.RFC3339, "1993-10-07T20:17:05Z")
@@ -287,12 +301,15 @@ age=a30`))
So(err, ShouldBeNil)
So(buf.String(), ShouldEqual, `NAME = Unknwon
Male = true
; Author's age
Age = 21
Height = 100
GPA = 2.8
Date = 1993-10-07T20:17:05Z
; Embeded section
[infos]
; Time data
Dates = 1993-10-07T20:17:05Z|1993-10-07T20:17:05Z
Places = HangZhou,Boston
Years = 1993,1994