Skip to content

Commit 39273af

Browse files
committed
Modified generator to generate plugins
Signed-off-by: saimedhi <saimedhi@amazon.com>
1 parent b2a1796 commit 39273af

File tree

8 files changed

+94
-12
lines changed

8 files changed

+94
-12
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
1313
- Added GHA release ([#614](https://github.com/opensearch-project/opensearch-py/pull/614))
1414
- Incorporated API generation into CI workflow and fixed 'generate' nox session ([#660](https://github.com/opensearch-project/opensearch-py/pull/660))
1515
- Added an automated api update bot for opensearch-py ([#664](https://github.com/opensearch-project/opensearch-py/pull/664))
16+
- Enhance generator to generate plugins ([#700](https://github.com/opensearch-project/opensearch-py/pull/700))
1617
- Enhance generator to update changelog only if generated code differs from existing ([#684](https://github.com/opensearch-project/opensearch-py/pull/684))
1718
### Changed
1819
- Updated the `get_policy` API in the index_management plugin to allow the policy_id argument as optional ([#633](https://github.com/opensearch-project/opensearch-py/pull/633))

opensearchpy/_async/client/__init__.py

+5
Original file line numberDiff line numberDiff line change
@@ -1601,6 +1601,7 @@ async def scroll(
16011601
"from_",
16021602
"ignore_throttled",
16031603
"ignore_unavailable",
1604+
"include_named_queries_score",
16041605
"lenient",
16051606
"max_concurrent_shard_requests",
16061607
"pre_filter_shard_size",
@@ -1681,6 +1682,10 @@ async def search(
16811682
aliased indices should be ignored when throttled.
16821683
:arg ignore_unavailable: Whether specified concrete indices
16831684
should be ignored when unavailable (missing or closed).
1685+
:arg include_named_queries_score: Indicates whether
1686+
hit.matched_queries should be rendered as a map that includes the name
1687+
of the matched query associated with its score (true) or as an array
1688+
containing the name of the matched queries (false) Default is false.
16841689
:arg lenient: Specify whether format-based query failures (such
16851690
as providing text to a numeric field) should be ignored.
16861691
:arg max_concurrent_shard_requests: The number of concurrent

opensearchpy/_async/client/indices.py

+3
Original file line numberDiff line numberDiff line change
@@ -1260,6 +1260,7 @@ async def shard_stores(
12601260
"ignore_unavailable",
12611261
"max_num_segments",
12621262
"only_expunge_deletes",
1263+
"primary_only",
12631264
"wait_for_completion",
12641265
)
12651266
async def forcemerge(
@@ -1288,6 +1289,8 @@ async def forcemerge(
12881289
be merged into (default: dynamic).
12891290
:arg only_expunge_deletes: Specify whether the operation should
12901291
only expunge deleted documents.
1292+
:arg primary_only: Specify whether the operation should only
1293+
perform on primary shards. Defaults to false. Default is false.
12911294
:arg wait_for_completion: Should this request wait until the
12921295
operation has completed before returning. Default is True.
12931296
"""

opensearchpy/client/__init__.py

+5
Original file line numberDiff line numberDiff line change
@@ -1601,6 +1601,7 @@ def scroll(
16011601
"from_",
16021602
"ignore_throttled",
16031603
"ignore_unavailable",
1604+
"include_named_queries_score",
16041605
"lenient",
16051606
"max_concurrent_shard_requests",
16061607
"pre_filter_shard_size",
@@ -1681,6 +1682,10 @@ def search(
16811682
aliased indices should be ignored when throttled.
16821683
:arg ignore_unavailable: Whether specified concrete indices
16831684
should be ignored when unavailable (missing or closed).
1685+
:arg include_named_queries_score: Indicates whether
1686+
hit.matched_queries should be rendered as a map that includes the name
1687+
of the matched query associated with its score (true) or as an array
1688+
containing the name of the matched queries (false) Default is false.
16841689
:arg lenient: Specify whether format-based query failures (such
16851690
as providing text to a numeric field) should be ignored.
16861691
:arg max_concurrent_shard_requests: The number of concurrent

opensearchpy/client/indices.py

+3
Original file line numberDiff line numberDiff line change
@@ -1260,6 +1260,7 @@ def shard_stores(
12601260
"ignore_unavailable",
12611261
"max_num_segments",
12621262
"only_expunge_deletes",
1263+
"primary_only",
12631264
"wait_for_completion",
12641265
)
12651266
def forcemerge(
@@ -1288,6 +1289,8 @@ def forcemerge(
12881289
be merged into (default: dynamic).
12891290
:arg only_expunge_deletes: Specify whether the operation should
12901291
only expunge deleted documents.
1292+
:arg primary_only: Specify whether the operation should only
1293+
perform on primary shards. Defaults to false. Default is false.
12911294
:arg wait_for_completion: Should this request wait until the
12921295
operation has completed before returning. Default is True.
12931296
"""

opensearchpy/plugins/__init__.py

-1
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,3 @@
66
#
77
# Modifications Copyright OpenSearch Contributors. See
88
# GitHub history for details.
9-
#

utils/generate_api.py

+76-10
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,10 @@ def is_valid_url(url: str) -> bool:
101101

102102

103103
class Module:
104-
def __init__(self, namespace: str) -> None:
104+
def __init__(self, namespace: str, is_plugin: bool) -> None:
105105
self.namespace: Any = namespace
106106
self._apis: Any = []
107+
self.is_plugin: bool = is_plugin
107108
self.parse_orig()
108109

109110
def add(self, api: Any) -> None:
@@ -118,10 +119,17 @@ def parse_orig(self) -> None:
118119
reads the written module and updates with important code specific to this client
119120
"""
120121
self.orders = []
121-
self.header = "from typing import Any, Collection, Optional, Tuple, Union\n\n"
122+
if self.is_plugin:
123+
self.header = "from typing import Any\n\n"
124+
else:
125+
self.header = (
126+
"from typing import Any, Collection, Optional, Tuple, Union\n\n"
127+
)
122128

123-
namespace_new = "".join(word.capitalize() for word in self.namespace.split("_"))
124-
self.header += "class " + namespace_new + "Client(NamespacedClient):"
129+
self.namespace_new = "".join(
130+
word.capitalize() for word in self.namespace.split("_")
131+
)
132+
self.header += "class " + self.namespace_new + "Client(NamespacedClient):"
125133
if os.path.exists(self.filepath):
126134
with open(self.filepath, encoding="utf-8") as file:
127135
content = file.read()
@@ -164,7 +172,45 @@ def dump(self) -> None:
164172
writes the module out to disk
165173
"""
166174
self.sort()
175+
if not os.path.exists(self.filepath):
176+
# Imports added for new namespaces in appropriate files.
177+
if self.is_plugin:
178+
with open(
179+
"opensearchpy/_async/client/plugins.py", "r+", encoding="utf-8"
180+
) as file:
181+
content = file.read()
182+
file_content = content.replace(
183+
"super(PluginsClient, self).__init__(client)",
184+
f"super(PluginsClient, self).__init__(client)\n self.{self.namespace} = {self.namespace_new}Client(client)", # pylint: disable=line-too-long
185+
1,
186+
)
187+
new_file_content = file_content.replace(
188+
"from .client import Client",
189+
f"from ..plugins.{self.namespace} import {self.namespace_new}Client\nfrom .client import Client", # pylint: disable=line-too-long
190+
1,
191+
)
192+
file.seek(0)
193+
file.write(new_file_content)
194+
file.truncate()
167195

196+
else:
197+
with open(
198+
"opensearchpy/_async/client/__init__.py", "r+", encoding="utf-8"
199+
) as file:
200+
content = file.read()
201+
file_content = content.replace(
202+
"# namespaced clients for compatibility with API names",
203+
f"# namespaced clients for compatibility with API names\n self.{self.namespace} = {self.namespace_new}Client(client)", # pylint: disable=line-too-long
204+
1,
205+
)
206+
new_file_content = file_content.replace(
207+
"from .utils import",
208+
f"from .{self.namespace} import {self.namespace_new}Client\nfrom .utils import", # pylint: disable=line-too-long
209+
1,
210+
)
211+
file.seek(0)
212+
file.write(new_file_content)
213+
file.truncate()
168214
# This code snippet adds headers to each generated module indicating
169215
# that the code is generated.The separator is the last line in the
170216
# "THIS CODE IS AUTOMATICALLY GENERATED" header.
@@ -209,8 +255,14 @@ def dump(self) -> None:
209255

210256
# Imports are temporarily removed from the header and are regenerated
211257
# later to ensure imports are updated after code generation.
258+
utils = ".utils"
259+
if self.is_plugin:
260+
utils = "..client.utils"
261+
212262
self.header = "\n".join(
213-
line for line in self.header.split("\n") if "from .utils import" not in line
263+
line
264+
for line in self.header.split("\n")
265+
if "from " + utils + " import" not in line
214266
)
215267

216268
with open(self.filepath, "w", encoding="utf-8") as file:
@@ -252,7 +304,7 @@ def dump(self) -> None:
252304
present_keywords = [keyword for keyword in keywords if keyword in content]
253305

254306
if present_keywords:
255-
utils_imports = "from .utils import"
307+
utils_imports = "from " + utils + " import"
256308
result = f"{utils_imports} {', '.join(present_keywords)}"
257309
utils_imports = result
258310
file_content = content.replace("#replace_token#", utils_imports)
@@ -265,7 +317,10 @@ def filepath(self) -> Any:
265317
"""
266318
:return: absolute path to the module
267319
"""
268-
return CODE_ROOT / f"opensearchpy/_async/client/{self.namespace}.py"
320+
if self.is_plugin:
321+
return CODE_ROOT / f"opensearchpy/_async/plugins/{self.namespace}.py"
322+
else:
323+
return CODE_ROOT / f"opensearchpy/_async/client/{self.namespace}.py"
269324

270325

271326
class API:
@@ -704,8 +759,12 @@ def read_modules() -> Any:
704759

705760
api = apply_patch(namespace, name, api)
706761

762+
is_plugin = False
763+
if "_plugins" in api["url"]["paths"][0]["path"] and namespace != "security":
764+
is_plugin = True
765+
707766
if namespace not in modules:
708-
modules[namespace] = Module(namespace)
767+
modules[namespace] = Module(namespace, is_plugin)
709768

710769
modules[namespace].add(API(namespace, name, api))
711770

@@ -752,13 +811,20 @@ def dump_modules(modules: Any) -> None:
752811
todir="/opensearchpy/client/",
753812
additional_replacements=additional_replacements,
754813
),
814+
unasync.Rule(
815+
fromdir="/opensearchpy/_async/plugins/",
816+
todir="/opensearchpy/plugins/",
817+
additional_replacements=additional_replacements,
818+
),
755819
]
756820

757821
filepaths = []
758822
for root, _, filenames in os.walk(CODE_ROOT / "opensearchpy/_async"):
759823
for filename in filenames:
760-
if filename.rpartition(".")[-1] in ("py",) and not filename.startswith(
761-
"utils.py"
824+
if filename.rpartition(".")[-1] in ("py",) and filename not in (
825+
"utils.py",
826+
"index_management.py",
827+
"alerting.py",
762828
):
763829
filepaths.append(os.path.join(root, filename))
764830

utils/license_headers.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def add_header_to_file(filepath: str) -> None:
7979
for i, line in enumerate(lines):
8080
if len(line) > 0 and line not in LINES_TO_KEEP:
8181
break
82-
lines = lines[:i] + [LICENSE_HEADER] + lines[i:]
82+
lines = lines[:i] + [LICENSE_HEADER + "\n\n"] + lines[i:]
8383
with open(filepath, mode="w", encoding="utf-8") as file:
8484
file.truncate()
8585
file.write("".join(lines))

0 commit comments

Comments
 (0)