📝 Add docstrings to `fix-windows-path-handling`

Docstrings generation was requested by @subhash-0000.

* https://github.com/OWASP/Nettacker/pull/1173#issuecomment-3602915683

The following files were modified:

* `nettacker/api/engine.py`
* `nettacker/core/arg_parser.py`
* `nettacker/core/messages.py`
* `nettacker/core/template.py`
* `nettacker/core/utils/common.py`
This commit is contained in:
coderabbitai[bot] 2025-12-02 16:27:54 +00:00 committed by GitHub
parent 65bf88e68f
commit 9fd025df80
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 62 additions and 30 deletions

View File

@ -374,10 +374,12 @@ def get_results():
@app.route("/results/get", methods=["GET"])
def get_result_content():
"""
get a result HTML/TEXT/JSON content
Retrieve the raw scan result content for a given report id and return it as an HTTP response.
Validates the API key on the incoming request. If the "id" parameter is missing, responds with HTTP 400; if the report cannot be retrieved, responds with HTTP 500.
Returns:
content of the scan result
Response: HTTP response whose body is the scan file content, with the MIME type determined from the file extension and a `Content-Disposition` attachment filename header.
"""
api_key_is_valid(app, flask_request)
scan_id = get_value(flask_request, "id")
@ -392,7 +394,7 @@ def get_result_content():
return Response(
file_content,
mimetype=mime_types().get(os.path.splitext(filename)[1], "text/plain"),
headers={"Content-Disposition": "attachment;filename=" + filename.split("/")[-1]},
headers={"Content-Disposition": "attachment;filename=" + os.path.basename(filename)},
)
@ -612,4 +614,4 @@ def start_api_server(options):
except KeyboardInterrupt:
for process in multiprocessing.active_children():
process.terminate()
break
break

View File

@ -43,48 +43,52 @@ class ArgParser(ArgumentParser):
@staticmethod
def load_graphs():
"""
load all available graphs
Discover available graph engine names.
Returns:
an array of graph names
graph_names (list[str]): Unique graph identifiers found under the graph directory, formatted as "<directory>_graph".
"""
graph_names = []
for graph_library in Config.path.graph_dir.glob("*/engine.py"):
graph_names.append(str(graph_library).split("/")[-2] + "_graph")
graph_names.append(graph_library.parent.name + "_graph")
return list(set(graph_names))
@staticmethod
def load_languages():
"""
Get available languages
Discover available language identifiers by scanning the locale directory for YAML files.
Returns:
an array of languages
list[str]: Unique language names derived from locale file stems (order not guaranteed).
"""
languages_list = []
for language in Config.path.locale_dir.glob("*.yaml"):
languages_list.append(str(language).split("/")[-1].split(".")[0])
languages_list.append(language.stem)
return list(set(languages_list))
@staticmethod
def load_modules(limit=-1, full_details=False):
"""
load all available modules
limit: return limited number of modules
full: with full details
Load available scanning modules from the configured modules directory.
Parameters:
limit (int): Maximum number of modules to return; -1 means no limit. If the limit is reached a "..." placeholder will be inserted.
full_details (bool): If True, include each module's parsed `info` mapping as the value; otherwise the value will be None.
Returns:
an array of all module names
dict: Mapping of module keys ("<library>_<category>") to either their `info` dict (when full_details is True) or None. Always includes an "all" entry and may include a "..." placeholder when truncated.
Notes:
This function also updates the module severity and description cache (all_module_severity_and_desc) for each discovered module.
"""
# Search for Modules
module_names = {}
for module_name in sorted(Config.path.modules_dir.glob("**/*.yaml")):
library = str(module_name).split("/")[-1].split(".")[0]
category = str(module_name).split("/")[-2]
library = module_name.stem
category = module_name.parent.name
module = f"{library}_{category}"
contents = yaml.safe_load(TemplateLoader(module).open().split("payload:")[0])
module_names[module] = contents["info"] if full_details else None
@ -763,4 +767,4 @@ class ArgParser(ArgumentParser):
options.time_sleep_between_requests = float(options.time_sleep_between_requests)
options.retries = int(options.retries)
self.arguments = options
self.arguments = options

View File

@ -25,15 +25,17 @@ def load_yaml(filename):
def get_languages():
"""
Get available languages
Return a deduplicated list of available locale identifiers.
Scans Config.path.locale_dir for files with a .yaml extension and collects each file's stem (filename without extension) as a language identifier.
Returns:
an array of languages
languages (list[str]): List of unique language codes derived from locale YAML filenames.
"""
languages_list = []
for language in Config.path.locale_dir.glob("*.yaml"):
languages_list.append(str(language).split("/")[-1].split(".")[0])
languages_list.append(language.stem)
return list(set(languages_list))
@ -68,4 +70,4 @@ def messages(msg_id):
the message content in the selected language if
message found otherwise return message in English
"""
return message_cache[str(msg_id)]
return message_cache[str(msg_id)]

View File

@ -28,15 +28,29 @@ class TemplateLoader:
return module_content
def open(self):
"""
Return the contents of the YAML module file identified by this loader's name.
The name is split on underscores to derive an action (last segment) and a library (remaining segments joined with underscores); the file at Config.path.modules_dir / action / f"{library}.yaml" is opened with UTF-8 encoding and its full text is returned.
Returns:
str: The raw text of the YAML file.
"""
module_name_parts = self.name.split("_")
action = module_name_parts[-1]
library = "_".join(module_name_parts[:-1])
with open(Config.path.modules_dir / action / f"{library}.yaml") as yaml_file:
with open(Config.path.modules_dir / action / f"{library}.yaml", encoding="utf-8") as yaml_file:
return yaml_file.read()
def format(self):
"""
Render the module's YAML template by applying the instance's inputs as format placeholders.
Returns:
formatted (str): The template string produced by calling `open()` and applying `str.format` with `self.inputs`.
"""
return self.open().format(**self.inputs)
def load(self):
return self.parse(yaml.safe_load(self.format()), self.inputs)
return self.parse(yaml.safe_load(self.format()), self.inputs)

View File

@ -165,6 +165,16 @@ def find_args_value(args_name):
def re_address_repeaters_key_name(key_name):
# Note: This uses "/" as a key delimiter, not a file path separator
"""
Format a slash-delimited key path into a sequence of dictionary-access segments excluding the final key.
Parameters:
key_name (str): A "/"-delimited key path ("/" is a key delimiter, not a filesystem separator).
Returns:
str: Concatenated "['key']" segments for every component of `key_name` except the last; returns an empty string if there are no components before the final segment.
"""
return "".join(["['" + _key + "']" for _key in key_name.split("/")[:-1]])
@ -449,4 +459,4 @@ def generate_compare_filepath(scan_id):
return "/report_compare_{date_time}_{scan_id}.json".format(
date_time=now(format="%Y_%m_%d_%H_%M_%S"),
scan_id=scan_id,
)
)