Skip to content
This repository has been archived by the owner on Jun 28, 2022. It is now read-only.

Python: README overhaul #1263

Merged
merged 1 commit into from
May 18, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,20 @@ public String getOutputFileName() {

// TODO: (landrito) this is copied from SurfaceNamer. Figure out a way to consolidate the methods.
public String getReleaseAnnotation(ReleaseLevel releaseLevel) {
return getNotImplementedString("SurfaceNamer.getReleaseAnnotation");
switch (releaseLevel) {
case UNSET_RELEASE_LEVEL:
// fallthrough
case ALPHA:
return "Alpha";
case BETA:
return "Beta";
case GA:
return "Production/Stable";
case DEPRECATED:
return "Inactive";
default:
throw new IllegalStateException("Invalid development status");
}
}

/** Returns the unimplemented string message */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,37 @@
package com.google.api.codegen.transformer.py;

import com.google.api.codegen.GapicContext;
import com.google.api.codegen.InterfaceView;
import com.google.api.codegen.SnippetSetRunner;
import com.google.api.codegen.TargetLanguage;
import com.google.api.codegen.config.FlatteningConfig;
import com.google.api.codegen.config.GapicProductConfig;
import com.google.api.codegen.config.PackageMetadataConfig;
import com.google.api.codegen.gapic.GapicProvider;
import com.google.api.codegen.transformer.DefaultFeatureConfig;
import com.google.api.codegen.transformer.DynamicLangApiMethodTransformer;
import com.google.api.codegen.transformer.GapicInterfaceContext;
import com.google.api.codegen.transformer.GapicMethodContext;
import com.google.api.codegen.transformer.InitCodeTransformer;
import com.google.api.codegen.transformer.ModelToViewTransformer;
import com.google.api.codegen.transformer.ModelTypeTable;
import com.google.api.codegen.transformer.PackageMetadataNamer;
import com.google.api.codegen.transformer.PackageMetadataTransformer;
import com.google.api.codegen.transformer.TestCaseTransformer;
import com.google.api.codegen.util.py.PythonTypeTable;
import com.google.api.codegen.util.testing.PythonValueProducer;
import com.google.api.codegen.util.testing.ValueProducer;
import com.google.api.codegen.viewmodel.ApiMethodView;
import com.google.api.codegen.viewmodel.OptionalArrayMethodView;
import com.google.api.codegen.viewmodel.SimpleViewModel;
import com.google.api.codegen.viewmodel.ViewModel;
import com.google.api.tools.framework.model.Interface;
import com.google.api.tools.framework.model.Method;
import com.google.api.tools.framework.model.Model;
import com.google.api.tools.framework.snippet.Doc;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.io.Files;
import java.io.File;
Expand All @@ -47,8 +65,18 @@
public class PythonPackageMetadataTransformer implements ModelToViewTransformer {
private static final String TEST_PREFIX = "test.";

private static final String GITHUB_DOC_HOST =
"https://googlecloudplatform.github.io/google-cloud-python/stable";
private static final String GITHUB_REPO_HOST =
"https://github.com/GoogleCloudPlatform/google-cloud-python";
private static final String AUTH_DOC_PATH = "/google-cloud-auth";
private static final String LIB_DOC_PATH = "/%s-usage";
private static final String MAIN_README_PATH = "/blob/master/README.rst";

private final PackageMetadataConfig packageConfig;
private final PackageMetadataTransformer metadataTransformer = new PackageMetadataTransformer();
private final ValueProducer valueProducer = new PythonValueProducer();
private final TestCaseTransformer testCaseTransformer = new TestCaseTransformer(valueProducer);
private final List<GapicProvider<? extends Object>> gapicProviders;
private final PythonSurfaceNamer surfaceNamer;
private List<String> apiModules = null;
Expand All @@ -66,8 +94,9 @@ public List<ViewModel> transform(final Model model, final GapicProductConfig pro
String version = packageConfig.apiVersion();
List<ViewModel> metadata =
computeInitFiles(computePackages(productConfig.getPackageName()), version);
PackageMetadataNamer namer = new PackageMetadataNamer();
for (String templateFileName : getTopLevelTemplateFileNames()) {
metadata.add(generateMetadataView(model, productConfig, templateFileName));
metadata.add(generateMetadataView(model, productConfig, templateFileName, namer));
}
return metadata;
}
Expand Down Expand Up @@ -100,23 +129,62 @@ public List<String> getInitTemplateFileNames() {
}

private ViewModel generateMetadataView(
Model model, GapicProductConfig productConfig, String template) {
Model model, GapicProductConfig productConfig, String template, PackageMetadataNamer namer) {
List<ApiMethodView> exampleMethods = generateExampleMethods(model, productConfig);
String noLeadingPyDir = template.startsWith("py/") ? template.substring(3) : template;
int extensionIndex = noLeadingPyDir.lastIndexOf(".");
String outputPath = noLeadingPyDir.substring(0, extensionIndex);
computeModules(gapicProviders);

return metadataTransformer
.generateMetadataView(packageConfig, model, template, outputPath, TargetLanguage.PYTHON)
.namespacePackages(
computeNamespacePackages(productConfig.getPackageName(), packageConfig.apiVersion()))
.developmentStatus(
surfaceNamer.getReleaseAnnotation(packageConfig.releaseLevel(TargetLanguage.PYTHON)))
.developmentStatusTitle(
namer.getReleaseAnnotation(packageConfig.releaseLevel(TargetLanguage.PYTHON)))
.apiModules(apiModules)
.typeModules(typeModules)
.exampleMethods(exampleMethods)
.targetLanguage("Python")
.mainReadmeLink(GITHUB_REPO_HOST + MAIN_README_PATH)
.libraryDocumentationLink(
GITHUB_DOC_HOST + String.format(LIB_DOC_PATH, packageConfig.shortName()))
.authDocumentationLink(GITHUB_DOC_HOST + AUTH_DOC_PATH)
.versioningDocumentationLink(GITHUB_REPO_HOST + MAIN_README_PATH)
.build();
}

// Generates methods used as examples for the README.md file.
// This currently generates a list of methods that have smoke test configuration. In the future,
// the example methods may be configured separately.
private List<ApiMethodView> generateExampleMethods(
Model model, GapicProductConfig productConfig) {
ImmutableList.Builder<ApiMethodView> exampleMethods = ImmutableList.builder();
for (Interface apiInterface : new InterfaceView().getElementIterable(model)) {
GapicInterfaceContext context = createContext(apiInterface, productConfig);
if (context.getInterfaceConfig().getSmokeTestConfig() != null) {
Method method = context.getInterfaceConfig().getSmokeTestConfig().getMethod();
FlatteningConfig flatteningGroup =
testCaseTransformer.getSmokeTestFlatteningGroup(
context.getMethodConfig(method), context.getInterfaceConfig().getSmokeTestConfig());
GapicMethodContext flattenedMethodContext =
context.asFlattenedMethodContext(method, flatteningGroup);
exampleMethods.add(createExampleApiMethodView(flattenedMethodContext));
}
}
return exampleMethods.build();
}

private OptionalArrayMethodView createExampleApiMethodView(GapicMethodContext context) {
DynamicLangApiMethodTransformer apiMethodTransformer =
new DynamicLangApiMethodTransformer(
new PythonApiMethodParamTransformer(),
new InitCodeTransformer(new PythonImportSectionTransformer()));

return apiMethodTransformer.generateMethod(context);
}

/** Determines the Python files generated in the main phase of generation. */
private void computeModules(List<GapicProvider<? extends Object>> gapicProviders) {
// Only run generation once.
Expand Down Expand Up @@ -197,4 +265,16 @@ private List<ViewModel> computeInitFiles(List<String> packages, final String api
}
return initFiles;
}

private GapicInterfaceContext createContext(
Interface apiInterface, GapicProductConfig productConfig) {
return GapicInterfaceContext.create(
apiInterface,
productConfig,
new ModelTypeTable(
new PythonTypeTable(productConfig.getPackageName()),
new PythonModelTypeNameConverter(productConfig.getPackageName())),
new PythonSurfaceNamer(productConfig.getPackageName()),
new DefaultFeatureConfig());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
*/
package com.google.api.codegen.transformer.ruby;

import com.google.api.codegen.ReleaseLevel;
import com.google.api.codegen.transformer.PackageMetadataNamer;
import com.google.api.codegen.util.Name;
import com.google.common.base.Joiner;
Expand Down Expand Up @@ -47,22 +46,4 @@ public String getMetadataIdentifier() {
public String getOutputFileName() {
return getMetadataIdentifier() + ".gemspec";
}

@Override
public String getReleaseAnnotation(ReleaseLevel releaseLevel) {
switch (releaseLevel) {
case UNSET_RELEASE_LEVEL:
// fallthrough
case ALPHA:
return "Alpha";
case BETA:
return "Beta";
case GA:
return "Production/Stable";
case DEPRECATED:
return "Inactive";
default:
throw new IllegalStateException("Invalid development status");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ private ViewModel generateReadmeView(
productConfig,
ImportSectionView.newBuilder().build(),
new RubySurfaceNamer(productConfig.getPackageName())))
.developmentStatus(
.developmentStatusTitle(
namer.getReleaseAnnotation(packageConfig.releaseLevel(TargetLanguage.RUBY)))
.exampleMethods(exampleMethods)
.targetLanguage("Ruby")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ public String resourceRoot() {
@Nullable
public abstract String developmentStatus();

@Nullable
public abstract String developmentStatusTitle();

public abstract boolean hasMultipleServices();

public abstract boolean hasSmokeTests();
Expand Down Expand Up @@ -203,6 +206,9 @@ public abstract static class Builder {
/** The developement status of the package. E.g., "alpha". */
public abstract Builder developmentStatus(String val);

/** The developement status of the package used in titles. E.g., "Alpha". */
public abstract Builder developmentStatusTitle(String s);

/** Whether the package contains multiple service objects */
public abstract Builder hasMultipleServices(boolean val);

Expand Down
100 changes: 35 additions & 65 deletions src/main/resources/com/google/api/codegen/py/README.rst.snip
Original file line number Diff line number Diff line change
@@ -1,81 +1,51 @@
@snippet generate(metadata)
GAPIC library for the {@metadata.fullName}
================================================================================

{@metadata.gapicPackageName} uses google-gax_ (Google API extensions) to provide an
easy-to-use client library for the `{@metadata.fullName}`_ ({@metadata.majorVersion}) defined in the googleapis_ git repository


.. _`googleapis`: https://github.com/googleapis/googleapis/tree/master/{@metadata.protoPath}
.. _`google-gax`: https://github.com/googleapis/gax-python
.. _`{@metadata.fullName}`: https://developers.google.com/apis-explorer/?hl=en_US#p/{@metadata.discoveryApiName}/{@metadata.majorVersion}/

Getting started
---------------

{@metadata.gapicPackageName} will allow you to connect to the
{@metadata.fullName} and access all its methods. In order to do this, you need
to set up authentication as well as install the library locally.


Setup Authentication
~~~~~~~~~~~~~~~~~~~~

To authenticate all your API calls, first install and setup the `Google Cloud SDK`_.
Once done, you can then run the following command in your terminal:

.. code-block:: console
@extends "readme_rst.snip"
@extends "py/method_sample.snip"

$ gcloud beta auth application-default login

or

.. code-block:: console

$ gcloud auth login

Please see `gcloud beta auth application-default login`_ document for the difference between these commands.

.. _Google Cloud SDK: https://cloud.google.com/sdk/
.. _gcloud beta auth application-default login: https://cloud.google.com/sdk/gcloud/reference/beta/auth/application-default/login


Installation
~~~~~~~~~~~~
@snippet generate(metadata)
{@readme(metadata, exampleMethods(metadata.exampleMethods), installationLines(metadata))}
@end

Install this library in a `virtualenv`_ using pip. `virtualenv`_ is a tool to
create isolated Python environments. The basic problem it addresses is one of
dependencies and versions, and indirectly permissions.
@private exampleMethods(methods)
@join method : methods on BREAK
{@method.apiClassName}
^^^^^^^^^^^^^^^^^^^^^^

With `virtualenv`_, it's possible to install this library without needing system
install permissions, and without clashing with the installed system
dependencies.
.. code:: py

.. _`virtualenv`: https://virtualenv.pypa.io/en/latest/
{@sampleCode_(method)}
@end
@end

@private installationLines(metadata)
Install this library in a `virtualenv`_ using pip. `virtualenv`_ is a tool to
create isolated Python environments. The basic problem it addresses is one of
dependencies and versions, and indirectly permissions.

Mac/Linux
~~~~~~~~~~
With `virtualenv`_, it's possible to install this library without needing system
install permissions, and without clashing with the installed system
dependencies.

.. code-block:: console
.. _`virtualenv`: https://virtualenv.pypa.io/en/latest/

pip install virtualenv
virtualenv <your-env>
source <your-env>/bin/activate
<your-env>/bin/pip install {@metadata.gapicPackageName}

Mac/Linux
^^^^^^^^^

Windows
~~~~~~~
.. code-block:: console

.. code-block:: console
pip install virtualenv
virtualenv <your-env>
source <your-env>/bin/activate
<your-env>/bin/pip install {@metadata.gapicPackageName}

pip install virtualenv
virtualenv <your-env>
<your-env>\Scripts\activate
<your-env>\Scripts\pip.exe install {@metadata.gapicPackageName}

Windows
^^^^^^^

At this point you are all set to continue.
.. code-block:: console

pip install virtualenv
virtualenv <your-env>
<your-env>\Scripts\activate
<your-env>\Scripts\pip.exe install {@metadata.gapicPackageName}
@end
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
@end
@end

@private sampleCode_(apiMethod)
@snippet sampleCode_(apiMethod)
{@importList(apiMethod.initCode.importSection.appImports)}
client = {@apiMethod.apiVariableName}.{@apiMethod.apiClassName}()
@if apiMethod.initCode.lines
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/com/google/api/codegen/readme.snip
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
@end

@private title(metadata)
@# {@metadata.targetLanguage} Client{@plurality(metadata.hasMultipleServices)} for {@metadata.fullName} ([{@metadata.developmentStatus}]({@metadata.versioningDocumentationLink}))
@# {@metadata.targetLanguage} Client{@plurality(metadata.hasMultipleServices)} for {@metadata.fullName} ([{@metadata.developmentStatusTitle}]({@metadata.versioningDocumentationLink}))

Idiomatic {@metadata.targetLanguage} client{@plurality(metadata.hasMultipleServices)} for [{@metadata.fullName}][Product Documentation]
- [Client Library Documentation][]
Expand Down
Loading