Skip to content

Commit 79f599a

Browse files
authored
feat(python): allow default version to be overridden (#4206)
Adds PythonPackage.DefaultVersion which is populated during migration, if and only if it is not the same as the final part of the first API path, and then uses this override in repo metadata generation. Additionally, the toAPIs code in the migration tool now sorts the APIs by path before returning the list. This means that migration can process the APIs in the same order they'll be saved at the end. Fixes #3146
1 parent 8e32f6c commit 79f599a

10 files changed

Lines changed: 87 additions & 24 deletions

File tree

doc/config-schema.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ This document describes the schema for the librarian.yaml.
157157
| `name_pretty_override` | string | Allows the "name_pretty" field in .repo-metadata.json to be overridden, to reduce diffs while migrating. TODO(https://github.com/googleapis/librarian/issues/4175): remove this field. |
158158
| `product_documentation_override` | string | Allows the "product_documentation" field in .repo-metadata.json to be overridden, to reduce diffs while migrating. TODO(https://github.com/googleapis/librarian/issues/4175): remove this field. |
159159
| `metadata_name_override` | string | Allows the name in .repo-metadata.json (which is also used as part of the client documentation URI) to be overridden. By default it's the package name, but older packages use the API short name instead. |
160+
| `default_version` | string | Is the default version of the API to use. When omitted, the version in the first API path is used. |
160161

161162
## RustCrate Configuration
162163

internal/config/language.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,10 @@ type PythonPackage struct {
324324
// default it's the package name, but older packages use the API short name
325325
// instead.
326326
MetadataNameOverride string `yaml:"metadata_name_override,omitempty"`
327+
328+
// DefaultVersion is the default version of the API to use. When omitted,
329+
// the version in the first API path is used.
330+
DefaultVersion string `yaml:"default_version,omitempty"`
327331
}
328332

329333
// PythonDefault contains Python-specific default configuration.

internal/librarian/python/generate.go

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -108,24 +108,27 @@ func generate(ctx context.Context, config *config.Config, library *config.Librar
108108

109109
// createRepoMetadata creates (in memory, not on disk) a RepoMetadata suitable
110110
// for the given library.
111-
func createRepoMetadata(config *config.Config, library *config.Library, googleapisDir string) (*repometadata.RepoMetadata, error) {
112-
// TODO(https://github.com/googleapis/librarian/issues/3157):
113-
// Copy files from .librarian/generator-input/client-post-processing
114-
// for post processing, or reimplement.
115-
repoMetadata, err := repometadata.FromLibrary(config, library, googleapisDir)
111+
func createRepoMetadata(cfg *config.Config, library *config.Library, googleapisDir string) (*repometadata.RepoMetadata, error) {
112+
// Just to avoid lots of checks for library.Python being nil.
113+
packageOptions := library.Python
114+
if packageOptions == nil {
115+
packageOptions = &config.PythonPackage{}
116+
}
117+
repoMetadata, err := repometadata.FromLibrary(cfg, library, googleapisDir)
116118
if err != nil {
117119
return nil, err
118120
}
119-
if library.Python != nil && library.Python.MetadataNameOverride != "" {
120-
repoMetadata.Name = library.Python.MetadataNameOverride
121+
if packageOptions.MetadataNameOverride != "" {
122+
repoMetadata.Name = packageOptions.MetadataNameOverride
121123
} else {
122124
repoMetadata.Name = library.Name
123125
}
124-
// TODO(https://github.com/googleapis/librarian/issues/3146):
125-
// Remove the default version fudge here, as Generate should
126-
// compute it. For now, use the last component of the first api path as
127-
// the default version.
126+
// Use the version of the first-listed API path as the default version,
127+
// unless it's overridden.
128128
repoMetadata.DefaultVersion = filepath.Base(library.APIs[0].Path)
129+
if packageOptions.DefaultVersion != "" {
130+
repoMetadata.DefaultVersion = packageOptions.DefaultVersion
131+
}
129132
// TODO(https://github.com/googleapis/librarian/issues/4147): use the right
130133
// library type.
131134
repoMetadata.LibraryType = repometadata.GAPICAutoLibraryType
@@ -137,11 +140,11 @@ func createRepoMetadata(config *config.Config, library *config.Library, googleap
137140
}
138141
repoMetadata.ClientDocumentation = fmt.Sprintf(docTemplate, repoMetadata.Name)
139142
// TODO(https://github.com/googleapis/librarian/issues/4175): remove these.
140-
if library.Python != nil && library.Python.NamePrettyOverride != "" {
141-
repoMetadata.NamePretty = library.Python.NamePrettyOverride
143+
if packageOptions.NamePrettyOverride != "" {
144+
repoMetadata.NamePretty = packageOptions.NamePrettyOverride
142145
}
143-
if library.Python != nil && library.Python.ProductDocumentationOverride != "" {
144-
repoMetadata.ProductDocumentation = library.Python.ProductDocumentationOverride
146+
if packageOptions.ProductDocumentationOverride != "" {
147+
repoMetadata.ProductDocumentation = packageOptions.ProductDocumentationOverride
145148
}
146149
return repoMetadata, nil
147150
}

internal/librarian/python/generate_test.go

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -765,9 +765,8 @@ func TestCreateRepoMetadata(t *testing.T) {
765765
Name: "google-cloud-secret-manager",
766766
ReleaseLevel: "stable",
767767
APIs: []*config.API{
768-
{
769-
Path: "google/cloud/secretmanager/v1",
770-
},
768+
{Path: "google/cloud/secretmanager/v1"},
769+
{Path: "google/cloud/secrets/v1beta1"},
771770
},
772771
},
773772
want: &repometadata.RepoMetadata{
@@ -822,11 +821,11 @@ func TestCreateRepoMetadata(t *testing.T) {
822821
ReleaseLevel: "stable",
823822
DescriptionOverride: "overridden description",
824823
APIs: []*config.API{
825-
{
826-
Path: "google/cloud/secretmanager/v1",
827-
},
824+
{Path: "google/cloud/secretmanager/v1"},
825+
{Path: "google/cloud/secrets/v1beta1"},
828826
},
829827
Python: &config.PythonPackage{
828+
DefaultVersion: "v1beta1",
830829
MetadataNameOverride: "secretmanager",
831830
NamePrettyOverride: "overridden name_pretty",
832831
ProductDocumentationOverride: "overridden product_documentation",
@@ -846,6 +845,34 @@ func TestCreateRepoMetadata(t *testing.T) {
846845
APIDescription: "overridden description",
847846
LibraryType: "GAPIC_AUTO",
848847
ClientDocumentation: "https://cloud.google.com/python/docs/reference/secretmanager/latest",
848+
DefaultVersion: "v1beta1",
849+
},
850+
},
851+
{
852+
name: "default version",
853+
library: &config.Library{
854+
Name: "google-cloud-secret-manager",
855+
ReleaseLevel: "stable",
856+
APIs: []*config.API{
857+
{
858+
Path: "google/cloud/secretmanager/v1",
859+
},
860+
},
861+
},
862+
want: &repometadata.RepoMetadata{
863+
Name: "google-cloud-secret-manager",
864+
NamePretty: "Secret Manager",
865+
ProductDocumentation: "https://cloud.google.com/secret-manager/",
866+
IssueTracker: "https://issuetracker.google.com/issues/new?component=784854&template=1380926",
867+
ReleaseLevel: "stable",
868+
Language: "python",
869+
Repo: "googleapis/google-cloud-python",
870+
DistributionName: "google-cloud-secret-manager",
871+
APIID: "secretmanager.googleapis.com",
872+
APIShortname: "secretmanager",
873+
APIDescription: "Stores sensitive data such as API keys, passwords, and certificates.\nProvides convenience while improving security.",
874+
LibraryType: "GAPIC_AUTO",
875+
ClientDocumentation: "https://cloud.google.com/python/docs/reference/google-cloud-secret-manager/latest",
849876
DefaultVersion: "v1",
850877
},
851878
},

tool/cmd/migrate/legacylibrarian.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"reflect"
2525
"slices"
2626
"sort"
27+
"strings"
2728

2829
"github.com/bazelbuild/buildtools/build"
2930
"github.com/googleapis/librarian/internal/config"
@@ -343,6 +344,12 @@ func toAPIs(legacyapis []*legacyconfig.API) []*config.API {
343344
Path: api.Path,
344345
})
345346
}
347+
// Formatting the library will sort the APIs by path later anyway, so let's
348+
// do that now. That way the migration code will observe the list of APIs
349+
// in the same order that it will eventually be saved.
350+
slices.SortFunc(apis, func(a, b *config.API) int {
351+
return strings.Compare(a.Path, b.Path)
352+
})
346353
return apis
347354
}
348355

tool/cmd/migrate/legacylibrarian_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,3 +720,18 @@ func TestParseBazel_Error(t *testing.T) {
720720
})
721721
}
722722
}
723+
724+
func TestToAPIs(t *testing.T) {
725+
legacyAPIs := []*legacyconfig.API{
726+
{Path: "google/cloud/functions/v2"},
727+
{Path: "google/cloud/functions/v1"},
728+
}
729+
want := []*config.API{
730+
{Path: "google/cloud/functions/v1"},
731+
{Path: "google/cloud/functions/v2"},
732+
}
733+
got := toAPIs(legacyAPIs)
734+
if diff := cmp.Diff(want, got); diff != "" {
735+
t.Errorf("mismatch (-want +got):\n%s", diff)
736+
}
737+
}

tool/cmd/migrate/python.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ func filterPathsByRegex(paths []string, regexps []*regexp.Regexp) []string {
299299
func applyRepoMetadata(metadataPath, googleapisDir string, library *config.Library) (*config.Library, error) {
300300
defaultTitle := ""
301301
defaultDocumentationURI := ""
302+
defaultDefaultVersion := ""
302303
// Load the service config file for the first API if there is one, and
303304
// use that
304305
if len(library.APIs) > 0 {
@@ -308,6 +309,7 @@ func applyRepoMetadata(metadataPath, googleapisDir string, library *config.Libra
308309
}
309310
defaultTitle = apiInfo.Title
310311
defaultDocumentationURI = apiInfo.DocumentationURI
312+
defaultDefaultVersion = filepath.Base(library.APIs[0].Path)
311313
}
312314

313315
// Load the current repo metadata and apply overrides for anything that
@@ -338,6 +340,9 @@ func applyRepoMetadata(metadataPath, googleapisDir string, library *config.Libra
338340
if repoMetadata.Name != library.Name {
339341
library.Python.MetadataNameOverride = repoMetadata.Name
340342
}
343+
if repoMetadata.DefaultVersion != defaultDefaultVersion {
344+
library.Python.DefaultVersion = repoMetadata.DefaultVersion
345+
}
341346

342347
return library, nil
343348
}

tool/cmd/migrate/python_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ func TestBuildPythonLibraries(t *testing.T) {
128128
},
129129
},
130130
{
131-
name: "billing budgets (transport varies by API)",
131+
name: "billing budgets (transport varies by API, need explicit default)",
132132
input: &MigrationInput{
133133
repoPath: "testdata/google-cloud-python",
134134
librarianState: &legacyconfig.LibrarianState{
@@ -153,6 +153,7 @@ func TestBuildPythonLibraries(t *testing.T) {
153153
},
154154
DescriptionOverride: "The Cloud Billing Budget API stores Cloud Billing budgets, which define a budget plan and the rules to execute as spend is tracked against that plan.",
155155
Python: &config.PythonPackage{
156+
DefaultVersion: "v1beta",
156157
NamePrettyOverride: "Cloud Billing Budget",
157158
ProductDocumentationOverride: "https://cloud.google.com/billing/docs/how-to/budget-api-overview",
158159
OptArgsByAPI: map[string][]string{

tool/cmd/migrate/testdata/google-cloud-python/packages/google-cloud-audit-log/.repo-metadata.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"api_id": "",
33
"api_shortname": "auditlog",
44
"client_documentation": "https://github.com/googleapis/google-cloud-python/tree/main/packages/google-cloud-audit-log",
5-
"default_version": "apiVersion",
5+
"default_version": "",
66
"distribution_name": "google-cloud-audit-log",
77
"issue_tracker": "",
88
"language": "python",

tool/cmd/migrate/testdata/google-cloud-python/packages/google-cloud-billing-budgets/.repo-metadata.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"api_id": "billingbudgets.googleapis.com",
44
"api_shortname": "billingbudgets",
55
"client_documentation": "https://cloud.google.com/python/docs/reference/google-cloud-billing-budgets/latest",
6-
"default_version": "v1",
6+
"default_version": "v1beta",
77
"distribution_name": "google-cloud-billing-budgets",
88
"issue_tracker": "https://issuetracker.google.com/savedsearches/559770",
99
"language": "python",

0 commit comments

Comments
 (0)