Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
557df5b
Add Clone derive to Scope enum
OMGeeky Oct 21, 2023
bcacb79
make regen-apis
OMGeeky Oct 21, 2023
5b2da03
restructure templates to use modules, so it's not just one big file
OMGeeky Oct 21, 2023
b09392b
cleanup python usages
OMGeeky Oct 21, 2023
ec6083f
make regen-apis
OMGeeky Oct 21, 2023
d45d669
move scope_enum to own mako file
OMGeeky Oct 21, 2023
a4b0f56
a building version of the enums-change (cli is broken).
OMGeeky Oct 22, 2023
4a258a5
make regen-apis
OMGeeky Oct 23, 2023
a333ae0
change enums visibility
OMGeeky Oct 23, 2023
bf15c96
make youtube3
OMGeeky Oct 23, 2023
ef57420
fix enum result parsing
OMGeeky Oct 29, 2023
8ba5aba
fix some items not having parameters crashing the script
OMGeeky Nov 10, 2023
55222f3
add generated enums.rs to drive3
OMGeeky Nov 10, 2023
90ac610
make regen-apis
OMGeeky Oct 21, 2023
3c93d7f
restructure templates to use modules, so it's not just one big file
OMGeeky Oct 21, 2023
95e10c9
cleanup python usages
OMGeeky Oct 21, 2023
665da6a
make regen-apis
OMGeeky Oct 21, 2023
cf0248f
move scope_enum to own mako file
OMGeeky Oct 21, 2023
8fc78fe
a building version of the enums-change (cli is broken).
OMGeeky Oct 22, 2023
c356d5f
make regen-apis
OMGeeky Oct 23, 2023
c034d75
change enums visibility
OMGeeky Oct 23, 2023
7b6aa6a
make youtube3
OMGeeky Oct 23, 2023
e5a85b3
fix enum result parsing
OMGeeky Oct 29, 2023
5a40cf1
fix some items not having parameters crashing the script
OMGeeky Nov 10, 2023
4167ddd
add generated enums.rs to drive3
OMGeeky Nov 10, 2023
85133fa
fix warnings
OMGeeky May 12, 2024
988ebe8
remove generated libs
OMGeeky May 12, 2024
5bfd23d
fix some errors where some stuff does not exist
OMGeeky May 12, 2024
d39652d
add test for wrong name
OMGeeky May 12, 2024
41049ed
implement workaround for status singular mistake
OMGeeky May 13, 2024
e8e1722
fix wrong value for enums
OMGeeky May 13, 2024
9719826
add impl to try to convert strings into the enum
OMGeeky May 13, 2024
d9a7fcc
fix conflicting implementation error for TryFrom
OMGeeky May 13, 2024
3092fef
add comment
OMGeeky May 13, 2024
d1d2e99
remove changes to gen
OMGeeky May 13, 2024
b6c063a
fix some enums getting wrong names
OMGeeky May 14, 2024
5dd05e4
fix enums not finding nested variants etc
OMGeeky May 14, 2024
3e27f63
generate random values in documentation correctly
OMGeeky May 16, 2024
e7cce53
add use for all enums to make the docs build
OMGeeky May 16, 2024
0f1e013
add regions around enums for better overview
OMGeeky May 16, 2024
52d2e89
reposition doc usage to better fit other usages
OMGeeky May 16, 2024
f528cb9
remove leftover print
OMGeeky May 16, 2024
3b667bb
cleanup some old stuff
OMGeeky May 16, 2024
c4c38e9
fix dict access errors while running test
OMGeeky May 16, 2024
2d9be85
Revert "fix dict access errors while running test"
OMGeeky May 16, 2024
04845a8
fix build error: TypeError: 'DictObject' object is not callable
OMGeeky May 16, 2024
b9b8cec
Reapply "fix dict access errors while running test"
OMGeeky May 16, 2024
488c81a
fix usage
OMGeeky May 16, 2024
51728ff
correctly handle multiline descriptions for enums
OMGeeky May 16, 2024
3455436
fix enum type not being wrapped as Vec if repeated
OMGeeky May 17, 2024
006ce57
Revert "Reapply "fix dict access errors while running test""
OMGeeky May 17, 2024
cb9d6ad
Use DictObject in tests
OMGeeky May 17, 2024
12d2398
remove writing file from test that was probably only a temporary debu…
OMGeeky May 17, 2024
88d8495
remove ambiguity in TryFrom implementation
OMGeeky May 17, 2024
cb7d92a
put module `api` in api.rs like before instead of `api/mod.rs`
OMGeeky May 17, 2024
c04fa3f
fix error where default for enum was not properly detected
OMGeeky May 17, 2024
f1a5835
add `bigtableadmin2` to blacklist because of recursive type
OMGeeky May 18, 2024
ef00af9
fix one problem in the CLIs that try to use enums
OMGeeky May 18, 2024
56643c8
improve enum docs
OMGeeky May 18, 2024
ad07a13
make `cargo doc` a bit happier about links
OMGeeky May 18, 2024
92ad312
improve some names
OMGeeky May 18, 2024
a6d4fdd
fix enum being generated multiple times in some cases
OMGeeky May 18, 2024
01aa609
fix wrong blacklist from earlier (bigtableadmin)
OMGeeky May 18, 2024
af71b9e
temporary disable links surrounding for `cargo doc`
OMGeeky May 18, 2024
dc91100
fix some more errors in the cli
OMGeeky May 19, 2024
0946a3b
specify full type path for std lib usages
OMGeeky May 31, 2024
d80498a
make enums their own class in python to better handle variants where …
OMGeeky May 31, 2024
04e188f
fix pycharm hints
OMGeeky May 31, 2024
f07db4c
improve warn outputs
OMGeeky May 31, 2024
70b1d1e
Revert part of "fix pycharm hints" that broke something
OMGeeky May 31, 2024
0a092ae
whitespace change to trigger check
OMGeeky Mar 20, 2025
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
File renamed without changes.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[workspace]

