Skip to content
Open
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 @@ -6,6 +6,32 @@ from {{package_path}} import gapic_version as package_version

__version__ = package_version.__version__

{% set versioned_package_path = (api.naming.module_namespace + (api.naming.versioned_module_name,))|join('.') %}
# PEP 0810: Explicit Lazy Imports
# Python 3.15+ natively intercepts and defers these imports.
# Developers can disable this behavior and force eager imports.
# For more information, see:
# https://docs.python.org/3.15/library/sys.html#sys.set_lazy_imports_filter
# Older Python versions safely ignore this variable.
__lazy_modules__ = {
{% filter sort_lines | indent(4, true) -%}
{% if api.subpackages -%}
"{{versioned_package_path}}",
{% endif -%}
{% for service in api.services.values()
if service.meta.address.subpackage == api.subpackage_view -%}
"{{versioned_package_path}}.services.{{ service.name|snake_case }}.client",
{% if 'grpc' in opts.transport -%}
"{{versioned_package_path}}.services.{{ service.name|snake_case }}.async_client",
{% endif -%}
{% endfor -%}
{% for proto in api.protos.values()
if proto.meta.address.subpackage == api.subpackage_view and (proto.messages or proto.enums) -%}
"{{versioned_package_path}}.types.{{ proto.module_name }}",
{% endfor -%}
{% endfilter %}
}
Comment thread
GouthamMahesh marked this conversation as resolved.
Resolved

{# Import subpackages. -#}
{% for subpackage in api.subpackages|dictsort %}
from {% if api.naming.module_namespace %}{{ api.naming.module_namespace|join('.') }}.{% endif %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,20 @@

__version__ = package_version.__version__

# PEP 0810: Explicit Lazy Imports
# Python 3.15+ natively intercepts and defers these imports.
# Developers can disable this behavior and force eager imports.
# For more information, see:
# https://docs.python.org/3.15/library/sys.html#sys.set_lazy_imports_filter
# Older Python versions safely ignore this variable.
__lazy_modules__ = {
"google.cloud.asset_v1.services.asset_service.async_client",
"google.cloud.asset_v1.services.asset_service.client",
"google.cloud.asset_v1.types.asset_enrichment_resourceowners",
"google.cloud.asset_v1.types.asset_service",
"google.cloud.asset_v1.types.assets",
}


from google.cloud.asset_v1.services.asset_service.client import AssetServiceClient
from google.cloud.asset_v1.services.asset_service.async_client import AssetServiceAsyncClient
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,18 @@

__version__ = package_version.__version__

# PEP 0810: Explicit Lazy Imports
# Python 3.15+ natively intercepts and defers these imports.
# Developers can disable this behavior and force eager imports.
# For more information, see:
# https://docs.python.org/3.15/library/sys.html#sys.set_lazy_imports_filter
# Older Python versions safely ignore this variable.
__lazy_modules__ = {
"google.iam.credentials_v1.services.iam_credentials.async_client",
"google.iam.credentials_v1.services.iam_credentials.client",
"google.iam.credentials_v1.types.common",
}


from google.iam.credentials_v1.services.iam_credentials.client import IAMCredentialsClient
from google.iam.credentials_v1.services.iam_credentials.async_client import IAMCredentialsAsyncClient
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,25 @@

__version__ = package_version.__version__

# PEP 0810: Explicit Lazy Imports
# Python 3.15+ natively intercepts and defers these imports.
# Developers can disable this behavior and force eager imports.
# For more information, see:
# https://docs.python.org/3.15/library/sys.html#sys.set_lazy_imports_filter
# Older Python versions safely ignore this variable.
__lazy_modules__ = {
"google.cloud.logging_v2.services.config_service_v2.async_client",
"google.cloud.logging_v2.services.config_service_v2.client",
"google.cloud.logging_v2.services.logging_service_v2.async_client",
"google.cloud.logging_v2.services.logging_service_v2.client",
"google.cloud.logging_v2.services.metrics_service_v2.async_client",
"google.cloud.logging_v2.services.metrics_service_v2.client",
"google.cloud.logging_v2.types.log_entry",
"google.cloud.logging_v2.types.logging",
"google.cloud.logging_v2.types.logging_config",
"google.cloud.logging_v2.types.logging_metrics",
}


from google.cloud.logging_v2.services.config_service_v2.client import ConfigServiceV2Client
from google.cloud.logging_v2.services.config_service_v2.async_client import ConfigServiceV2AsyncClient
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,25 @@

__version__ = package_version.__version__

# PEP 0810: Explicit Lazy Imports
# Python 3.15+ natively intercepts and defers these imports.
# Developers can disable this behavior and force eager imports.
# For more information, see:
# https://docs.python.org/3.15/library/sys.html#sys.set_lazy_imports_filter
# Older Python versions safely ignore this variable.
__lazy_modules__ = {
"google.cloud.logging_v2.services.config_service_v2.async_client",
"google.cloud.logging_v2.services.config_service_v2.client",
"google.cloud.logging_v2.services.logging_service_v2.async_client",
"google.cloud.logging_v2.services.logging_service_v2.client",
"google.cloud.logging_v2.services.metrics_service_v2.async_client",
"google.cloud.logging_v2.services.metrics_service_v2.client",
"google.cloud.logging_v2.types.log_entry",
"google.cloud.logging_v2.types.logging",
"google.cloud.logging_v2.types.logging_config",
"google.cloud.logging_v2.types.logging_metrics",
}


from google.cloud.logging_v2.services.config_service_v2.client import BaseConfigServiceV2Client
from google.cloud.logging_v2.services.config_service_v2.async_client import BaseConfigServiceV2AsyncClient
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,18 @@

__version__ = package_version.__version__

# PEP 0810: Explicit Lazy Imports
# Python 3.15+ natively intercepts and defers these imports.
# Developers can disable this behavior and force eager imports.
# For more information, see:
# https://docs.python.org/3.15/library/sys.html#sys.set_lazy_imports_filter
# Older Python versions safely ignore this variable.
__lazy_modules__ = {
"google.cloud.redis_v1.services.cloud_redis.async_client",
"google.cloud.redis_v1.services.cloud_redis.client",
"google.cloud.redis_v1.types.cloud_redis",
}


from google.cloud.redis_v1.services.cloud_redis.client import CloudRedisClient
from google.cloud.redis_v1.services.cloud_redis.async_client import CloudRedisAsyncClient
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,18 @@

__version__ = package_version.__version__

# PEP 0810: Explicit Lazy Imports
# Python 3.15+ natively intercepts and defers these imports.
# Developers can disable this behavior and force eager imports.
# For more information, see:
# https://docs.python.org/3.15/library/sys.html#sys.set_lazy_imports_filter
# Older Python versions safely ignore this variable.
__lazy_modules__ = {
"google.cloud.redis_v1.services.cloud_redis.async_client",
"google.cloud.redis_v1.services.cloud_redis.client",
"google.cloud.redis_v1.types.cloud_redis",
}


from google.cloud.redis_v1.services.cloud_redis.client import CloudRedisClient
from google.cloud.redis_v1.services.cloud_redis.async_client import CloudRedisAsyncClient
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,34 @@

__version__ = package_version.__version__

# PEP 0810: Explicit Lazy Imports
# Python 3.15+ natively intercepts and defers these imports.
# Developers can disable this behavior and force eager imports.
# For more information, see:
# https://docs.python.org/3.15/library/sys.html#sys.set_lazy_imports_filter
# Older Python versions safely ignore this variable.
__lazy_modules__ = {
"google.showcase_v1beta1.services.echo.async_client",
"google.showcase_v1beta1.services.echo.client",
"google.showcase_v1beta1.services.identity.async_client",
"google.showcase_v1beta1.services.identity.client",
"google.showcase_v1beta1.services.messaging.async_client",
"google.showcase_v1beta1.services.messaging.client",
"google.showcase_v1beta1.services.resumable_upload_service.async_client",
"google.showcase_v1beta1.services.resumable_upload_service.client",
"google.showcase_v1beta1.services.sequence_service.async_client",
"google.showcase_v1beta1.services.sequence_service.client",
"google.showcase_v1beta1.services.testing.async_client",
"google.showcase_v1beta1.services.testing.client",
"google.showcase_v1beta1.types.echo",
"google.showcase_v1beta1.types.identity",
"google.showcase_v1beta1.types.messaging",
"google.showcase_v1beta1.types.rest_error",
"google.showcase_v1beta1.types.resumable_upload",
"google.showcase_v1beta1.types.sequence",
"google.showcase_v1beta1.types.testing",
}


from google.showcase_v1beta1.services.echo.client import EchoClient
from google.showcase_v1beta1.services.echo.async_client import EchoAsyncClient
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,19 @@

__version__ = package_version.__version__

# PEP 0810: Explicit Lazy Imports
# Python 3.15+ natively intercepts and defers these imports.
# Developers can disable this behavior and force eager imports.
# For more information, see:
# https://docs.python.org/3.15/library/sys.html#sys.set_lazy_imports_filter
# Older Python versions safely ignore this variable.
__lazy_modules__ = {
"google.cloud.storagebatchoperations_v1.services.storage_batch_operations.async_client",
"google.cloud.storagebatchoperations_v1.services.storage_batch_operations.client",
"google.cloud.storagebatchoperations_v1.types.storage_batch_operations",
"google.cloud.storagebatchoperations_v1.types.storage_batch_operations_types",
}


from google.cloud.storagebatchoperations_v1.services.storage_batch_operations.client import StorageBatchOperationsClient
from google.cloud.storagebatchoperations_v1.services.storage_batch_operations.async_client import StorageBatchOperationsAsyncClient
Expand Down
93 changes: 93 additions & 0 deletions packages/gapic-generator/tests/unit/generator/test_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import ast
import json
import os
import sys
from textwrap import dedent
from types import ModuleType
from typing import Mapping
from unittest import mock

Expand Down Expand Up @@ -341,6 +344,96 @@ def test_get_response_resumable_upload_generates_async_client_and_rest_asyncio()
}


@pytest.mark.parametrize("transport", ("grpc+rest", "rest"))
@pytest.mark.parametrize("namespace", ("google.cloud", "example.api"))
def test_unversioned_package_lazy_imports(transport, namespace):
opts = Options.build(f"transport={transport},python-gapic-namespace={namespace}")
package = "google.cloud.hatstand.v1"
api_schema = api.API.build(
[
descriptor_pb2.FileDescriptorProto(
name="hatstand.proto",
package=package,
service=[descriptor_pb2.ServiceDescriptorProto(name="Hatstand")],
message_type=[descriptor_pb2.DescriptorProto(name="Request")],
),
descriptor_pb2.FileDescriptorProto(
name="state.proto",
package=package,
enum_type=[
descriptor_pb2.EnumDescriptorProto(
name="State",
value=[
descriptor_pb2.EnumValueDescriptorProto(
name="UNKNOWN", number=0
)
],
)
],
),
descriptor_pb2.FileDescriptorProto(name="empty.proto", package=package),
],
package=package,
opts=opts,
)
source = (
generator.Generator(opts)
._env.get_template("%namespace/%name/__init__.py.j2")
.render(api=api_schema, opts=opts)
)
assignments = {
node.targets[0].id: ast.literal_eval(node.value)
for node in ast.parse(source).body
if isinstance(node, ast.Assign)
and node.targets[0].id in ("__lazy_modules__", "__all__")
}
expected_modules = {
f"{namespace}.hatstand_v1.services.hatstand.client",
f"{namespace}.hatstand_v1.types.hatstand",
f"{namespace}.hatstand_v1.types.state",
}
expected_exports = {"HatstandClient", "Request", "State"}
if "grpc" in transport:
expected_modules.add(f"{namespace}.hatstand_v1.services.hatstand.async_client")
expected_exports.add("HatstandAsyncClient")
assert assignments["__lazy_modules__"] == expected_modules
assert set(assignments["__all__"]) == expected_exports

if sys.version_info >= (3, 15):
package_module = ModuleType(f"{namespace}.hatstand")
package_module.gapic_version = ModuleType("gapic_version")
package_module.gapic_version.__version__ = "1.0.0"
with mock.patch.dict(sys.modules, {package_module.__name__: package_module}):
exec(source, package_module.__dict__)
assert expected_modules.isdisjoint(sys.modules)
request_module = ModuleType(f"{namespace}.hatstand_v1.types.hatstand")
request_module.Request = object()
sys.modules[request_module.__name__] = request_module
assert package_module.Request is request_module.Request
assert expected_modules.isdisjoint(sys.modules)


def test_unversioned_lazy_declaration_targets_subpackage_parent():
api_schema = api.API.build(
[
descriptor_pb2.FileDescriptorProto(
name="hatstand.proto", package="google.cloud.hatstand.v1"
),
descriptor_pb2.FileDescriptorProto(
name="common.proto", package="google.cloud.hatstand.v1.common"
),
],
package="google.cloud.hatstand.v1",
)
source = (
make_generator()
._env.get_template("%namespace/%name/__init__.py.j2")
.render(api=api_schema, opts=Options.build(""))
)
assert '"google.cloud.hatstand_v1",' in source
assert '"google.cloud.hatstand_v1.common",' not in source


def test_get_response_enumerates_services():
generator_obj = make_generator()
with mock.patch.object(jinja2.FileSystemLoader, "list_templates") as list_templates:
Expand Down
Loading