Update dependencies to K8s 1.8

This commit is contained in:
Nick Sardo 2017-09-29 10:12:14 -07:00
parent ba6c89672d
commit 6a59f4c9a2
1114 changed files with 160955 additions and 262845 deletions

View file

@ -1,4 +1,4 @@
// This file was generated by go generate; DO NOT EDIT
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
package language

View file

@ -678,6 +678,8 @@ func (b *builder) parseIndices() {
b.locale.parse(meta.DefaultContent.Locales)
}
// TODO: region inclusion data will probably not be use used in future matchers.
func (b *builder) computeRegionGroups() {
b.groups = make(map[int]index)
@ -686,6 +688,11 @@ func (b *builder) computeRegionGroups() {
b.groups[i] = index(len(b.groups))
}
for _, g := range b.supp.TerritoryContainment.Group {
// Skip UN and EURO zone as they are flattening the containment
// relationship.
if g.Type == "EZ" || g.Type == "UN" {
continue
}
group := b.region.index(g.Type)
if _, ok := b.groups[group]; !ok {
b.groups[group] = index(len(b.groups))
@ -782,6 +789,7 @@ func (b *builder) writeLanguage() {
lang.updateLater("tw", "twi")
lang.updateLater("nb", "nob")
lang.updateLater("ak", "aka")
lang.updateLater("bh", "bih")
// Ensure that each 2-letter code is matched with a 3-letter code.
for _, v := range lang.s[1:] {
@ -798,10 +806,10 @@ func (b *builder) writeLanguage() {
}
}
// Complete canonialized language tags.
// Complete canonicalized language tags.
lang.freeze()
for i, v := range lang.s {
// We can avoid these manual entries by using the IANI registry directly.
// We can avoid these manual entries by using the IANA registry directly.
// Seems easier to update the list manually, as changes are rare.
// The panic in this loop will trigger if we miss an entry.
add := ""
@ -908,7 +916,7 @@ func (b *builder) writeRegion() {
i := b.region.index(s)
for _, d := range e.description {
if strings.Contains(d, "Private use") {
regionTypes[i] = iso3166UserAssgined
regionTypes[i] = iso3166UserAssigned
}
}
regionTypes[i] |= bcp47Region
@ -1065,7 +1073,7 @@ const (
)
const (
iso3166UserAssgined = 1 << iota
iso3166UserAssigned = 1 << iota
ccTLD
bcp47Region
)
@ -1355,42 +1363,23 @@ func (b *builder) writeLikelyData() {
type mutualIntelligibility struct {
want, have uint16
conf uint8
distance uint8
oneway bool
}
type scriptIntelligibility struct {
lang uint16 // langID or 0 if *
want, have uint8
conf uint8
wantLang, haveLang uint16
wantScript, haveScript uint8
distance uint8
// Always oneway
}
type sortByConf []mutualIntelligibility
func (l sortByConf) Less(a, b int) bool {
return l[a].conf > l[b].conf
}
func (l sortByConf) Swap(a, b int) {
l[a], l[b] = l[b], l[a]
}
func (l sortByConf) Len() int {
return len(l)
}
// toConf converts a percentage value [0, 100] to a confidence class.
func toConf(pct uint8) uint8 {
switch {
case pct == 100:
return 3 // Exact
case pct >= 90:
return 2 // High
case pct > 50:
return 1 // Low
default:
return 0 // No
}
type regionIntelligibility struct {
lang uint16 // compact language id
script uint8 // 0 means any
group uint8 // 0 means any; if bit 7 is set it means inverse
distance uint8
// Always twoway.
}
// writeMatchData writes tables with languages and scripts for which there is
@ -1400,13 +1389,50 @@ func toConf(pct uint8) uint8 {
// We also drop all region-related data as we use a different algorithm to
// determine region equivalence.
func (b *builder) writeMatchData() {
lm := b.supp.LanguageMatching.LanguageMatches
cldr.MakeSlice(&lm).SelectAnyOf("type", "written_new")
regionHierarchy := map[string][]string{}
for _, g := range b.supp.TerritoryContainment.Group {
regions := strings.Split(g.Contains, " ")
regionHierarchy[g.Type] = append(regionHierarchy[g.Type], regions...)
}
regionToGroups := make([]uint8, len(b.region.s))
idToIndex := map[string]uint8{}
for i, mv := range lm[0].MatchVariable {
if i > 6 {
log.Fatalf("Too many groups: %d", i)
}
idToIndex[mv.Id] = uint8(i + 1)
// TODO: also handle '-'
for _, r := range strings.Split(mv.Value, "+") {
todo := []string{r}
for k := 0; k < len(todo); k++ {
r := todo[k]
regionToGroups[b.region.index(r)] |= 1 << uint8(i)
todo = append(todo, regionHierarchy[r]...)
}
}
}
b.writeSlice("regionToGroups", regionToGroups)
b.writeType(mutualIntelligibility{})
b.writeType(scriptIntelligibility{})
lm := b.supp.LanguageMatching.LanguageMatches
cldr.MakeSlice(&lm).SelectAnyOf("type", "written")
b.writeType(regionIntelligibility{})
matchLang := []mutualIntelligibility{}
matchLang := []mutualIntelligibility{{
// TODO: remove once CLDR is fixed.
want: uint16(b.langIndex("sr")),
have: uint16(b.langIndex("hr")),
distance: uint8(5),
}, {
want: uint16(b.langIndex("sr")),
have: uint16(b.langIndex("bs")),
distance: uint8(5),
}}
matchScript := []scriptIntelligibility{}
matchRegion := []regionIntelligibility{}
// Convert the languageMatch entries in lists keyed by desired language.
for _, m := range lm[0].LanguageMatch {
// Different versions of CLDR use different separators.
@ -1414,33 +1440,38 @@ func (b *builder) writeMatchData() {
supported := strings.Replace(m.Supported, "-", "_", -1)
d := strings.Split(desired, "_")
s := strings.Split(supported, "_")
if len(d) != len(s) || len(d) > 2 {
// Skip all entries with regions and work around CLDR bug.
if len(d) != len(s) {
log.Fatalf("not supported: desired=%q; supported=%q", desired, supported)
continue
}
pct, _ := strconv.ParseInt(m.Percent, 10, 8)
if len(d) == 2 && d[0] == s[0] && len(d[1]) == 4 {
// language-script pair.
lang := uint16(0)
if d[0] != "*" {
lang = uint16(b.langIndex(d[0]))
distance, _ := strconv.ParseInt(m.Distance, 10, 8)
switch len(d) {
case 2:
if desired == supported && desired == "*_*" {
continue
}
// language-script pair.
matchScript = append(matchScript, scriptIntelligibility{
lang: lang,
want: uint8(b.script.index(d[1])),
have: uint8(b.script.index(s[1])),
conf: toConf(uint8(pct)),
wantLang: uint16(b.langIndex(d[0])),
haveLang: uint16(b.langIndex(s[0])),
wantScript: uint8(b.script.index(d[1])),
haveScript: uint8(b.script.index(s[1])),
distance: uint8(distance),
})
if m.Oneway != "true" {
matchScript = append(matchScript, scriptIntelligibility{
lang: lang,
want: uint8(b.script.index(s[1])),
have: uint8(b.script.index(d[1])),
conf: toConf(uint8(pct)),
wantLang: uint16(b.langIndex(s[0])),
haveLang: uint16(b.langIndex(d[0])),
wantScript: uint8(b.script.index(s[1])),
haveScript: uint8(b.script.index(d[1])),
distance: uint8(distance),
})
}
} else if len(d) == 1 && d[0] != "*" {
if pct == 100 {
case 1:
if desired == supported && desired == "*" {
continue
}
if distance == 1 {
// nb == no is already handled by macro mapping. Check there
// really is only this case.
if d[0] != "no" || s[0] != "nb" {
@ -1448,28 +1479,57 @@ func (b *builder) writeMatchData() {
}
continue
}
// TODO: consider dropping oneway field and just doubling the entry.
matchLang = append(matchLang, mutualIntelligibility{
want: uint16(b.langIndex(d[0])),
have: uint16(b.langIndex(s[0])),
conf: uint8(pct),
oneway: m.Oneway == "true",
want: uint16(b.langIndex(d[0])),
have: uint16(b.langIndex(s[0])),
distance: uint8(distance),
oneway: m.Oneway == "true",
})
} else {
// TODO: Handle other mappings.
a := []string{"*;*", "*_*;*_*", "es_MX;es_419"}
s := strings.Join([]string{desired, supported}, ";")
if i := sort.SearchStrings(a, s); i == len(a) || a[i] != s {
log.Printf("%q not handled", s)
case 3:
if desired == supported && desired == "*_*_*" {
continue
}
if desired != supported { // (Weird but correct.)
log.Fatalf("not supported: desired=%q; supported=%q", desired, supported)
continue
}
ri := regionIntelligibility{
lang: b.langIndex(d[0]),
distance: uint8(distance),
}
if d[1] != "*" {
ri.script = uint8(b.script.index(d[1]))
}
switch {
case d[2] == "*":
ri.group = 0x80 // not contained in anything
case strings.HasPrefix(d[2], "$!"):
ri.group = 0x80
d[2] = "$" + d[2][len("$!"):]
fallthrough
case strings.HasPrefix(d[2], "$"):
ri.group |= idToIndex[d[2]]
}
matchRegion = append(matchRegion, ri)
default:
log.Fatalf("not supported: desired=%q; supported=%q", desired, supported)
}
}
sort.Stable(sortByConf(matchLang))
// collapse percentage into confidence classes
for i, m := range matchLang {
matchLang[i].conf = toConf(m.conf)
}
sort.SliceStable(matchLang, func(i, j int) bool {
return matchLang[i].distance < matchLang[j].distance
})
b.writeSlice("matchLang", matchLang)
sort.SliceStable(matchScript, func(i, j int) bool {
return matchScript[i].distance < matchScript[j].distance
})
b.writeSlice("matchScript", matchScript)
sort.SliceStable(matchRegion, func(i, j int) bool {
return matchRegion[i].distance < matchRegion[j].distance
})
b.writeSlice("matchRegion", matchRegion)
}
func (b *builder) writeRegionInclusionData() {
@ -1482,6 +1542,11 @@ func (b *builder) writeRegionInclusionData() {
containment = make(map[index][]index)
)
for _, g := range b.supp.TerritoryContainment.Group {
// Skip UN and EURO zone as they are flattening the containment
// relationship.
if g.Type == "EZ" || g.Type == "UN" {
continue
}
group := b.region.index(g.Type)
groupIdx := b.groups[group]
for _, mem := range strings.Split(g.Contains, " ") {
@ -1508,7 +1573,6 @@ func (b *builder) writeRegionInclusionData() {
for _, v := range l {
regionContainment[g] |= 1 << v
}
// log.Printf("%d: %X", g, regionContainment[g])
}
b.writeSlice("regionContainment", regionContainment)

File diff suppressed because it is too large Load diff

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:generate go run maketables.go gen_common.go -output tables.go
//go:generate go run gen.go gen_common.go -output tables.go
//go:generate go run gen_index.go
// Package language implements BCP 47 language tags and related functionality.
@ -129,8 +129,15 @@ const (
// specific language or locale. All language tag values are guaranteed to be
// well-formed.
type Tag struct {
lang langID
region regionID
lang langID
region regionID
// TODO: we will soon run out of positions for script. Idea: instead of
// storing lang, region, and script codes, store only the compact index and
// have a lookup table from this code to its expansion. This greatly speeds
// up table lookup, speed up common variant cases.
// This will also immediately free up 3 extra bytes. Also, the pVariant
// field can now be moved to the lookup table, as the compact index uniquely
// determines the offset of a possible variant.
script scriptID
pVariant byte // offset in str, includes preceding '-'
pExt uint16 // offset of first extension, includes preceding '-'
@ -593,7 +600,7 @@ func (t Tag) Extension(x byte) (ext Extension, ok bool) {
return Extension{ext}, true
}
}
return Extension{string(x)}, false
return Extension{}, false
}
// Extensions returns all extensions of t.

View file

@ -6,6 +6,16 @@ package language
import "errors"
// A MatchOption configures a Matcher.
type MatchOption func(*matcher)
// PreferSameScript will, in the absence of a match, result in the first
// preferred tag with the same script as a supported tag to match this supported
// tag. The default is currently true, but this may change in the future.
func PreferSameScript(preferSame bool) MatchOption {
return func(m *matcher) { m.preferSameScript = preferSame }
}
// Matcher is the interface that wraps the Match method.
//
// Match returns the best match for any of the given tags, along with
@ -36,23 +46,44 @@ func Comprehends(speaker, alternative Tag) Confidence {
// matched tag in t, but is augmented with the Unicode extension ('u')of the
// corresponding preferred tag. This allows user locale options to be passed
// transparently.
func NewMatcher(t []Tag) Matcher {
return newMatcher(t)
func NewMatcher(t []Tag, options ...MatchOption) Matcher {
return newMatcher(t, options)
}
func (m *matcher) Match(want ...Tag) (t Tag, index int, c Confidence) {
match, w, c := m.getBest(want...)
if match == nil {
t = m.default_.tag
} else {
if match != nil {
t, index = match.tag, match.index
} else {
// TODO: this should be an option
t = m.default_.tag
if m.preferSameScript {
outer:
for _, w := range want {
script, _ := w.Script()
if script.scriptID == 0 {
// Don't do anything if there is no script, such as with
// private subtags.
continue
}
for i, h := range m.supported {
if script.scriptID == h.maxScript {
t, index = h.tag, i
break outer
}
}
}
}
// TODO: select first language tag based on script.
}
if w.region != 0 && t.region != 0 && t.region.contains(w.region) {
t, _ = Raw.Compose(t, Region{w.region})
}
// Copy options from the user-provided tag into the result tag. This is hard
// to do after the fact, so we do it here.
// TODO: consider also adding in variants that are compatible with the
// matched language.
// TODO: Add back region if it is non-ambiguous? Or create another tag to
// preserve the region?
// TODO: add in alternative variants to -u-va-.
// TODO: add preferred region to -u-rg-.
// TODO: add other extensions. Merge with existing extensions.
if u, ok := w.Extension('u'); ok {
t, _ = Raw.Compose(t, u)
}
@ -388,16 +419,18 @@ func minimizeTags(t Tag) (Tag, error) {
// matcher keeps a set of supported language tags, indexed by language.
type matcher struct {
default_ *haveTag
index map[langID]*matchHeader
passSettings bool
default_ *haveTag
supported []*haveTag
index map[langID]*matchHeader
passSettings bool
preferSameScript bool
}
// matchHeader has the lists of tags for exact matches and matches based on
// maximized and canonicalized tags for a given language.
type matchHeader struct {
exact []haveTag
max []haveTag
exact []*haveTag
max []*haveTag
}
// haveTag holds a supported Tag and its maximized script and region. The maximized
@ -440,8 +473,10 @@ func makeHaveTag(tag Tag, index int) (haveTag, langID) {
// script to map to another and we rely on this to keep the code simple.
func altScript(l langID, s scriptID) scriptID {
for _, alt := range matchScript {
if (alt.lang == 0 || langID(alt.lang) == l) && scriptID(alt.have) == s {
return scriptID(alt.want)
// TODO: also match cases where language is not the same.
if (langID(alt.wantLang) == l || langID(alt.haveLang) == l) &&
scriptID(alt.haveScript) == s {
return scriptID(alt.wantScript)
}
}
return 0
@ -457,7 +492,7 @@ func (h *matchHeader) addIfNew(n haveTag, exact bool) {
}
}
if exact {
h.exact = append(h.exact, n)
h.exact = append(h.exact, &n)
}
// Allow duplicate maximized tags, but create a linked list to allow quickly
// comparing the equivalents and bail out.
@ -472,7 +507,7 @@ func (h *matchHeader) addIfNew(n haveTag, exact bool) {
break
}
}
h.max = append(h.max, n)
h.max = append(h.max, &n)
}
// header returns the matchHeader for the given language. It creates one if
@ -486,12 +521,26 @@ func (m *matcher) header(l langID) *matchHeader {
return h
}
func toConf(d uint8) Confidence {
if d <= 10 {
return High
}
if d < 30 {
return Low
}
return No
}
// newMatcher builds an index for the given supported tags and returns it as
// a matcher. It also expands the index by considering various equivalence classes
// for a given tag.
func newMatcher(supported []Tag) *matcher {
func newMatcher(supported []Tag, options []MatchOption) *matcher {
m := &matcher{
index: make(map[langID]*matchHeader),
index: make(map[langID]*matchHeader),
preferSameScript: true,
}
for _, o := range options {
o(m)
}
if len(supported) == 0 {
m.default_ = &haveTag{}
@ -502,8 +551,9 @@ func newMatcher(supported []Tag) *matcher {
for i, tag := range supported {
pair, _ := makeHaveTag(tag, i)
m.header(tag.lang).addIfNew(pair, true)
m.supported = append(m.supported, &pair)
}
m.default_ = &m.header(supported[0].lang).exact[0]
m.default_ = m.header(supported[0].lang).exact[0]
for i, tag := range supported {
pair, max := makeHaveTag(tag, i)
if max != tag.lang {
@ -511,6 +561,9 @@ func newMatcher(supported []Tag) *matcher {
}
}
// TODO: include alt script.
// - don't replace regions, but allow regions to be made more specific.
// update is used to add indexes in the map for equivalent languages.
// If force is true, the update will also apply to derived entries. To
// avoid applying a "transitive closure", use false.
@ -520,7 +573,8 @@ func newMatcher(supported []Tag) *matcher {
return
}
hw := m.header(langID(want))
for _, v := range hh.max {
for _, ht := range hh.max {
v := *ht
if conf < v.conf {
v.conf = conf
}
@ -536,9 +590,9 @@ func newMatcher(supported []Tag) *matcher {
// Add entries for languages with mutual intelligibility as defined by CLDR's
// languageMatch data.
for _, ml := range matchLang {
update(ml.want, ml.have, Confidence(ml.conf), false)
update(ml.want, ml.have, toConf(ml.distance), false)
if !ml.oneway {
update(ml.have, ml.want, Confidence(ml.conf), false)
update(ml.have, ml.want, toConf(ml.distance), false)
}
}
@ -580,7 +634,7 @@ func (m *matcher) getBest(want ...Tag) (got *haveTag, orig Tag, c Confidence) {
continue
}
for i := range h.exact {
have := &h.exact[i]
have := h.exact[i]
if have.tag.equalsRest(w) {
return have, w, Exact
}
@ -591,7 +645,7 @@ func (m *matcher) getBest(want ...Tag) (got *haveTag, orig Tag, c Confidence) {
// Base language is not defined.
if h != nil {
for i := range h.exact {
have := &h.exact[i]
have := h.exact[i]
if have.tag.equalsRest(w) {
return have, w, Exact
}
@ -609,11 +663,11 @@ func (m *matcher) getBest(want ...Tag) (got *haveTag, orig Tag, c Confidence) {
}
// Check for match based on maximized tag.
for i := range h.max {
have := &h.max[i]
have := h.max[i]
best.update(have, w, max.script, max.region)
if best.conf == Exact {
for have.nextMax != 0 {
have = &h.max[have.nextMax]
have = h.max[have.nextMax]
best.update(have, w, max.script, max.region)
}
return best.have, best.want, High
@ -635,11 +689,12 @@ type bestMatch struct {
want Tag
conf Confidence
// Cached results from applying tie-breaking rules.
origLang bool
origReg bool
regDist uint8
origScript bool
parentDist uint8 // 255 if have is not an ancestor of want tag.
origLang bool
origReg bool
regGroupDist uint8
regDist uint8
origScript bool
parentDist uint8 // 255 if have is not an ancestor of want tag.
}
// update updates the existing best match if the new pair is considered to be a
@ -693,6 +748,14 @@ func (m *bestMatch) update(have *haveTag, tag Tag, maxScript scriptID, maxRegion
beaten = true
}
regGroupDist := regionGroupDist(have.maxRegion, maxRegion, maxScript, tag.lang)
if !beaten && m.regGroupDist != regGroupDist {
if regGroupDist > m.regGroupDist {
return
}
beaten = true
}
// We prefer if the pre-maximized region was specified and identical.
origReg := have.tag.region == tag.region && tag.region != 0
if !beaten && m.origReg != origReg {
@ -702,8 +765,22 @@ func (m *bestMatch) update(have *haveTag, tag Tag, maxScript scriptID, maxRegion
beaten = true
}
// Next we prefer smaller distances between regions, as defined by regionDist.
regDist := regionDist(have.maxRegion, maxRegion, tag.lang)
// TODO: remove the region distance rule. Region distance has been replaced
// by the region grouping rule. For now we leave it as it still seems to
// have a net positive effect when applied after the grouping rule.
// Possible solutions:
// - apply the primary locale rule first to effectively disable region
// region distance if groups are defined.
// - express the following errors in terms of grouping (if possible)
// - find another method of handling the following cases.
// maximization of legacy: find mo in
// "sr-Cyrl, sr-Latn, ro, ro-MD": have ro; want ro-MD (High)
// region distance French: find fr-US in
// "en, fr, fr-CA, fr-CH": have fr; want fr-CA (High)
// Next we prefer smaller distances between regions, as defined by
// regionDist.
regDist := uint8(regionDistance(have.maxRegion, maxRegion))
if !beaten && m.regDist != regDist {
if regDist > m.regDist {
return
@ -721,6 +798,9 @@ func (m *bestMatch) update(have *haveTag, tag Tag, maxScript scriptID, maxRegion
}
// Finally we prefer tags which have a closer parent relationship.
// TODO: the parent relationship no longer seems necessary. It doesn't hurt
// to leave it in as the final tie-breaker, though, especially until the
// grouping data has further matured.
parentDist := parentDistance(have.tag.region, tag)
if !beaten && m.parentDist != parentDist {
if parentDist > m.parentDist {
@ -737,6 +817,7 @@ func (m *bestMatch) update(have *haveTag, tag Tag, maxScript scriptID, maxRegion
m.origLang = origLang
m.origReg = origReg
m.origScript = origScript
m.regGroupDist = regGroupDist
m.regDist = regDist
m.parentDist = parentDist
}
@ -759,15 +840,27 @@ func parentDistance(haveRegion regionID, tag Tag) uint8 {
return d
}
// regionDist wraps regionDistance with some exceptions to the algorithmic distance.
func regionDist(a, b regionID, lang langID) uint8 {
if lang == _en {
// Two variants of non-US English are close to each other, regardless of distance.
if a != _US && b != _US {
return 2
// regionGroupDist computes the distance between two regions based on their
// CLDR grouping.
func regionGroupDist(a, b regionID, script scriptID, lang langID) uint8 {
aGroup := uint(regionToGroups[a]) << 1
bGroup := uint(regionToGroups[b]) << 1
for _, ri := range matchRegion {
if langID(ri.lang) == lang && (ri.script == 0 || scriptID(ri.script) == script) {
group := uint(1 << (ri.group &^ 0x80))
if 0x80&ri.group == 0 {
if aGroup&bGroup&group != 0 { // Both regions are in the group.
return ri.distance
}
} else {
if (aGroup|bGroup)&group == 0 { // Both regions are not in the group.
return ri.distance
}
}
}
}
return uint8(regionDistance(a, b))
const defaultDistance = 4
return defaultDistance
}
// regionDistance computes the distance between two regions based on the

File diff suppressed because it is too large Load diff