resolver = "2"
members = [
"google-apis-common",
"google-clis-common",
"src/rust/preproc"
]
exclude = ["gen"]
exclude = ["gen"]
2 changes: 2 additions & 0 deletions etc/api/shared.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ api:
- analyticsadmin
# resursive type
- bigquery
# resursive type
- bigtableadmin
# redefinition of `Scope`
- binaryauthorization
# ampersand & in type name
Expand Down
12 changes: 12 additions & 0 deletions etc/api/type-api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,18 @@ make:
output_dir: src
- source: api.rs
output_dir: src
- source: api/utilities.rs
output_dir: src
- source: api/hub.rs
output_dir: src
- source: api/method_builders.rs
output_dir: src
- source: api/schemas.rs
output_dir: src
- source: api/call_builders.rs
output_dir: src
- source: api/enums.rs
output_dir: src
cargo:
keywords: [protocol, web, api]
doc_base_url: https://docs.rs
Expand Down
192 changes: 192 additions & 0 deletions src/generator/lib/__tests__/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
from copy import deepcopy
import sys

# COPY FROM `mako-render` TO CONVERT DATA FOR TESTS

# From https://github.com/Byron/bcore
class DictObject(object):

"""An object which wraps a dictionary to allow object.key access.
If the source dictionary doesn't contain any sub-dictionaries, the input
dict will be referenced. Otherwise it will be copied.

An attribute error is raised if a value is not accessible.

Please note that you cannot access dict keys which are not valid attribute names.
"""

_default_dict = dict()
_unpackable_types = (dict, tuple, list)

def __init__(self, indict=_default_dict):
"""Initialize this instance from an input dictionary. If it contains other dictionaries, those will
trigger their parent dictionaries to be copied, as they will be used as DictObject themselves and
placed in the copy accordingly.
NOTE: other DictObjects are used by reference. Generally, this type tries to perform the least
amount of copying possible."""
if indict is self._default_dict:
return
# end handle default instantiation, which makes us empty
if isinstance(indict, DictObject):
self.__dict__ = indict.__dict__
return
# END handle special case, be a reference
dct = indict
for key, val in dct.items():
if isinstance(val, self._unpackable_types):
dct = None
break
# END for each key-value pair

if dct is None:
dct = dict(indict)

def unpack(val):
"""unpack helper"""
if isinstance(val, dict):
val = DictObject(val)
elif isinstance(val, (tuple, list)):
val = type(val)(unpack(item) for item in val)
return val
# END unpack
for key, val in dct.items():
dct[key] = unpack(val)
# END for each k,v pair
# END handle recursive copy
self.__dict__ = dct

def __str__(self):
return str(self.__dict__)

def __repr__(self):
return repr(self.__dict__)

def __getitem__(self, name):
try:
return getattr(self, name)
except AttributeError:
raise KeyError(name)
# end convert exception

