Skip to content

Commit 76390ac

Browse files
authored
Automate manual changes to stub files (#64)
1 parent 0663ab0 commit 76390ac

File tree

8 files changed

+186
-7
lines changed

8 files changed

+186
-7
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@
1515
!/create_types_pyi.py
1616
!/stubdefaulter.sh
1717
!/stubgen.py
18+
!/fixup_versions.py
1819
__pycache__

fixup_versions.py

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
import re
2+
3+
from google.ads.googleads import client
4+
5+
sorted_versions = sorted(client._VALID_API_VERSIONS)
6+
7+
8+
def replace_between_markers(content, marker_prefix, marker_suffix, replacement):
9+
replacement = "\n".join([marker_prefix, replacement, marker_suffix])
10+
new_content = re.sub(
11+
f"{marker_prefix}.+{marker_suffix}",
12+
replacement,
13+
content,
14+
flags=re.DOTALL,
15+
)
16+
return new_content
17+
18+
19+
def fix_interceptors():
20+
interceptor_imports = []
21+
interceptor_request_types = []
22+
23+
for version in sorted_versions:
24+
interceptor_imports.append(f"import google.ads.googleads.{version}.services")
25+
interceptor_request_types.append(
26+
f"google.ads.googleads.{version}.services.SearchGoogleAdsRequest"
27+
)
28+
interceptor_request_types.append(
29+
f"google.ads.googleads.{version}.services.SearchGoogleAdsStreamRequest"
30+
)
31+
32+
interceptor_imports_prefix = "# Autogenerated imports"
33+
interceptor_imports_suffix = "# End of autogenerated imports"
34+
interceptor_request_types_prefix = "# Autogenerated request types"
35+
interceptor_request_types_suffix = "# End of autogenerated request types"
36+
37+
interceptor_import_replacement = "\n".join(interceptor_imports)
38+
interceptor_request_types_replacement = ",\n".join(interceptor_request_types)
39+
40+
interceptor_files = [
41+
"google-stubs/ads/googleads/interceptors/exception_interceptor.pyi",
42+
"google-stubs/ads/googleads/interceptors/logging_interceptor.pyi",
43+
"google-stubs/ads/googleads/interceptors/metadata_interceptor.pyi",
44+
]
45+
46+
for interceptor_file in interceptor_files:
47+
with open(interceptor_file) as f:
48+
interceptor_pyi = f.read()
49+
interceptor_pyi = replace_between_markers(
50+
interceptor_pyi,
51+
interceptor_imports_prefix,
52+
interceptor_imports_suffix,
53+
interceptor_import_replacement,
54+
)
55+
interceptor_pyi = replace_between_markers(
56+
interceptor_pyi,
57+
interceptor_request_types_prefix,
58+
interceptor_request_types_suffix,
59+
interceptor_request_types_replacement,
60+
)
61+
with open(interceptor_file, mode="w") as f:
62+
f.write(interceptor_pyi)
63+
64+
65+
def fix_errors():
66+
error_imports = []
67+
error_types = []
68+
69+
for version in sorted_versions:
70+
error_imports.append(
71+
f"from google.ads.googleads.{version}.errors import GoogleAdsFailure as GoogleAdsFailure{version.upper()}"
72+
)
73+
error_types.append(f"GoogleAdsFailure{version.upper()}")
74+
75+
error_imports_prefix = "# Autogenerated imports"
76+
error_imports_suffix = "# End of autogenerated imports"
77+
error_types_prefix = "# Autogenerated failure types"
78+
error_types_suffix = "# End of autogenerated failure types"
79+
80+
error_imports_replacement = "\n".join(error_imports)
81+
error_types_replacement = " | ".join(error_types)
82+
83+
with open("google-stubs/ads/googleads/errors.pyi") as f:
84+
errors_pyi = f.read()
85+
86+
errors_pyi = replace_between_markers(
87+
errors_pyi,
88+
error_imports_prefix,
89+
error_imports_suffix,
90+
error_imports_replacement,
91+
)
92+
errors_pyi = replace_between_markers(
93+
errors_pyi,
94+
error_types_prefix,
95+
error_types_suffix,
96+
error_types_replacement,
97+
)
98+
with open("google-stubs/ads/googleads/errors.pyi", mode="w") as f:
99+
f.write(errors_pyi)
100+
101+
102+
def fix_client():
103+
default_version_import = (
104+
f"from google.ads.googleads import {client._DEFAULT_VERSION}"
105+
)
106+
107+
default_version_import_prefix = "# Autogenerated import of latest version"
108+
default_version_import_suffix = "# End of autogenerated import of latest version"
109+
110+
with open("google-stubs/ads/googleads/client.pyi") as f:
111+
client_pyi = f.read()
112+
113+
client_pyi = replace_between_markers(
114+
client_pyi,
115+
default_version_import_prefix,
116+
default_version_import_suffix,
117+
default_version_import,
118+
)
119+
120+
version_literals = []
121+
for version in sorted_versions:
122+
version_literals.append(f'_{version.upper()} = Literal["{version}"]')
123+
version_literals.append(
124+
f"_V = {' | '.join([f'_{version.upper()}' for version in sorted_versions])}"
125+
)
126+
127+
version_literals_prefix = "# Autogenerated version literals"
128+
version_literals_suffix = "# End of autogenerated version literals"
129+
130+
version_literals_replacement = "\n".join(version_literals)
131+
132+
client_pyi = replace_between_markers(
133+
client_pyi,
134+
version_literals_prefix,
135+
version_literals_suffix,
136+
version_literals_replacement,
137+
)
138+
139+
get_type_overload = f' def get_type(cls, name: str, version: _V = "{client._DEFAULT_VERSION}") -> Any: ...'
140+
141+
get_type_overload_prefix = " # Autogenerated get_type overload"
142+
get_type_overload_suffix = " # End of autogenerated get_type overload"
143+
144+
client_pyi = replace_between_markers(
145+
client_pyi,
146+
get_type_overload_prefix,
147+
get_type_overload_suffix,
148+
get_type_overload,
149+
)
150+
151+
with open("google-stubs/ads/googleads/client.pyi", mode="w") as f:
152+
f.write(client_pyi)
153+
154+
155+
fix_interceptors()
156+
fix_errors()
157+
fix_client()

gen.sh

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,8 @@
33
set -eou pipefail
44
shopt -s globstar
55

6-
# Manual: Clone https://github.com/googleads/google-ads-python
7-
# Manual: Update google-ads-python dependency
8-
# Manual: Update the following to match the API versions:
9-
# - GoogleAdsFailure in errors.pyi
10-
# - _V, imports and get_type default in client.pyi
11-
# - _Request in exception_interceptor.pyi, logging_interceptor.pyi and metadata_interceptor.pyi
6+
uv remove google-ads && uv add google-ads
7+
git clone https://github.com/googleads/google-ads-python.git || true
128
cd google-ads-python
139
git restore .
1410
git pull
@@ -21,8 +17,9 @@ uv run python stubgen.py
2117
uv run python create_type_stubs.py
2218
uv run python create_enums.py
2319
uv run python create_service_overloads.py
20+
uv run python fixup_versions.py
2421
./stubdefaulter.sh
25-
mv .gitignore gitignore
22+
mv .gitignore gitignore # Workaround for ruff's handling of gitignore files with whitelisting.
2623
uv run ruff check google-stubs --fix --unsafe-fixes
2724
uv run ruff format google-stubs
2825
mv gitignore .gitignore

google-stubs/ads/googleads/client.pyi

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,14 +437,19 @@ import google.ads.googleads.v23.services.services.user_list_customer_type_servic
437437
import google.ads.googleads.v23.services.services.user_list_service
438438

439439
# End of autogenerated service imports
440+
# Autogenerated import of latest version
440441
from google.ads.googleads import v23
442+
443+
# End of autogenerated import of latest version
441444
from google.ads.googleads.config import _ConfigDataUnparsed
442445

446+
# Autogenerated version literals
443447
_V20 = Literal["v20"]
444448
_V21 = Literal["v21"]
445449
_V22 = Literal["v22"]
446450
_V23 = Literal["v23"]
447451
_V = _V20 | _V21 | _V22 | _V23
452+
# End of autogenerated version literals
448453

449454
class _EnumGetter:
450455
# Autogenerated enums
@@ -1303,7 +1308,9 @@ class GoogleAdsClient:
13031308
use_proto_plus: bool = False,
13041309
use_cloud_org_for_api_access: bool | None = None,
13051310
) -> None: ...
1311+
# Autogenerated get_type overload
13061312
def get_type(cls, name: str, version: _V = "v23") -> Any: ...
1313+
# End of autogenerated get_type overload
13071314
# Autogenerated service overloads
13081315
@overload
13091316
def get_service(

google-stubs/ads/googleads/errors.pyi

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
import grpc
22

3+
# Autogenerated imports
34
from google.ads.googleads.v20.errors import GoogleAdsFailure as GoogleAdsFailureV20
45
from google.ads.googleads.v21.errors import GoogleAdsFailure as GoogleAdsFailureV21
56
from google.ads.googleads.v22.errors import GoogleAdsFailure as GoogleAdsFailureV22
67
from google.ads.googleads.v23.errors import GoogleAdsFailure as GoogleAdsFailureV23
78

9+
# End of autogenerated imports
10+
811
GoogleAdsFailure = (
12+
# Autogenerated failure types
913
GoogleAdsFailureV20
1014
| GoogleAdsFailureV21
1115
| GoogleAdsFailureV22
1216
| GoogleAdsFailureV23
17+
# End of autogenerated failure types
1318
)
1419

1520
class GoogleAdsException(Exception):

google-stubs/ads/googleads/interceptors/exception_interceptor.pyi

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,18 @@ from typing import TypeVar
33

44
import grpc
55

6+
# Autogenerated imports
67
import google.ads.googleads.v20.services
78
import google.ads.googleads.v21.services
89
import google.ads.googleads.v22.services
910
import google.ads.googleads.v23.services
1011

12+
# End of autogenerated imports
1113
from .interceptor import Interceptor
1214

1315
_Request = TypeVar(
1416
"_Request",
17+
# Autogenerated request types
1518
google.ads.googleads.v20.services.SearchGoogleAdsRequest,
1619
google.ads.googleads.v20.services.SearchGoogleAdsStreamRequest,
1720
google.ads.googleads.v21.services.SearchGoogleAdsRequest,
@@ -20,6 +23,7 @@ _Request = TypeVar(
2023
google.ads.googleads.v22.services.SearchGoogleAdsStreamRequest,
2124
google.ads.googleads.v23.services.SearchGoogleAdsRequest,
2225
google.ads.googleads.v23.services.SearchGoogleAdsStreamRequest,
26+
# End of autogenerated request types
2327
)
2428
_Response = TypeVar("_Response")
2529

google-stubs/ads/googleads/interceptors/logging_interceptor.pyi

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,18 @@ from typing import TypeVar
55
import grpc
66
from google.protobuf.message import Message
77

8+
# Autogenerated imports
89
import google.ads.googleads.v20.services
910
import google.ads.googleads.v21.services
1011
import google.ads.googleads.v22.services
1112
import google.ads.googleads.v23.services
1213

14+
# End of autogenerated imports
1315
from .interceptor import Interceptor
1416

1517
_Request = TypeVar(
1618
"_Request",
19+
# Autogenerated request types
1720
google.ads.googleads.v20.services.SearchGoogleAdsRequest,
1821
google.ads.googleads.v20.services.SearchGoogleAdsStreamRequest,
1922
google.ads.googleads.v21.services.SearchGoogleAdsRequest,
@@ -22,6 +25,7 @@ _Request = TypeVar(
2225
google.ads.googleads.v22.services.SearchGoogleAdsStreamRequest,
2326
google.ads.googleads.v23.services.SearchGoogleAdsRequest,
2427
google.ads.googleads.v23.services.SearchGoogleAdsStreamRequest,
28+
# End of autogenerated request types
2529
)
2630
_Response = TypeVar("_Response")
2731

google-stubs/ads/googleads/interceptors/metadata_interceptor.pyi

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,18 @@ from typing import TypeVar
33

44
import grpc
55

6+
# Autogenerated imports
67
import google.ads.googleads.v20.services
78
import google.ads.googleads.v21.services
89
import google.ads.googleads.v22.services
910
import google.ads.googleads.v23.services
1011

12+
# End of autogenerated imports
1113
from .interceptor import Interceptor
1214

1315
_Request = TypeVar(
1416
"_Request",
17+
# Autogenerated request types
1518
google.ads.googleads.v20.services.SearchGoogleAdsRequest,
1619
google.ads.googleads.v20.services.SearchGoogleAdsStreamRequest,
1720
google.ads.googleads.v21.services.SearchGoogleAdsRequest,
@@ -20,6 +23,7 @@ _Request = TypeVar(
2023
google.ads.googleads.v22.services.SearchGoogleAdsStreamRequest,
2124
google.ads.googleads.v23.services.SearchGoogleAdsRequest,
2225
google.ads.googleads.v23.services.SearchGoogleAdsStreamRequest,
26+
# End of autogenerated request types
2327
)
2428
_Response = TypeVar("_Response")
2529

0 commit comments

Comments
 (0)