Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(148)

Unified Diff: vpython/python/version.go

Issue 2701073002: vpython: Add Python interpreter handling package. (Closed)
Patch Set: rebase Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « vpython/python/python_test.go ('k') | vpython/python/version_test.go » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: vpython/python/version.go
diff --git a/vpython/python/version.go b/vpython/python/version.go
new file mode 100644
index 0000000000000000000000000000000000000000..5d4639773bfc0166487c5b0c0333fd833a3dfc6a
--- /dev/null
+++ b/vpython/python/version.go
@@ -0,0 +1,144 @@
+// Copyright 2017 The LUCI Authors. All rights reserved.
+// Use of this source code is governed under the Apache License, Version 2.0
+// that can be found in the LICENSE file.
+
+package python
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+
+ "github.com/luci/luci-go/common/errors"
+)
+
+// Version is a Python interpreter version.
+type Version struct {
+ Major int
+ Minor int
+ Patch int
+}
+
+// ParseVersion parses a Python version from a version string (e.g., "1.2.3").
+func ParseVersion(s string) (Version, error) {
+ if len(s) == 0 {
+ return Version{}, nil
+ }
+
+ parseVersion := func(value string) (int, error) {
+ version, err := strconv.Atoi(value)
+ if err != nil {
+ return 0, errors.Annotate(err).Reason("invalid number value: %(value)q").
+ D("value", value).
+ Err()
+ }
+ if version < 0 {
+ return 0, errors.Reason("version (%(version)d) must not be negative").
+ D("version", version).
+ Err()
+ }
+ return version, nil
+ }
+
+ var v Version
+ parts := strings.Split(s, ".")
+ var err error
+ switch l := len(parts); l {
+ case 3:
+ if v.Patch, err = parseVersion(parts[2]); err != nil {
+ return v, errors.Annotate(err).Reason("invalid patch value").Err()
+ }
+ fallthrough
+
+ case 2:
+ if v.Minor, err = parseVersion(parts[1]); err != nil {
+ return v, errors.Annotate(err).Reason("invalid minor value").Err()
+ }
+ fallthrough
+
+ case 1:
+ if v.Major, err = parseVersion(parts[0]); err != nil {
+ return v, errors.Annotate(err).Reason("invalid major value").Err()
+ }
+ if v.IsZero() {
+ return v, errors.Reason("version is incomplete").Err()
+ }
+ return v, nil
+
+ default:
+ return v, errors.Reason("unsupported number of parts (%(count)d)").
+ D("count", l).
+ Err()
+ }
+}
+
+func (v Version) String() string {
+ if v.IsZero() {
+ return ""
+ }
+ return fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)
+}
+
+// IsZero returns true if the Version is empty. This is true if the Major field,
+// which must be set, is empty.
+func (v *Version) IsZero() bool { return v.Major <= 0 }
+
+// PythonBase returns the base Python interpreter name for this version.
+func (v *Version) PythonBase() string {
+ switch {
+ case v.IsZero():
+ return "python"
+ case v.Minor > 0:
+ return fmt.Sprintf("python%d.%d", v.Major, v.Minor)
+ default:
+ return fmt.Sprintf("python%d", v.Major)
+ }
+}
+
+// IsSatisfiedBy returns true if "other" is a suitable match for this version. A
+// suitable match:
+//
+// - MUST have a Major version.
+// - If v is zero, other is automatically suitable.
+// - If v is non-zero, other must have the same Major version as v, and a
+// minor/patch version that is >= v's.
+func (v *Version) IsSatisfiedBy(other Version) bool {
+ switch {
+ case other.Major <= 0:
+ // "other" must have a Major version.
+ return false
+ case v.IsZero():
+ // "v" is zero (anything), so "other" satisfies it.
+ return true
+ case v.Major != other.Major:
+ // "other" must match "v"'s Major version precisely.
+ return false
+ case v.Minor > other.Minor:
+ // "v" requires a Minor version that is greater than "other"'s.
+ return false
+ case v.Minor < other.Minor:
+ // "v" requires a Minor version that is less than "other"'s.
+ return true
+ case v.Patch > other.Patch:
+ // "v" requires a Patch version that is greater than "other"'s.
+ return false
+ default:
+ return true
+ }
+}
+
+// Less returns true if "v"'s Version semantically precedes "other".
+func (v *Version) Less(other *Version) bool {
+ switch {
+ case v.Major < other.Major:
+ return true
+ case v.Major > other.Major:
+ return false
+ case v.Minor < other.Minor:
+ return true
+ case v.Minor > other.Minor:
+ return false
+ default:
+ return (v.Patch < other.Patch)
+ }
+}
« no previous file with comments | « vpython/python/python_test.go ('k') | vpython/python/version_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698