def __setitem__(self, name, value):
setattr(self, name, value)

def __contains__(self, name):
return name in self.__dict__

def __len__(self):
return len(self.__dict__)

def __iter__(self):
return iter(self.__dict__)

def __eq__(self, other):
"""Compares a possibly expensive comparison"""
if isinstance(other, DictObject):
# EXPENSIVE !
return self.to_dict() == other.to_dict()
elif isinstance(other, dict):
return self.to_dict() == other
# end handle type of other
return self is other

def update(self, other, **kwargs):
"""Similar to dict.update"""
items = other
if hasattr(other, 'keys'):
items = other.items()
for item_list in (items, kwargs.items()):
for k, v in item_list:
setattr(self, k, v)
# end for each item list

def to_dict(self, recursive=False):
"""@return ourselves as normal dict
@param recursive if True, a recursive copy will be returned if required."""
if recursive:
def obtain_needs_copy(value):
"""figure out if a copy is required"""
if isinstance(value, DictObject):
return True
if isinstance(value, (tuple, list, set)):
for item in value:
if obtain_needs_copy(item):
return True
# end check needs copy
# end for each item in value
# end if instance is iterable
return False
# end check needs copy

def unpack(val):
"""unpack val recursively and copy it gently"""
if isinstance(val, DictObject):
val = val.to_dict(recursive)
elif isinstance(val, (tuple, list, set)):
val = type(val)(unpack(item) for item in val)
# end handle type resolution
return val
# end unpack

needs_copy = False
for value in self.__dict__.values():
if obtain_needs_copy(value):
needs_copy = True
break
# end check value
# END for each value

if needs_copy:
new_dict = dict()
for key, val in self.__dict__.items():
new_dict[key] = unpack(val)
# END for each key, value pair
return new_dict
# else:
# just fall through and return ourselves as dictionary

# END handle recursion
return self.__dict__

def copy(self):
"""@return a (deep) copy of self"""
return type(self)(self.to_dict())

def clone(self):
"""@return a deep copy of this dict. This onyl means that the key-sets are independent. However, the
values are still shared, which matters in case of lists for instance"""
return type(self)(deepcopy(self.to_dict(recursive=True)))

def inversed_dict(self):
"""@return new dictionary which uses this dicts keys as values, and values as keys
@note duplicate values will result in just a single key, effectively drupping items.
Use this only if you have unique key-value pairs"""
return dict(list(zip(list(self.__dict__.values()), list(self.__dict__.keys()))))

def get(self, name, default=None):
"""as dict.get"""
return self.__dict__.get(name, default)

def keys(self):
"""as dict.keys"""
return list(self.__dict__.keys())

def values(self):
"""as dict.values"""
return list(self.__dict__.values())

def items(self):
"""as dict.items"""
return list(self.__dict__.items())

def _items(self):
"""as dict.items, avoiding name clashes"""
return list(self.__dict__.items())

def pop(self, key, default=sys):
"""as dict.pop"""
if default is sys:
return self.__dict__.pop(key)
else:
return self.__dict__.pop(key, default)
# end assure semantics are kept
43 changes: 21 additions & 22 deletions src/generator/lib/__tests__/context_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from pprint import pprint

from generator.lib.util import new_context
from . import DictObject
from .test_data.discovery_document import DISCOVERY_DOC


Expand All @@ -11,7 +12,7 @@ def setUp(self):
self.discovery_doc = json.loads(DISCOVERY_DOC)

def test_sta_map(self):
expected = {
expected = DictObject({
"AddEnrichmentToAlbumRequest": {
"photoslibrary.albums.addEnrichment": ["request"]
},
Expand Down Expand Up @@ -59,16 +60,16 @@ def test_sta_map(self):
"photoslibrary.sharedAlbums.join": [],
"photoslibrary.sharedAlbums.list": [],
},
}
})

schemas = self.discovery_doc["schemas"]
resources = self.discovery_doc["resources"]
schemas = DictObject(self.discovery_doc["schemas"])
resources = DictObject(self.discovery_doc["resources"])

actual = new_context(schemas, resources).sta_map
self.assertEqual(actual, expected)

def test_fqan_map(self):
expected = {
expected = DictObject({
"photoslibrary.mediaItems.batchCreate": {
"flatPath": "v1/mediaItems:batchCreate",
"path": "v1/mediaItems:batchCreate",
Expand Down Expand Up @@ -345,44 +346,42 @@ def test_fqan_map(self):
"path": "v1/albums/{+albumId}:share",
"id": "photoslibrary.albums.share",
},
}
})

