Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: generate snippet metadata #1129

Merged
merged 24 commits into from
Jan 18, 2022
Merged

feat: generate snippet metadata #1129

merged 24 commits into from
Jan 18, 2022

Conversation

busunkim96
Copy link
Contributor

@busunkim96 busunkim96 commented Jan 11, 2022

Follow up to #1121.

Main changes:

  • When snippets are generated, snippet metadata is also generated.
  • If a method has a snippet, that snippet is included in the method docstring.

Other changes:

  • Removed the method docstring in the code snippet file (line right below the method definition) since the same text is already in the comment block at the top of the file.
  • Removed the concept of a "standalone" sample. All generated samples are expected to be standalone. When someone wants a smaller portion of the sample (e.g., request initialization only) they should fetch it from the file by looking up the line numbers in the snippet metadata file.

Other Notes:

  • It doesn't look like it's possible to do type annotations with _pb2 types, so those are annotated as Any. It is possible to do mypy checking with https://github.com/dropbox/mypy-protobuf, but I think it will be easier make that change in a separate PR.
  • There are a lot of golden file updates, this range of commits has most of the generator and test changes.

@busunkim96 busunkim96 marked this pull request as ready for review January 13, 2022 18:08
@busunkim96 busunkim96 requested review from a team as code owners January 13, 2022 18:08
Copy link
Contributor

@software-dov software-dov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! Just a few inline questions, no need to block submission.

# output_files[manifest_fname] = CodeGeneratorResponse.File(
# content=manifest_doc.render(), name=manifest_fname
# )
if len(index.metadata_index.snippets) > 0:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit:

if index.metadata_index.snippets:

# NOTE(busunkim): Not all fields are yet populated in the snippet metadata.
# Expected filename: snippet_metadata_{metadata_schema_version}_{apishortname}_{apiversion}.json
snippet_metadata_path = str(pathlib.Path(
out_dir) / f"snippet_metadata_v1_{api_schema.naming.name}_{api_schema.naming.version}.json").lower()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To clarify: the v1 here is about the snippet metadata itself, correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes! Amanda left a note below saying the metadata will not be versioned for now though, so I'll go ahead and remove it.

Comment on lines 212 to 213
# NOTE(busunkim): Not all fields are yet populated in the snippet metadata.
# Expected filename: snippet_metadata_{metadata_schema_version}_{apishortname}_{apiversion}.json
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this comment still relevant, or is it cruft?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep still relevant, there's a lot of fields that are not yet filled out.

@@ -324,8 +325,8 @@ def _get_file(
template_name: str,
*,
opts: Options,
api_schema=api.API,
**context: Mapping,
api_schema: api.API,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doh! Good catch.

Comment on lines 925 to 926
raise types.InvalidConfig(
"Sample config is invalid", valid)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Outside the scope of the review, but taking a second look, this isn't very helpful. Do you think it would be better to include the config or the filepath tothe config here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Modified the error message to look like this:

                if not valid:
                    raise types.InvalidConfig(
                        "Sample config in '{}' is invalid\n\n{}".format(config_fpath, cfg), valid)

@@ -1062,7 +1055,7 @@ def generate_sample_specs(api_schema: api.API, *, opts) -> Generator[Dict[str, A
yield spec


def generate_sample(sample, api_schema, sample_template: jinja2.Template) -> str:
def generate_sample(sample, api_schema, sample_template: jinja2.Template) -> Tuple[str, Any]:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why use Any as the type of the second second element instead of the real type? Is it related to the # type: ignore a few lines down?

Copy link
Contributor Author

@busunkim96 busunkim96 Jan 14, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, since the type is ignored I cannot use it in an annotation. I learned about mypy-protobuf from a PR with Tres though, so I'll open a separate PR to start type checking all the protobuf types.

@@ -207,6 +207,13 @@ class {{ service.async_client_name }}:
{% endif %}
r"""{{ method.meta.doc|rst(width=72, indent=8) }}

.. code-block::
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the .. code-block:: be inside the if statement a few lines below?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh good catch, this would have created a lot of noise in the regen PRs.

@@ -210,6 +210,31 @@ async def export_assets(self,
the export operation result. For regular-size resource parent,
the export operation usually finishes within 5 minutes.


.. code-block::
from google.cloud import asset_v1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This indentation is a little unfortunate, but we can probably ignore it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hrrm I didn't notice this earlier, I'll try poking at the template to see where this is coming from.

Copy link

@amanda-tarafa amanda-tarafa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left a couple of comments on the generated metadata file, but it looks good!

@@ -0,0 +1,1048 @@
{

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the time beeing, we dropped versioning of the metadata scheam so you can drop the first v1 here.
Also, we are doing, where possible, snippet_metadata_{protopackage}.json, although the real important part is snippet_metadata*.json as the rest of the name is not going to be used to identify anything automatically.

"clientMethod": {
"async": true,
"method": {
"fullName": "AnalyzeIamPolicyLongrunning",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fullName shuld be the RPC method name qualified by the proto package and the service name
This looks more like shortName.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack, I'll switch this out for shortName.

"method": {
"fullName": "AnalyzeIamPolicyLongrunning",
"service": {
"shortName": "AssetService"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And fullName would be the service name qualified by the proto package.
Fine if this is one the ones you are adding later.

}
}
},
"file": "samples/generated_samples/cloudasset_generated_asset_v1_asset_service_analyze_iam_policy_longrunning_async.py",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This path should be relative to the location of this metadata file. Just double checking that's the case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah it's currently relative to the library root. I'll remove the samples/generated_samples since the metadata sits in the same directory as the snippets.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants