nexo-google 0.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 hubagrayuda
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,103 @@
1
+ Metadata-Version: 2.4
2
+ Name: nexo-google
3
+ Version: 0.0.1
4
+ Summary: Google package for Nexo
5
+ Author-email: Agra Bima Yuda <agra@nexmedis.com>
6
+ License: Proprietary
7
+ Requires-Python: >=3.12
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Requires-Dist: aioredis>=2.0.1
11
+ Requires-Dist: annotated-types>=0.7.0
12
+ Requires-Dist: anyio>=4.10.0
13
+ Requires-Dist: async-timeout>=5.0.1
14
+ Requires-Dist: bcrypt>=4.3.0
15
+ Requires-Dist: black>=25.9.0
16
+ Requires-Dist: cachetools>=5.5.2
17
+ Requires-Dist: certifi>=2025.8.3
18
+ Requires-Dist: cffi>=2.0.0
19
+ Requires-Dist: cfgv>=3.4.0
20
+ Requires-Dist: charset-normalizer>=3.4.3
21
+ Requires-Dist: click>=8.3.0
22
+ Requires-Dist: colorama>=0.4.6
23
+ Requires-Dist: cryptography>=46.0.1
24
+ Requires-Dist: distlib>=0.4.0
25
+ Requires-Dist: dnspython>=2.8.0
26
+ Requires-Dist: elastic-transport>=9.1.0
27
+ Requires-Dist: elasticsearch>=9.1.1
28
+ Requires-Dist: fastapi>=0.117.1
29
+ Requires-Dist: filelock>=3.19.1
30
+ Requires-Dist: google-api-core>=2.25.1
31
+ Requires-Dist: google-auth>=2.40.3
32
+ Requires-Dist: google-cloud-appengine-logging>=1.6.2
33
+ Requires-Dist: google-cloud-audit-log>=0.3.2
34
+ Requires-Dist: google-cloud-core>=2.4.3
35
+ Requires-Dist: google-cloud-logging>=3.12.1
36
+ Requires-Dist: google-cloud-pubsub>=2.31.1
37
+ Requires-Dist: google-cloud-secret-manager>=2.24.0
38
+ Requires-Dist: google-cloud-storage>=3.4.0
39
+ Requires-Dist: google-crc32c>=1.7.1
40
+ Requires-Dist: google-resumable-media>=2.7.2
41
+ Requires-Dist: googleapis-common-protos>=1.70.0
42
+ Requires-Dist: greenlet>=3.2.4
43
+ Requires-Dist: grpc-google-iam-v1>=0.14.2
44
+ Requires-Dist: grpcio>=1.75.0
45
+ Requires-Dist: grpcio-status>=1.75.0
46
+ Requires-Dist: h11>=0.16.0
47
+ Requires-Dist: httpcore>=1.0.9
48
+ Requires-Dist: httpx>=0.28.1
49
+ Requires-Dist: identify>=2.6.14
50
+ Requires-Dist: idna>=3.10
51
+ Requires-Dist: importlib_metadata>=8.7.0
52
+ Requires-Dist: iniconfig>=2.1.0
53
+ Requires-Dist: motor>=3.7.1
54
+ Requires-Dist: mypy_extensions>=1.1.0
55
+ Requires-Dist: nexo-crypto>=0.0.2
56
+ Requires-Dist: nexo-database>=0.0.1
57
+ Requires-Dist: nexo-enums>=0.0.2
58
+ Requires-Dist: nexo-logging>=0.0.3
59
+ Requires-Dist: nexo-schemas>=0.0.1
60
+ Requires-Dist: nexo-types>=0.0.2
61
+ Requires-Dist: nexo-utils>=0.0.2
62
+ Requires-Dist: nodeenv>=1.9.1
63
+ Requires-Dist: opentelemetry-api>=1.37.0
64
+ Requires-Dist: opentelemetry-sdk>=1.37.0
65
+ Requires-Dist: opentelemetry-semantic-conventions>=0.58b0
66
+ Requires-Dist: packaging>=25.0
67
+ Requires-Dist: pathspec>=0.12.1
68
+ Requires-Dist: platformdirs>=4.4.0
69
+ Requires-Dist: pluggy>=1.6.0
70
+ Requires-Dist: pre_commit>=4.3.0
71
+ Requires-Dist: proto-plus>=1.26.1
72
+ Requires-Dist: protobuf>=6.32.1
73
+ Requires-Dist: pyasn1>=0.6.1
74
+ Requires-Dist: pyasn1_modules>=0.4.2
75
+ Requires-Dist: pycparser>=2.23
76
+ Requires-Dist: pycryptodome>=3.23.0
77
+ Requires-Dist: pydantic>=2.12.2
78
+ Requires-Dist: pydantic-settings>=2.10.1
79
+ Requires-Dist: pydantic_core>=2.41.4
80
+ Requires-Dist: Pygments>=2.19.2
81
+ Requires-Dist: PyJWT>=2.10.1
82
+ Requires-Dist: pymongo>=4.15.1
83
+ Requires-Dist: pytest>=8.4.2
84
+ Requires-Dist: python-dateutil>=2.9.0.post0
85
+ Requires-Dist: python-dotenv>=1.1.1
86
+ Requires-Dist: pytokens>=0.1.10
87
+ Requires-Dist: PyYAML>=6.0.2
88
+ Requires-Dist: redis>=6.4.0
89
+ Requires-Dist: requests>=2.32.5
90
+ Requires-Dist: rsa>=4.9.1
91
+ Requires-Dist: six>=1.17.0
92
+ Requires-Dist: sniffio>=1.3.1
93
+ Requires-Dist: SQLAlchemy>=2.0.44
94
+ Requires-Dist: starlette>=0.48.0
95
+ Requires-Dist: typing-inspection>=0.4.2
96
+ Requires-Dist: typing_extensions>=4.15.0
97
+ Requires-Dist: ua-parser>=1.0.1
98
+ Requires-Dist: ua-parser-builtins>=0.18.0.post1
99
+ Requires-Dist: urllib3>=2.5.0
100
+ Requires-Dist: user-agents>=2.2.0
101
+ Requires-Dist: virtualenv>=20.34.0
102
+ Requires-Dist: zipp>=3.23.0
103
+ Dynamic: license-file
@@ -0,0 +1,103 @@
1
+ Metadata-Version: 2.4
2
+ Name: nexo-google
3
+ Version: 0.0.1
4
+ Summary: Google package for Nexo
5
+ Author-email: Agra Bima Yuda <agra@nexmedis.com>
6
+ License: Proprietary
7
+ Requires-Python: >=3.12
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Requires-Dist: aioredis>=2.0.1
11
+ Requires-Dist: annotated-types>=0.7.0
12
+ Requires-Dist: anyio>=4.10.0
13
+ Requires-Dist: async-timeout>=5.0.1
14
+ Requires-Dist: bcrypt>=4.3.0
15
+ Requires-Dist: black>=25.9.0
16
+ Requires-Dist: cachetools>=5.5.2
17
+ Requires-Dist: certifi>=2025.8.3
18
+ Requires-Dist: cffi>=2.0.0
19
+ Requires-Dist: cfgv>=3.4.0
20
+ Requires-Dist: charset-normalizer>=3.4.3
21
+ Requires-Dist: click>=8.3.0
22
+ Requires-Dist: colorama>=0.4.6
23
+ Requires-Dist: cryptography>=46.0.1
24
+ Requires-Dist: distlib>=0.4.0
25
+ Requires-Dist: dnspython>=2.8.0
26
+ Requires-Dist: elastic-transport>=9.1.0
27
+ Requires-Dist: elasticsearch>=9.1.1
28
+ Requires-Dist: fastapi>=0.117.1
29
+ Requires-Dist: filelock>=3.19.1
30
+ Requires-Dist: google-api-core>=2.25.1
31
+ Requires-Dist: google-auth>=2.40.3
32
+ Requires-Dist: google-cloud-appengine-logging>=1.6.2
33
+ Requires-Dist: google-cloud-audit-log>=0.3.2
34
+ Requires-Dist: google-cloud-core>=2.4.3
35
+ Requires-Dist: google-cloud-logging>=3.12.1
36
+ Requires-Dist: google-cloud-pubsub>=2.31.1
37
+ Requires-Dist: google-cloud-secret-manager>=2.24.0
38
+ Requires-Dist: google-cloud-storage>=3.4.0
39
+ Requires-Dist: google-crc32c>=1.7.1
40
+ Requires-Dist: google-resumable-media>=2.7.2
41
+ Requires-Dist: googleapis-common-protos>=1.70.0
42
+ Requires-Dist: greenlet>=3.2.4
43
+ Requires-Dist: grpc-google-iam-v1>=0.14.2
44
+ Requires-Dist: grpcio>=1.75.0
45
+ Requires-Dist: grpcio-status>=1.75.0
46
+ Requires-Dist: h11>=0.16.0
47
+ Requires-Dist: httpcore>=1.0.9
48
+ Requires-Dist: httpx>=0.28.1
49
+ Requires-Dist: identify>=2.6.14
50
+ Requires-Dist: idna>=3.10
51
+ Requires-Dist: importlib_metadata>=8.7.0
52
+ Requires-Dist: iniconfig>=2.1.0
53
+ Requires-Dist: motor>=3.7.1
54
+ Requires-Dist: mypy_extensions>=1.1.0
55
+ Requires-Dist: nexo-crypto>=0.0.2
56
+ Requires-Dist: nexo-database>=0.0.1
57
+ Requires-Dist: nexo-enums>=0.0.2
58
+ Requires-Dist: nexo-logging>=0.0.3
59
+ Requires-Dist: nexo-schemas>=0.0.1
60
+ Requires-Dist: nexo-types>=0.0.2
61
+ Requires-Dist: nexo-utils>=0.0.2
62
+ Requires-Dist: nodeenv>=1.9.1
63
+ Requires-Dist: opentelemetry-api>=1.37.0
64
+ Requires-Dist: opentelemetry-sdk>=1.37.0
65
+ Requires-Dist: opentelemetry-semantic-conventions>=0.58b0
66
+ Requires-Dist: packaging>=25.0
67
+ Requires-Dist: pathspec>=0.12.1
68
+ Requires-Dist: platformdirs>=4.4.0
69
+ Requires-Dist: pluggy>=1.6.0
70
+ Requires-Dist: pre_commit>=4.3.0
71
+ Requires-Dist: proto-plus>=1.26.1
72
+ Requires-Dist: protobuf>=6.32.1
73
+ Requires-Dist: pyasn1>=0.6.1
74
+ Requires-Dist: pyasn1_modules>=0.4.2
75
+ Requires-Dist: pycparser>=2.23
76
+ Requires-Dist: pycryptodome>=3.23.0
77
+ Requires-Dist: pydantic>=2.12.2
78
+ Requires-Dist: pydantic-settings>=2.10.1
79
+ Requires-Dist: pydantic_core>=2.41.4
80
+ Requires-Dist: Pygments>=2.19.2
81
+ Requires-Dist: PyJWT>=2.10.1
82
+ Requires-Dist: pymongo>=4.15.1
83
+ Requires-Dist: pytest>=8.4.2
84
+ Requires-Dist: python-dateutil>=2.9.0.post0
85
+ Requires-Dist: python-dotenv>=1.1.1
86
+ Requires-Dist: pytokens>=0.1.10
87
+ Requires-Dist: PyYAML>=6.0.2
88
+ Requires-Dist: redis>=6.4.0
89
+ Requires-Dist: requests>=2.32.5
90
+ Requires-Dist: rsa>=4.9.1
91
+ Requires-Dist: six>=1.17.0
92
+ Requires-Dist: sniffio>=1.3.1
93
+ Requires-Dist: SQLAlchemy>=2.0.44
94
+ Requires-Dist: starlette>=0.48.0
95
+ Requires-Dist: typing-inspection>=0.4.2
96
+ Requires-Dist: typing_extensions>=4.15.0
97
+ Requires-Dist: ua-parser>=1.0.1
98
+ Requires-Dist: ua-parser-builtins>=0.18.0.post1
99
+ Requires-Dist: urllib3>=2.5.0
100
+ Requires-Dist: user-agents>=2.2.0
101
+ Requires-Dist: virtualenv>=20.34.0
102
+ Requires-Dist: zipp>=3.23.0
103
+ Dynamic: license-file
@@ -0,0 +1,20 @@
1
+ LICENSE
2
+ pyproject.toml
3
+ nexo_google.egg-info/PKG-INFO
4
+ nexo_google.egg-info/SOURCES.txt
5
+ nexo_google.egg-info/dependency_links.txt
6
+ nexo_google.egg-info/requires.txt
7
+ nexo_google.egg-info/top_level.txt
8
+ src/__init__.py
9
+ src/base.py
10
+ src/credential.py
11
+ src/secret.py
12
+ src/storage.py
13
+ src/types.py
14
+ src/pubsub/__init__.py
15
+ src/pubsub/handlers.py
16
+ src/pubsub/types.py
17
+ src/pubsub/config/__init__.py
18
+ src/pubsub/config/config.example.yaml
19
+ src/pubsub/config/publisher.py
20
+ src/pubsub/config/subscription.py
@@ -0,0 +1,93 @@
1
+ aioredis>=2.0.1
2
+ annotated-types>=0.7.0
3
+ anyio>=4.10.0
4
+ async-timeout>=5.0.1
5
+ bcrypt>=4.3.0
6
+ black>=25.9.0
7
+ cachetools>=5.5.2
8
+ certifi>=2025.8.3
9
+ cffi>=2.0.0
10
+ cfgv>=3.4.0
11
+ charset-normalizer>=3.4.3
12
+ click>=8.3.0
13
+ colorama>=0.4.6
14
+ cryptography>=46.0.1
15
+ distlib>=0.4.0
16
+ dnspython>=2.8.0
17
+ elastic-transport>=9.1.0
18
+ elasticsearch>=9.1.1
19
+ fastapi>=0.117.1
20
+ filelock>=3.19.1
21
+ google-api-core>=2.25.1
22
+ google-auth>=2.40.3
23
+ google-cloud-appengine-logging>=1.6.2
24
+ google-cloud-audit-log>=0.3.2
25
+ google-cloud-core>=2.4.3
26
+ google-cloud-logging>=3.12.1
27
+ google-cloud-pubsub>=2.31.1
28
+ google-cloud-secret-manager>=2.24.0
29
+ google-cloud-storage>=3.4.0
30
+ google-crc32c>=1.7.1
31
+ google-resumable-media>=2.7.2
32
+ googleapis-common-protos>=1.70.0
33
+ greenlet>=3.2.4
34
+ grpc-google-iam-v1>=0.14.2
35
+ grpcio>=1.75.0
36
+ grpcio-status>=1.75.0
37
+ h11>=0.16.0
38
+ httpcore>=1.0.9
39
+ httpx>=0.28.1
40
+ identify>=2.6.14
41
+ idna>=3.10
42
+ importlib_metadata>=8.7.0
43
+ iniconfig>=2.1.0
44
+ motor>=3.7.1
45
+ mypy_extensions>=1.1.0
46
+ nexo-crypto>=0.0.2
47
+ nexo-database>=0.0.1
48
+ nexo-enums>=0.0.2
49
+ nexo-logging>=0.0.3
50
+ nexo-schemas>=0.0.1
51
+ nexo-types>=0.0.2
52
+ nexo-utils>=0.0.2
53
+ nodeenv>=1.9.1
54
+ opentelemetry-api>=1.37.0
55
+ opentelemetry-sdk>=1.37.0
56
+ opentelemetry-semantic-conventions>=0.58b0
57
+ packaging>=25.0
58
+ pathspec>=0.12.1
59
+ platformdirs>=4.4.0
60
+ pluggy>=1.6.0
61
+ pre_commit>=4.3.0
62
+ proto-plus>=1.26.1
63
+ protobuf>=6.32.1
64
+ pyasn1>=0.6.1
65
+ pyasn1_modules>=0.4.2
66
+ pycparser>=2.23
67
+ pycryptodome>=3.23.0
68
+ pydantic>=2.12.2
69
+ pydantic-settings>=2.10.1
70
+ pydantic_core>=2.41.4
71
+ Pygments>=2.19.2
72
+ PyJWT>=2.10.1
73
+ pymongo>=4.15.1
74
+ pytest>=8.4.2
75
+ python-dateutil>=2.9.0.post0
76
+ python-dotenv>=1.1.1
77
+ pytokens>=0.1.10
78
+ PyYAML>=6.0.2
79
+ redis>=6.4.0
80
+ requests>=2.32.5
81
+ rsa>=4.9.1
82
+ six>=1.17.0
83
+ sniffio>=1.3.1
84
+ SQLAlchemy>=2.0.44
85
+ starlette>=0.48.0
86
+ typing-inspection>=0.4.2
87
+ typing_extensions>=4.15.0
88
+ ua-parser>=1.0.1
89
+ ua-parser-builtins>=0.18.0.post1
90
+ urllib3>=2.5.0
91
+ user-agents>=2.2.0
92
+ virtualenv>=20.34.0
93
+ zipp>=3.23.0
@@ -0,0 +1,126 @@
1
+ [build-system]
2
+ requires = ["setuptools", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "nexo-google"
7
+ version = "0.0.1"
8
+ description = "Google package for Nexo"
9
+ authors = [
10
+ { name = "Agra Bima Yuda", email = "agra@nexmedis.com" }
11
+ ]
12
+ license = { text = "Proprietary"}
13
+ readme = "README.md"
14
+ requires-python = ">=3.12"
15
+ dependencies = [
16
+ "aioredis>=2.0.1",
17
+ "annotated-types>=0.7.0",
18
+ "anyio>=4.10.0",
19
+ "async-timeout>=5.0.1",
20
+ "bcrypt>=4.3.0",
21
+ "black>=25.9.0",
22
+ "cachetools>=5.5.2",
23
+ "certifi>=2025.8.3",
24
+ "cffi>=2.0.0",
25
+ "cfgv>=3.4.0",
26
+ "charset-normalizer>=3.4.3",
27
+ "click>=8.3.0",
28
+ "colorama>=0.4.6",
29
+ "cryptography>=46.0.1",
30
+ "distlib>=0.4.0",
31
+ "dnspython>=2.8.0",
32
+ "elastic-transport>=9.1.0",
33
+ "elasticsearch>=9.1.1",
34
+ "fastapi>=0.117.1",
35
+ "filelock>=3.19.1",
36
+ "google-api-core>=2.25.1",
37
+ "google-auth>=2.40.3",
38
+ "google-cloud-appengine-logging>=1.6.2",
39
+ "google-cloud-audit-log>=0.3.2",
40
+ "google-cloud-core>=2.4.3",
41
+ "google-cloud-logging>=3.12.1",
42
+ "google-cloud-pubsub>=2.31.1",
43
+ "google-cloud-secret-manager>=2.24.0",
44
+ "google-cloud-storage>=3.4.0",
45
+ "google-crc32c>=1.7.1",
46
+ "google-resumable-media>=2.7.2",
47
+ "googleapis-common-protos>=1.70.0",
48
+ "greenlet>=3.2.4",
49
+ "grpc-google-iam-v1>=0.14.2",
50
+ "grpcio>=1.75.0",
51
+ "grpcio-status>=1.75.0",
52
+ "h11>=0.16.0",
53
+ "httpcore>=1.0.9",
54
+ "httpx>=0.28.1",
55
+ "identify>=2.6.14",
56
+ "idna>=3.10",
57
+ "importlib_metadata>=8.7.0",
58
+ "iniconfig>=2.1.0",
59
+ "motor>=3.7.1",
60
+ "mypy_extensions>=1.1.0",
61
+ "nexo-crypto>=0.0.2",
62
+ "nexo-database>=0.0.1",
63
+ "nexo-enums>=0.0.2",
64
+ "nexo-logging>=0.0.3",
65
+ "nexo-schemas>=0.0.1",
66
+ "nexo-types>=0.0.2",
67
+ "nexo-utils>=0.0.2",
68
+ "nodeenv>=1.9.1",
69
+ "opentelemetry-api>=1.37.0",
70
+ "opentelemetry-sdk>=1.37.0",
71
+ "opentelemetry-semantic-conventions>=0.58b0",
72
+ "packaging>=25.0",
73
+ "pathspec>=0.12.1",
74
+ "platformdirs>=4.4.0",
75
+ "pluggy>=1.6.0",
76
+ "pre_commit>=4.3.0",
77
+ "proto-plus>=1.26.1",
78
+ "protobuf>=6.32.1",
79
+ "pyasn1>=0.6.1",
80
+ "pyasn1_modules>=0.4.2",
81
+ "pycparser>=2.23",
82
+ "pycryptodome>=3.23.0",
83
+ "pydantic>=2.12.2",
84
+ "pydantic-settings>=2.10.1",
85
+ "pydantic_core>=2.41.4",
86
+ "Pygments>=2.19.2",
87
+ "PyJWT>=2.10.1",
88
+ "pymongo>=4.15.1",
89
+ "pytest>=8.4.2",
90
+ "python-dateutil>=2.9.0.post0",
91
+ "python-dotenv>=1.1.1",
92
+ "pytokens>=0.1.10",
93
+ "PyYAML>=6.0.2",
94
+ "redis>=6.4.0",
95
+ "requests>=2.32.5",
96
+ "rsa>=4.9.1",
97
+ "six>=1.17.0",
98
+ "sniffio>=1.3.1",
99
+ "SQLAlchemy>=2.0.44",
100
+ "starlette>=0.48.0",
101
+ "typing-inspection>=0.4.2",
102
+ "typing_extensions>=4.15.0",
103
+ "ua-parser>=1.0.1",
104
+ "ua-parser-builtins>=0.18.0.post1",
105
+ "urllib3>=2.5.0",
106
+ "user-agents>=2.2.0",
107
+ "virtualenv>=20.34.0",
108
+ "zipp>=3.23.0",
109
+ ]
110
+
111
+ [tool.setuptools]
112
+ packages = [
113
+ "nexo.google",
114
+ "nexo.google.pubsub",
115
+ "nexo.google.pubsub.config"
116
+ ]
117
+
118
+ [tool.setuptools.package-data]
119
+ "nexo.google" = ["*.json", "*.yaml"]
120
+ "nexo.google.pubsub" = ["*.json", "*.yaml"]
121
+ "nexo.google.pubsub.config" = ["*.json", "*.yaml"]
122
+
123
+ [tool.setuptools.package-dir]
124
+ "nexo.google" = "src"
125
+ "nexo.google.pubsub" = "src/pubsub"
126
+ "nexo.google.pubsub.config" = "src/pubsub/config"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
File without changes
@@ -0,0 +1,65 @@
1
+ from nexo.logging.config import LogConfig
2
+ from nexo.logging.logger import Client
3
+ from nexo.schemas.application import ApplicationContext, OptApplicationContext
4
+ from nexo.schemas.operation.context import generate
5
+ from nexo.schemas.operation.enums import Origin, Layer, Target
6
+ from nexo.schemas.resource import Resource, ResourceIdentifier
7
+ from nexo.types.misc import OptPathOrStr
8
+ from .credential import load
9
+ from .types import OptionalCredentials
10
+
11
+
12
+ GOOGLE_RESOURCE = Resource(
13
+ identifiers=[ResourceIdentifier(key="google", name="Google", slug="google")],
14
+ details=None,
15
+ )
16
+
17
+
18
+ class GoogleClientManager:
19
+ def __init__(
20
+ self,
21
+ key: str,
22
+ name: str,
23
+ log_config: LogConfig,
24
+ application_context: OptApplicationContext = None,
25
+ credentials: OptionalCredentials = None,
26
+ credentials_path: OptPathOrStr = None,
27
+ ) -> None:
28
+ self._key = key
29
+ self._name = name
30
+
31
+ self._application_context = (
32
+ application_context
33
+ if application_context is not None
34
+ else ApplicationContext.new()
35
+ )
36
+
37
+ self._logger = Client(
38
+ environment=self._application_context.environment,
39
+ service_key=self._application_context.service_key,
40
+ client_key=self._key,
41
+ config=log_config,
42
+ )
43
+
44
+ if (credentials is None and credentials_path is None) or (
45
+ credentials is not None and credentials_path is not None
46
+ ):
47
+ raise ValueError(
48
+ "Only either 'credentials' and 'credentials_path' must be given"
49
+ )
50
+
51
+ if credentials is not None:
52
+ self._credentials = credentials
53
+ else:
54
+ self._credentials = load(credentials_path)
55
+
56
+ self._operation_context = generate(
57
+ origin=Origin.CLIENT, layer=Layer.SERVICE, target=Target.INTERNAL
58
+ )
59
+
60
+ @property
61
+ def project_id(self) -> str:
62
+ self._project_id = self._credentials.project_id
63
+ if not isinstance(self._project_id, str):
64
+ raise ValueError("Project ID must exist")
65
+ return self._project_id
@@ -0,0 +1,110 @@
1
+ import os
2
+ from google.auth import default
3
+ from google.oauth2.service_account import Credentials
4
+ from pathlib import Path
5
+ from nexo.types.dict import StrToAnyDict
6
+ from nexo.types.misc import OptPathOrStr
7
+ from nexo.utils.loaders.json import from_path
8
+
9
+
10
+ def _load_from_default() -> Credentials:
11
+ """Load service account credentials from default sources."""
12
+ try:
13
+ credentials, _ = default()
14
+
15
+ # Check if the default credentials are service account credentials
16
+ if isinstance(credentials, Credentials):
17
+ # Already service account credentials
18
+ if not credentials.project_id:
19
+ # For service account credentials, project_id should be available
20
+ # If not, the service account file is malformed
21
+ raise ValueError(
22
+ "Service account credentials loaded from default source do not have project_id. "
23
+ "Please ensure your service account key file contains the project_id field."
24
+ )
25
+
26
+ return credentials
27
+ else:
28
+ # Default credentials are not service account credentials
29
+ raise ValueError(
30
+ "Default credentials are not service account credentials. "
31
+ f"Found credentials of type: {type(credentials)}. "
32
+ "Please provide a service account key file via 'credentials_path' argument "
33
+ "or the 'GOOGLE_APPLICATION_CREDENTIALS' environment variable."
34
+ )
35
+
36
+ except Exception as e:
37
+ if "service account" in str(e).lower() or "project_id" in str(e).lower():
38
+ raise
39
+ raise ValueError(
40
+ f"Failed to load service account credentials from default sources: {str(e)}. "
41
+ "Please provide a service account key file via 'credentials_path' argument "
42
+ "or the 'GOOGLE_APPLICATION_CREDENTIALS' environment variable."
43
+ )
44
+
45
+
46
+ def _load_from_file(credentials_path: Path) -> Credentials:
47
+ """Load credentials from a service account file."""
48
+ service_account_info: StrToAnyDict = from_path(credentials_path)
49
+
50
+ # Ensure project_id is present in the file
51
+ if (
52
+ "project_id" not in service_account_info
53
+ or not service_account_info["project_id"]
54
+ ):
55
+ raise ValueError(
56
+ f"Service account file {credentials_path} does not contain project_id"
57
+ )
58
+
59
+ # Load credentials from the file
60
+ credentials = Credentials.from_service_account_file(str(credentials_path))
61
+
62
+ # Double-check that project_id is available in the credentials object
63
+ if not credentials.project_id:
64
+ raise ValueError(
65
+ f"Loaded credentials from {credentials_path} do not have project_id"
66
+ )
67
+
68
+ return credentials
69
+
70
+
71
+ def load(credentials_path: OptPathOrStr = None) -> Credentials:
72
+ """
73
+ Load Google service account credentials with guaranteed project_id.
74
+ Priority:
75
+ 1. Explicit path argument
76
+ 2. GOOGLE_APPLICATION_CREDENTIALS environment variable
77
+ 3. Service account from default credentials (if available)
78
+
79
+ Always returns google.oauth2.service_account.Credentials with project_id.
80
+ Raises ValueError if service account credentials cannot be loaded or project_id is missing.
81
+ """
82
+ # Try explicit path first
83
+ if credentials_path is not None:
84
+ credentials_path = Path(credentials_path)
85
+ if credentials_path.exists() and credentials_path.is_file():
86
+ return _load_from_file(credentials_path)
87
+
88
+ # Try GOOGLE_APPLICATION_CREDENTIALS environment variable
89
+ app_credentials_path = os.getenv("GOOGLE_APPLICATION_CREDENTIALS")
90
+ if app_credentials_path:
91
+ credentials_path = Path(app_credentials_path)
92
+ if credentials_path.exists() and credentials_path.is_file():
93
+ return _load_from_file(credentials_path)
94
+
95
+ # Try to get service account from default credentials
96
+ return _load_from_default()
97
+
98
+
99
+ def validate(credentials: Credentials) -> None:
100
+ """Validate that credentials are service account credentials with project_id."""
101
+ if not isinstance(credentials, Credentials):
102
+ raise ValueError(
103
+ "Credentials must be google.oauth2.service_account.Credentials"
104
+ )
105
+
106
+ if not credentials.project_id:
107
+ raise ValueError("Service account credentials must have project_id")
108
+
109
+ if not credentials.service_account_email:
110
+ raise ValueError("Service account credentials must have service_account_email")