schemas = self.discovery_doc["schemas"]
resources = self.discovery_doc["resources"]
schemas = DictObject(self.discovery_doc["schemas"])
resources = DictObject(self.discovery_doc["resources"])

actual = new_context(schemas, resources).fqan_map
self.assertEqual(actual, expected)

def test_rta_map(self):
expected = {
expected = DictObject({
"mediaItems": ["batchCreate", "search", "list", "get"],
"sharedAlbums": ["get", "list", "join"],
"albums": ["list", "get", "addEnrichment", "create", "share"],
}
})

schemas = self.discovery_doc["schemas"]
resources = self.discovery_doc["resources"]
schemas = DictObject(self.discovery_doc["schemas"])
resources = DictObject(self.discovery_doc["resources"])

actual = new_context(schemas, resources).rta_map
self.assertEqual(actual, expected)

def test_rtc_map(self):
expected = {
expected = DictObject({
"mediaItems": "photoslibrary",
"sharedAlbums": "photoslibrary",
"albums": "photoslibrary",
}
})

schemas = self.discovery_doc["schemas"]
resources = self.discovery_doc["resources"]
schemas = DictObject(self.discovery_doc["schemas"])
resources = DictObject(self.discovery_doc["resources"])

actual = new_context(schemas, resources).rtc_map
with open("actual.json", "w") as aj:
json.dump(actual, aj, indent=4)
self.assertEqual(actual, expected)

def test_schemas(self):
expected = {
expected = DictObject({
"EnrichmentItem": {
"description": "An enrichment item.",
"type": "object",
Expand Down Expand Up @@ -1360,10 +1359,10 @@ def test_schemas(self):
"used_by": ["MediaMetadata"],
"parents": [],
},
}
})

schemas = self.discovery_doc["schemas"]
resources = self.discovery_doc["resources"]
schemas = DictObject(self.discovery_doc["schemas"])
resources = DictObject(self.discovery_doc["resources"])

actual = new_context(schemas, resources).schemas
self.assertEqual(actual, expected)
27 changes: 26 additions & 1 deletion src/generator/lib/__tests__/util_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,21 @@
import unittest
import json

from generator.lib.util import to_api_version, library_name, re_find_replacements, to_rust_type
from generator.lib.util import (to_api_version, library_name, re_find_replacements, to_rust_type,
singular, use_automatic_links_in_rust_doc_comment)

from src.generator.lib.util import inflection
from .test_data.discovery_document import DISCOVERY_DOC


class UtilsTest(unittest.TestCase):
def test_singular_status(self):
singular_word = singular('Status')
self.assertEqual(singular_word, 'Status')

def test_singular_upload_status(self):
singular_word = singular('UploadStatus')
self.assertEqual(singular_word, 'UploadStatus')

def test_to_version_ok(self):
for v, want in (('v1.3', '1d3'),
Expand Down Expand Up @@ -106,6 +116,21 @@ def test_to_rust_type(self):
rust_type = to_rust_type(schemas, class_name, property_name, property_value, allow_optionals=True)
self.assertEqual(rust_type, 'Option<Vec<HashMap<String, json::Value>>>')

def test_url_in_doc(self):
s = "This is a documentation with a link to https://goo.gl/TgSFN2 which is a link to some more info"
expected = "This is a documentation with a link to <https://goo.gl/TgSFN2> which is a link to some more info"
result = use_automatic_links_in_rust_doc_comment(s)
# self.assertEqual(result, expected)
s = "/// Creates multiple new sessions. This API can be used to initialize a session cache on the clients. See https://goo.gl/TgSFN2 for best practices on session cache management."
expected = "/// Creates multiple new sessions. This API can be used to initialize a session cache on the clients. See <https://goo.gl/TgSFN2> for best practices on session cache management."
result = use_automatic_links_in_rust_doc_comment(s)
# self.assertEqual(result, expected)

def test_url_in_doc_ending_with_dot(self):
s = "This is a documentation with a link to https://goo.gl/TgSFN2."
expected = "This is a documentation with a link to <https://goo.gl/TgSFN2>."
result = use_automatic_links_in_rust_doc_comment(s)
# self.assertEqual(result, expected)

def main():
unittest.main()
Expand Down
Loading