-
Notifications
You must be signed in to change notification settings - Fork 78
Updated docstrings for all classes #250
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
WalkthroughThis update introduces comprehensive documentation, type annotations, and minor refactoring across the entire codebase. All classes, methods, and functions now have detailed docstrings explaining their purpose, parameters, return values, and exceptions. Type hints were added or clarified throughout. Some logic was refactored for clarity, error handling was improved, and variable naming was standardized, but core functionality remains unchanged. Changes
Sequence Diagram(s)Omitted—changes are documentation and refactoring only, with no new or modified control flow. Possibly related PRs
Poem
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
@coderabbitai pause |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR updates and significantly expands documentation across the codebase by adding or improving docstrings for classes, methods, and properties. Key changes include comprehensive docstring additions in the core configuration, AWS, and Azure modules, and consistent inline documentation for various FaaS-related functionalities.
Reviewed Changes
Copilot reviewed 63 out of 63 changed files in this pull request and generated no comments.
Show a summary per file
File | Description |
---|---|
sebs/experiments/config.py | Added detailed class and method docstrings for experiment settings. |
sebs/config.py | Improved docstrings and inline explanations for configuration APIs. |
sebs/azure/* | Expanded documentation for Azure-specific classes, methods, and clients. |
sebs/aws/* | Added and enhanced docstrings covering AWS resources, triggers, and functions. |
sebs/init.py | Updated package-level docstring describing SeBS functionalities. |
Comments suppressed due to low confidence (2)
sebs/aws/aws.py:516
- The docstring for delete_function still contains a FIXME note; consider addressing or removing it to clarify the method's behavior in production code.
FIXME: does not clean the cache.
sebs/aws/triggers.py:101
- [nitpick] The async_invoke method for LibraryTrigger includes a FIXME comment regarding the return type; resolving this by specifying a concrete return type would improve clarity and maintainability.
# FIXME: proper return type - consider a dataclass for the response
@coderabbitai resume |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 33
🔭 Outside diff range comments (17)
sebs/azure/function.py (1)
67-69
: Avoidassert
for runtime validation of trigger types.
assert
statements are stripped with Python’s-O
flag, silently turning the branch into aNone
dereference later on.
Raise an explicit exception instead:- assert trigger_type, "Unknown trigger type {}".format(trigger["type"]) + if not trigger_type: + raise ValueError(f"Unknown trigger type {trigger['type']}")sebs/local/measureMem.py (2)
34-50
: Heavy use ofsubprocess
&cat
is wasteful and risky.Spawning a shell for every sample (~
subprocess.Popen(..., shell=True)
) is orders-of-magnitude slower and opens command-injection foot-guns (the container id comes from user input).
Read the file directly with Python I/O and removeshell=True
:- cmd = f"cat /sys/fs/cgroup/system.slice/{longId}/memory.current" - p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=True) - f.write(f"{container_id} {int(p.communicate()[0].decode())}\n") + path = f"/sys/fs/cgroup/system.slice/{longId}/memory.current" + with open(path, "r") as memf: + f.write(f"{container_id} {int(memf.read().strip())}\n")Apply the same change in the fallback branch.
42-45
: Catching bareexcept
hides real problems.Replace the broad catch with the specific
FileNotFoundError
you expect when the first cgroup mount is missing:- except: # noqa + except FileNotFoundError:sebs/experiments/network_ping_pong.py (1)
212-214
:message
may be undefined – will crash on total packet lossIf all
recvfrom
calls time-out,message
is never set, yet it’s decoded
unconditionally, raisingUnboundLocalError
.- request_id = message.decode() + if not times: + self.logging.warning(f"No datagrams received on port {port}; skipping save.") + return + request_id = message.decode()sebs/aws/dynamodb.py (1)
76-88
:update_cache
uses an undefined attribute
update_cache()
referencesself._cache_client
, but the correct attribute name (defined byNoSQLStorage
/Cache
setup) isself.cache_client
.
This will raise anAttributeError
the first time the method is called.- self._cache_client.update_nosql( + self.cache_client.update_nosql(sebs/storage/scylladb.py (1)
93-101
: Fix duplicateelse
block – SyntaxErrorLines 93-101 contain two consecutive
else:
clauses, which will raise aSyntaxError
.- if not self._cfg.data_volume: - scylla_data_path = os.path.join(project_absolute_path(), "scylladb-volume") - else: - scylla_data_path = self._cfg.data_volume - scylla_data_path = os.path.abspath(scylla_data_path) - else: - scylladb_volume = self._cfg.data_volume - scylladb_volume = os.path.abspath(scylladb_volume) + if not self._cfg.data_volume: + scylla_data_path = os.path.join(project_absolute_path(), "scylladb-volume") + else: + scylla_data_path = self._cfg.data_volume + scylla_data_path = os.path.abspath(scylla_data_path) + scylladb_volume = scylla_data_path # single canonical variablesebs/storage/minio.py (1)
100-109
: Fix the variable naming and control flow issue.The code has conflicting variable names and an invalid
else
statement at line 105. The logic assigns tominio_data_path
but then usesminio_volume
.Apply this diff to fix the issue:
-if not self._cfg.data_volume: # Check if data_volume is empty or None - minio_data_path = os.path.join(project_absolute_path(), "minio-volume") -else: - minio_data_path = self._cfg.data_volume -minio_data_path = os.path.abspath(minio_data_path) -else: - minio_volume = self._cfg.data_volume -minio_volume = os.path.abspath(minio_volume) +if not self._cfg.data_volume: # Check if data_volume is empty or None + minio_volume = os.path.join(project_absolute_path(), "minio-volume") +else: + minio_volume = self._cfg.data_volume +minio_volume = os.path.abspath(minio_volume)sebs/regression.py (9)
5-8
: Add missing imports for List and json.The code uses
List
type hint andjson
module but they are not imported.-from typing import cast, Dict, Optional, Set, TYPE_CHECKING +from typing import cast, Dict, List, Optional, Set, TYPE_CHECKING +import json
242-246
: Use the correct variable name for logging filename.The code creates
log_file_name
but uses undefined variablef
.-log_file_name = f"regression_{deployment_name}_{benchmark_name}_{architecture}_{deployment_type}.log" deployment_client = self.client.get_deployment( cloud_config, - logging_filename=os.path.join(self.client.output_dir, f), + logging_filename=os.path.join(self.client.output_dir, log_file_name), )
278-282
: Use the correct variable name for logging filename.-log_file_name = f"regression_{deployment_name}_{benchmark_name}_{architecture}_{deployment_type}.log" deployment_client = self.client.get_deployment( cloud_config, - logging_filename=os.path.join(self.client.output_dir, f), + logging_filename=os.path.join(self.client.output_dir, log_file_name), )
332-337
: Use the correct variable name for logging filename.deployment_client = self.client.get_deployment( cloud_config, - logging_filename=os.path.join(self.client.output_dir, f), + logging_filename=os.path.join(self.client.output_dir, log_file_name), deployment_config=AzureTestSequencePython.cfg, )
385-390
: Use the correct variable name for logging filename.deployment_client = self.client.get_deployment( cloud_config, - logging_filename=os.path.join(self.client.output_dir, f), + logging_filename=os.path.join(self.client.output_dir, log_file_name), deployment_config=AzureTestSequencePython.cfg, )
422-426
: Use the correct variable name for logging filename.-log_file_name = f"regression_{deployment_name}_{benchmark_name}_{architecture}_{deployment_type}.log" deployment_client = self.client.get_deployment( cloud_config, - logging_filename=os.path.join(self.client.output_dir, f), + logging_filename=os.path.join(self.client.output_dir, log_file_name), )
457-461
: Use the correct variable name for logging filename.-log_file_name = f"regression_{deployment_name}_{benchmark_name}_{architecture}_{deployment_type}.log" deployment_client = self.client.get_deployment( cloud_config, - logging_filename=os.path.join(self.client.output_dir, f), + logging_filename=os.path.join(self.client.output_dir, log_file_name), )
502-506
: Use the correct variable name for logging filename.-log_file_name = f"regression_{deployment_name}_{benchmark_name}_{architecture}_{deployment_type}.log" deployment_client = self.client.get_deployment( config_copy, - logging_filename=os.path.join(self.client.output_dir, f), + logging_filename=os.path.join(self.client.output_dir, log_file_name), )
545-549
: Use the correct variable name for logging filename.-log_file_name = f"regression_{deployment_name}_{benchmark_name}_{architecture}_{deployment_type}.log" deployment_client = self.client.get_deployment( config_copy, - logging_filename=os.path.join(self.client.output_dir, f), + logging_filename=os.path.join(self.client.output_dir, log_file_name), )sebs/local/local.py (1)
5-5
: Add missing Any import.The code uses
Any
type hint on line 229 but it's not imported.-from typing import cast, Dict, List, Optional, Type, Tuple # noqa +from typing import Any, cast, Dict, List, Optional, Type, Tuple # noqa
🧹 Nitpick comments (55)
sebs/experiments/experiment.py (1)
38-43
: Typo inname()
docstring.The first line reads "Return the a short, human-readable name...". Remove the extra article:
- Return the a short, human-readable name of the experiment. + Return a short, human-readable name of the experiment.sebs/azure/function.py (1)
30-31
: Prefer a private attribute + accessor forfunction_storage
.
function_storage
is written as a public attribute. Exposing provider-specific internals invites accidental modification from outside the class. Make it_function_storage
and add a read-only@property
for clarity & encapsulation.- self.function_storage = function_storage + self._function_storage = function_storage + + @property + def function_storage(self) -> AzureResources.Storage: # noqa: D401 + """Return the Azure storage associated with this function.""" + return self._function_storagesebs/faas/resources.py (1)
36-46
: Docstring default contradicts signature.
replace_existing
defaults toNone
, but the docstring says Defaults to False.
Synchronise the two to avoid confusion.sebs/aws/config.py (1)
134-134
: Pylint warning: “Too many instance attributes”.
AWSResources
now carries 8 attributes (limit 7). Not blocking, but splitting Docker-related state into a small data class (ECRAuth
) would silence the linter and improve cohesion.sebs/aws/triggers.py (1)
89-101
: Comprehensive documentation with valid improvement suggestion.The docstring accurately documents the current behavior. The FIXME comment about using a more specific return type (like a dataclass) is a valid suggestion for future improvement.
Would you like me to create an issue to track the return type improvement suggestion mentioned in the FIXME comment?
sebs/statistics.py (1)
13-34
: Improved edge case handling and documentation.Good addition of NaN returns for empty inputs and zero mean cases. The implementation is correct.
Consider using a ternary operator as suggested by static analysis:
- if mean_val == 0: - cv_val = np.nan - else: - cv_val = (std_val / mean_val) * 100 + cv_val = np.nan if mean_val == 0 else (std_val / mean_val) * 100sebs/gcp/resources.py (1)
53-54
: Nit: tiny typo in comment
# Flag to indicate if this instance owns the CLI
– consider “this object” instead of “this instance” to avoid confusion with the CLI instance itself.sebs/storage/config.py (5)
61-62
: Simpler and faster default factoryThe lambda is unnecessary—
list
is already a callable.- input_buckets: List[str] = field(default_factory=lambda: []) # Ensure default_factory is callable + input_buckets: List[str] = field(default_factory=list)
75-80
: Avoid needless.keys()
call and non-existent “resources” skip
for key_name in self.__dataclass_fields__:
is clearer and satisfies Ruff SIM118.- The
if key_name == "resources"
guard is dead code – no such field exists.- for key_name in self.__dataclass_fields__.keys(): - # Avoid trying to cache complex objects or fields not meant for direct caching - if key_name == "resources": # Example of a field to skip if it existed - continue + for key_name in self.__dataclass_fields__: cache.update_config(val=getattr(self, key_name), keys=[*path, key_name])
93-99
: Same.keys()
pattern indeserialize
- known_keys = list(MinioConfig.__dataclass_fields__.keys()) + known_keys = MinioConfig.__dataclass_fields__This change also applies to
ScyllaDBConfig.deserialize
.
64-65
: Consider renaming fieldtype
to avoid shadowing built-inUsing
type
as an attribute can confuse static analysis and readers. A common alternative iskind
orstorage_type
.
182-183
: Repeat of.keys()
issue inScyllaDBConfig.update_cache
Apply the same iteration simplification here to silence SIM118.
sebs/faas/config.py (3)
78-90
: UseValueError
instead of genericException
inStorageBucketType.deserialize
Raising a broad
Exception
hampers consumers’ ability to distinguish configuration errors.- raise Exception(f"Unknown storage bucket type type {val}") + raise ValueError(f"Unknown storage bucket type '{val}'.")
148-149
: String duplication in f-string
"type type"
appears twice in the error message; see previous suggestion.
161-170
:initialize
is both abstract and partially implementedMarking the method
@abstractmethod
while providing usable logic forces every subclass to re-implement or explicitly callsuper().initialize
, otherwise instantiation fails. If the base implementation is sufficient for some providers, consider removing@abstractmethod
or extracting the shared part into a protected helper.sebs/local/deployment.py (1)
110-121
: Gracefully handle unknown storage schemaGood addition of the
None
check; however, if future versions of the JSON omitstorage
entirely, aKeyError
will be raised earlier when you accessinput_data["inputs"]
and["functions"]
. Consider.get()
with defaults to make deserialization forwards-compatible.sebs/azure/cosmosdb.py (2)
256-258
: Inconsistent indentationLine 257 has one extra leading space, breaking 4-space multiples and failing some strict linters.
- benchmark_resources.database_client = self.cosmos_client().get_database_client(benchmark) + benchmark_resources.database_client = self.cosmos_client().get_database_client(benchmark)
264-267
: Minor: avoid side-effect comment; make it explicitCalling
db_client.read()
solely for existence verification is non-obvious. Wrapping it into a helper (e.g.,_database_exists()
) or adding a short comment explaining “force API call” improves readability.sebs/local/function.py (1)
200-204
: Preserve original traceback when re-raisingRuff B904: use
raise … from e
to indicate the causal exception chain.- except docker.errors.NotFound: - raise RuntimeError(f"Cached container {instance_id} not available anymore!") + except docker.errors.NotFound as e: + raise RuntimeError( + f"Cached container {instance_id} not available anymore!" + ) from esebs/experiments/network_ping_pong.py (1)
153-160
: Optional: guard histogram generation
hist()
on an empty dataframe raises; you already log earlier when no data
exists, so simply return before reaching this block to avoid the extra try/except.sebs/aws/s3.py (2)
122-128
: Chain the caught exceptionSame Ruff B904 issue – preserve traceback.
- except self.client.exceptions.BucketAlreadyExists as e: - self.logging.error(f"The bucket {bucket_name} exists already in region {self.region}!") - raise e + except self.client.exceptions.BucketAlreadyExists as e: + self.logging.error( + f"The bucket {bucket_name} exists already in region {self.region}!" + ) + raise RuntimeError("Bucket creation failed") from e
221-224
: Redundantelse
branchAfter a
return
theelse
is unnecessary; simplifies flow.- else: - return [bucket["Name"] for bucket in s3_buckets] + return [bucket["Name"] for bucket in s3_buckets]sebs/experiments/eviction_model.py (1)
160-170
: Sleep calculation can be simplified & guarded
seconds_to_sleep_precisely
may still be negative if system clock skews or the
first invocation overrunssleep_time
. You already usemax(0, …)
, but the
variable naming (seconds_to_sleep_precisely
) is misleading once clamped.
Consider:- time_spent_after_invocation = (datetime.now() - end).total_seconds() - seconds_to_sleep_precisely = sleep_time - time_spent_after_invocation - actual_sleep_duration = max(0, seconds_to_sleep_precisely) + elapsed = (datetime.now() - end).total_seconds() + sleep_remaining = max(0, sleep_time - elapsed)A tiny readability win; no functional change.
sebs/gcp/storage.py (3)
258-264
: Simplify nested if statements.The nested if statements can be combined for better readability.
Apply this diff:
-if not self.replace_existing: - # input_prefixes_files should contain full keys for the given prefix. - # This check assumes self.input_prefixes_files[path_idx] has been populated correctly. - if full_key in self.input_prefixes_files[path_idx]: - logging.info(f"Skipping upload of {filepath} to {bucket_name}/{full_key} as it exists and replace_existing is False.") - return +if not self.replace_existing and full_key in self.input_prefixes_files[path_idx]: + logging.info(f"Skipping upload of {filepath} to {bucket_name}/{full_key} as it exists and replace_existing is False.") + return
190-201
: Remove unnecessary else after return.The else block is unnecessary after a return statement.
Apply this diff:
def list_buckets(self, bucket_name_filter: Optional[str] = None) -> List[str]: """...""" all_buckets_iterator = self.client.list_buckets() if bucket_name_filter is not None: return [bucket.name for bucket in all_buckets_iterator if bucket_name_filter in bucket.name] - else: - return [bucket.name for bucket in all_buckets_iterator] + return [bucket.name for bucket in all_buckets_iterator]
216-232
: Implement the clean_bucket method.The method is documented but not implemented. This could cause runtime errors if called.
Would you like me to implement the
clean_bucket
method based on the example sketch in the comments?sebs/local/config.py (1)
115-147
: Complex deserialization logic needs clarification.The deserialization method has become quite complex with the parent class interaction. Consider adding more detailed comments about the interaction with
SelfHostedResources._deserialize
.Would you like me to help refactor this method to make the parent-child class interaction clearer?
sebs/storage/resources.py (1)
125-138
: Simplify the conditional structure.The
elif
afterreturn
is unnecessary and can be simplified for better readability.- elif storage_impl_type_str: - self.logging.warning(f"Unknown {storage_type_key} type: {storage_impl_type_str}") - else: - self.logging.info(f"No 'type' specified for {storage_type_key} in {source_msg} config.") + if storage_impl_type_str: + self.logging.warning(f"Unknown {storage_type_key} type: {storage_impl_type_str}") + else: + self.logging.info(f"No 'type' specified for {storage_type_key} in {source_msg} config.")sebs/gcp/datastore.py (1)
242-245
: Preserve original exception context when re-raisingUse
raise … from e
to retain the CLI error details and ease debugging.- raise RuntimeError(f"Couldn't query Datastore database {database_name}!") + raise RuntimeError( + f"Couldn't query Datastore database {database_name}!" + ) from esebs/faas/function.py (1)
313-317
: Wrong variable referenced in error path
TriggerType.get()
builds an error message with the last iterated enum member
instead of the requestedname
, e.g."Unknown trigger type TriggerType.STORAGE"
.- raise Exception("Unknown trigger type {}".format(member)) + raise Exception(f"Unknown trigger type {name}")sebs/gcp/config.py (1)
84-96
: Optional – validate credential path early
GCPCredentials.deserialize
trusts the user-supplied or environment-supplied path
without checkingos.path.isfile(...)
. A simple existence check would provide a
clearer error before the lateropen()
inevitably fails.sebs/faas/storage.py (1)
289-289
: Remove implementation detail comment.The comment about renaming the variable is an implementation detail that shouldn't be in production code.
- description_map = { # Renamed from `description` to avoid conflict + description_map = {sebs/benchmark.py (1)
541-543
: Remove unused variable assignment.The file handle
f
is not used in the context manager.- with open(req_file_path, "w") as f: - pass # Create empty file + with open(req_file_path, "w"): + pass # Create empty filesebs/faas/system.py (2)
313-319
: Remove stray triple-quoted literalThe multi-line string is placed after executable code, so it is evaluated as a useless expression each time
get_function
runs.
Convert it to a comment or move it to the top of the method as the actual docstring.
322-328
: Delete unused variable
code_location
is assigned but never used → F841.
Safe to drop the assignment.- code_location = code_package.code_location
sebs/storage/scylladb.py (1)
72-80
: Endpoint may include port twice
endpoint_url=f"http://{config.address}:{config.alternator_port}"
appends the port even though laterconfigure_connection
setsaddress
toip:port
.
Guard against double:port
concatenation.sebs/openwhisk/openwhisk.py (2)
16-17
: Remove unused import
GCPFunction
is never referenced in this module – drop the import to silence F401.-from sebs.gcp.function import GCPFunction
569-584
: Fragile URL parsingSplitting on
"https://"
and then manually re-adding protocol/.json
is brittle.
Consider using regex orurlparse
to extract the URL without trailing log text, and avoid blindly appending.json
.sebs/storage/minio.py (2)
218-218
: Remove the misleading comment.The comment states "Should be self._cfg.access_key" but the code already correctly uses
self._cfg.access_key
.-access_key=self._cfg.access_key, # Should be self._cfg.access_key +access_key=self._cfg.access_key,
396-396
: Fix the incorrect comment about remove_bucket parameters.The comment incorrectly states that
remove_bucket
expects abucket_name
kwarg, but the minio client actually takes it as a positional argument.-self.connection.remove_bucket(bucket_name) # Minio remove_bucket expects bucket_name kwarg +self.connection.remove_bucket(bucket_name)sebs/local/local.py (2)
180-180
: Rename unused loop variable.The loop variable
dirs
is not used within the loop body.-for path, dirs, files in os.walk(directory): +for path, _, files in os.walk(directory):
295-295
: Avoid direct access to private attributes.The code directly modifies the private
_measurement_pid
attribute. Consider using a property or setter method.-func_obj._measurement_pid = measurement_process_pid +func_obj.measurement_pid = measurement_process_pid # Assuming a setter property existsIf no setter exists, consider adding one to the LocalFunction class.
sebs/cache.py (3)
48-56
: Unnecessaryelse
branch after earlyreturn
In
update_dict.map_keys_recursive
, theelse
is unreachable because thereturn
in the preceding branch already exits.- if len(current_keys): - # Recursively build the dictionary structure - return {current_keys[0]: map_keys_recursive(current_keys[1:])} - else: - # Base case: return the value to be set - return val + if current_keys: + return {current_keys[0]: map_keys_recursive(current_keys[1:])} + return valRemoves dead code and satisfies pylint R1705.
419-422
:new_entry_structure
is dead codeThe variable is built but never used, triggering Ruff F841 and wasting cycles.
Delete it or integrate it into the final merge logic to avoid confusion.
624-633
: Loop variable unused & redundant break
deployment_key
is never referenced and theif updated: break
is unreachable after the precedingbreak
.-for deployment_key, deployment_data in master_config.items(): +for _, deployment_data in master_config.items(): ... - break # Found and updated -if updated: - break + break # Found and updatedCleans up the control flow and fixes Ruff B007.
sebs/gcp/gcp.py (2)
193-204
: Remove unused variable.
package_config_exclusions
is assigned but never referenced, triggeringF841
.
Delete the assignment or put it to use; otherwise it’s dead code.
1070-1103
: Use context manager forZipFile
and simplify compression selection.Manually closing the archive and calling
zipfile.is_zipfile
on a path that doesn’t exist are unnecessary. A clearer, safer implementation:- compression_method = zipfile.ZIP_DEFLATED if zipfile.is_zipfile(archname) or hasattr(zipfile, "ZIP_DEFLATED") else zipfile.ZIP_STORED - archive = zipfile.ZipFile(archname, "w", compression=compression_method) - try: - ... - finally: - archive.close() + compression_method = zipfile.ZIP_DEFLATED + with zipfile.ZipFile(archname, "w", compression=compression_method) as archive: + if os.path.isdir(directory): + GCP.helper_zip(directory, directory, archive) + else: + archive.write(directory, os.path.basename(directory))This fixes
R1732
(use-with-resource) and removes the redundantis_zipfile
call.sebs/aws/aws.py (8)
91-98
: Documentinitialize
parameters usage.
The docstring notes thatconfig
is currently unused. Consider marking it with a leading underscore or updating the signature to avoid confusion.
137-159
:package_code
docstring formatting nitpick.
The return tuple description is indented inconsistently. Align the second line under the:return:
tag for readability. For example:- :return: Tuple containing the path to the zip archive, size of the archive in bytes, - and the ECR container URI (if applicable). + :return: Tuple containing: + - path to the zip archive + - size of the archive in bytes + - the ECR container URI (if applicable)
210-218
:_map_language_runtime
docstring duplication.
The inline comments repeat content from the docstring. Consider removing the code comments to avoid redundancy.
233-244
: Enhancecreate_function
exception documentation.
You catchResourceNotFoundException
but don’t document it. Consider adding::raises botocore.exceptions.ResourceNotFoundException: if the function does not exist
348-354
:cached_function
return behavior missing.
The docstring doesn’t state that it returnsNone
. You may add a brief:return: None
for clarity.
370-377
:update_function
docstring missing error cases.
Consider adding:raises
to document potential AWS client exceptions.
514-519
: RemoveFIXME
from docstring.
TheFIXME: does not clean the cache.
belongs in a# TODO
comment in the body or an issue tracker, not the docstring.
635-644
:download_metrics
unusedmetrics
parameter.
The docstring and signature includemetrics
but it isn’t used. Consider removing it or documenting its intended role.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (63)
sebs/__init__.py
(1 hunks)sebs/aws/aws.py
(17 hunks)sebs/aws/config.py
(15 hunks)sebs/aws/container.py
(4 hunks)sebs/aws/dynamodb.py
(8 hunks)sebs/aws/function.py
(5 hunks)sebs/aws/resources.py
(4 hunks)sebs/aws/s3.py
(7 hunks)sebs/aws/triggers.py
(3 hunks)sebs/azure/azure.py
(15 hunks)sebs/azure/blob_storage.py
(5 hunks)sebs/azure/cli.py
(4 hunks)sebs/azure/cloud_resources.py
(5 hunks)sebs/azure/config.py
(20 hunks)sebs/azure/cosmosdb.py
(8 hunks)sebs/azure/function.py
(2 hunks)sebs/azure/system_resources.py
(5 hunks)sebs/azure/triggers.py
(1 hunks)sebs/benchmark.py
(5 hunks)sebs/cache.py
(4 hunks)sebs/config.py
(3 hunks)sebs/experiments/config.py
(3 hunks)sebs/experiments/environment.py
(2 hunks)sebs/experiments/eviction_model.py
(5 hunks)sebs/experiments/experiment.py
(1 hunks)sebs/experiments/invocation_overhead.py
(6 hunks)sebs/experiments/network_ping_pong.py
(4 hunks)sebs/experiments/perf_cost.py
(6 hunks)sebs/experiments/result.py
(4 hunks)sebs/experiments/startup_time.py
(1 hunks)sebs/faas/config.py
(3 hunks)sebs/faas/container.py
(4 hunks)sebs/faas/function.py
(9 hunks)sebs/faas/nosql.py
(3 hunks)sebs/faas/resources.py
(1 hunks)sebs/faas/storage.py
(2 hunks)sebs/faas/system.py
(12 hunks)sebs/gcp/cli.py
(3 hunks)sebs/gcp/config.py
(3 hunks)sebs/gcp/datastore.py
(4 hunks)sebs/gcp/function.py
(3 hunks)sebs/gcp/gcp.py
(8 hunks)sebs/gcp/resources.py
(4 hunks)sebs/gcp/storage.py
(1 hunks)sebs/gcp/triggers.py
(2 hunks)sebs/local/config.py
(1 hunks)sebs/local/deployment.py
(2 hunks)sebs/local/function.py
(1 hunks)sebs/local/local.py
(3 hunks)sebs/local/measureMem.py
(3 hunks)sebs/openwhisk/config.py
(1 hunks)sebs/openwhisk/container.py
(2 hunks)sebs/openwhisk/function.py
(1 hunks)sebs/openwhisk/openwhisk.py
(4 hunks)sebs/regression.py
(12 hunks)sebs/sebs.py
(2 hunks)sebs/statistics.py
(1 hunks)sebs/storage/config.py
(1 hunks)sebs/storage/minio.py
(3 hunks)sebs/storage/resources.py
(1 hunks)sebs/storage/scylladb.py
(2 hunks)sebs/types.py
(1 hunks)sebs/utils.py
(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (27)
sebs/experiments/experiment.py (5)
sebs/experiments/eviction_model.py (2)
name
(67-69)typename
(72-74)sebs/experiments/network_ping_pong.py (2)
name
(224-226)typename
(229-231)sebs/experiments/invocation_overhead.py (2)
name
(439-441)typename
(444-446)sebs/experiments/startup_time.py (2)
name
(21-23)typename
(26-28)sebs/experiments/perf_cost.py (2)
name
(38-40)typename
(43-45)
sebs/azure/function.py (2)
sebs/faas/function.py (19)
benchmark
(626-628)name
(621-623)serialize
(408-414)serialize
(454-456)serialize
(485-491)serialize
(573-587)serialize
(677-693)deserialize
(57-66)deserialize
(87-96)deserialize
(119-128)deserialize
(181-193)deserialize
(271-285)deserialize
(418-425)deserialize
(435-446)deserialize
(459-470)deserialize
(494-501)deserialize
(555-571)deserialize
(697-706)Function
(590-706)sebs/azure/config.py (4)
serialize
(142-149)serialize
(219-225)serialize
(546-561)serialize
(674-688)
sebs/local/measureMem.py (2)
sebs/local/deployment.py (2)
measurement_file
(20-22)measurement_file
(25-27)sebs/local/local.py (1)
measure_interval
(64-66)
sebs/aws/function.py (4)
sebs/aws/triggers.py (2)
serialize
(116-122)serialize
(183-189)sebs/faas/function.py (6)
serialize
(408-414)serialize
(454-456)serialize
(485-491)serialize
(573-587)serialize
(677-693)benchmark
(626-628)sebs/gcp/function.py (1)
code_bucket
(83-96)sebs/aws/s3.py (1)
S3
(12-243)
sebs/local/function.py (5)
sebs/storage/minio.py (3)
config
(58-60)config
(63-65)stop
(191-205)sebs/faas/function.py (30)
trigger_type
(383-385)Trigger
(288-425)TriggerType
(298-316)sync_invoke
(388-395)ExecutionResult
(196-285)_http_invoke
(318-377)async_invoke
(398-405)serialize
(408-414)serialize
(454-456)serialize
(485-491)serialize
(573-587)serialize
(677-693)deserialize
(57-66)deserialize
(87-96)deserialize
(119-128)deserialize
(181-193)deserialize
(271-285)deserialize
(418-425)deserialize
(435-446)deserialize
(459-470)deserialize
(494-501)deserialize
(555-571)Function
(590-706)name
(621-623)benchmark
(626-628)code_package_hash
(631-633)code_package_hash
(636-638)config
(616-618)FunctionConfig
(508-587)get
(305-316)sebs/utils.py (6)
logging
(377-382)debug
(267-272)serialize
(58-71)is_linux
(441-447)error
(286-290)info
(274-278)sebs/local/deployment.py (2)
serialize
(69-90)deserialize
(94-121)sebs/storage/scylladb.py (2)
config
(37-39)stop
(216-230)
sebs/gcp/cli.py (5)
sebs/azure/cli.py (4)
typename
(69-71)execute
(73-88)login
(90-109)shutdown
(139-142)sebs/gcp/config.py (4)
credentials
(245-247)GCPCredentials
(20-135)project_name
(49-51)project_name
(240-242)sebs/config.py (1)
SeBSConfig
(7-229)sebs/sebs.py (2)
docker_client
(36-38)shutdown
(335-340)sebs/gcp/resources.py (1)
shutdown
(125-133)
sebs/aws/triggers.py (2)
sebs/aws/aws.py (3)
AWS
(27-793)name
(38-40)typename
(43-45)sebs/aws/function.py (2)
typename
(45-47)serialize
(49-63)
sebs/gcp/triggers.py (3)
sebs/aws/triggers.py (11)
trigger_type
(44-46)trigger_type
(156-158)sync_invoke
(48-87)sync_invoke
(160-168)serialize
(116-122)serialize
(183-189)deserialize
(125-132)LibraryTrigger
(11-132)HTTPTrigger
(135-199)async_invoke
(89-114)async_invoke
(170-181)sebs/gcp/gcp.py (2)
GCP
(37-1103)name
(78-80)sebs/azure/triggers.py (6)
trigger_type
(51-53)sync_invoke
(55-62)serialize
(77-83)deserialize
(86-93)HTTPTrigger
(36-93)async_invoke
(64-75)
sebs/faas/nosql.py (4)
sebs/aws/dynamodb.py (3)
deployment_name
(20-22)retrieve_cache
(57-74)update_cache
(76-88)sebs/azure/cosmosdb.py (3)
deployment_name
(57-59)retrieve_cache
(106-123)update_cache
(125-133)sebs/gcp/datastore.py (3)
deployment_name
(55-57)retrieve_cache
(106-123)update_cache
(125-133)sebs/cache.py (1)
Cache
(59-643)
sebs/local/config.py (2)
sebs/faas/config.py (16)
serialize
(55-61)serialize
(194-208)serialize
(320-329)deserialize
(40-52)deserialize
(78-89)deserialize
(180-191)deserialize
(279-317)Credentials
(23-61)initialize
(161-176)initialize
(265-275)Resources
(64-225)resources
(259-261)update_cache
(210-225)update_cache
(332-341)Config
(228-341)credentials
(253-255)sebs/cache.py (4)
Cache
(59-643)update_config
(128-141)get_config
(119-126)typename
(93-97)
sebs/gcp/resources.py (10)
sebs/aws/resources.py (3)
typename
(19-21)config
(24-26)get_storage
(58-85)sebs/azure/cli.py (3)
typename
(69-71)login
(90-109)shutdown
(139-142)sebs/azure/system_resources.py (4)
typename
(19-21)config
(24-26)get_storage
(53-77)shutdown
(154-162)sebs/gcp/gcp.py (3)
typename
(83-85)config
(73-75)shutdown
(736-739)sebs/faas/system.py (5)
config
(87-89)cache_client
(68-70)docker_client
(63-65)system_config
(58-60)shutdown
(533-545)sebs/gcp/storage.py (3)
GCPStorage
(14-265)replace_existing
(27-29)replace_existing
(32-34)sebs/gcp/datastore.py (1)
Datastore
(47-286)sebs/gcp/cli.py (3)
GCloudCLI
(11-116)login
(93-111)shutdown
(113-116)sebs/faas/resources.py (1)
get_storage
(36-47)sebs/cache.py (1)
shutdown
(151-166)
sebs/config.py (1)
sebs/utils.py (1)
project_absolute_path
(21-28)
sebs/azure/blob_storage.py (3)
sebs/aws/s3.py (10)
replace_existing
(25-27)replace_existing
(30-32)_create_bucket
(73-133)list_buckets
(213-224)uploader_func
(135-160)upload
(162-171)exists_bucket
(184-195)list_bucket
(197-211)clean_bucket
(226-235)remove_bucket
(237-243)sebs/gcp/storage.py (10)
replace_existing
(27-29)replace_existing
(32-34)_create_bucket
(67-119)list_buckets
(190-201)uploader_func
(235-265)upload
(134-158)exists_bucket
(160-175)list_bucket
(177-188)clean_bucket
(216-232)remove_bucket
(203-213)sebs/faas/storage.py (11)
region
(55-57)replace_existing
(45-47)replace_existing
(50-52)_create_bucket
(118-132)list_buckets
(170-177)uploader_func
(312-323)upload
(146-156)exists_bucket
(180-187)list_bucket
(159-167)clean_bucket
(190-196)remove_bucket
(199-205)
sebs/azure/cosmosdb.py (4)
sebs/azure/cloud_resources.py (2)
serialize
(122-132)deserialize
(135-142)sebs/faas/nosql.py (8)
NoSQLStorage
(10-202)deployment_name
(19-26)cache_client
(29-31)region
(34-36)get_tables
(53-62)_get_table_name
(65-73)clear_table
(180-192)remove_table
(195-202)sebs/azure/cli.py (1)
AzureCLI
(12-142)sebs/cache.py (2)
Cache
(59-643)update_nosql
(304-314)
sebs/gcp/config.py (5)
sebs/faas/config.py (19)
Credentials
(23-61)initialize
(161-176)initialize
(265-275)deserialize
(40-52)deserialize
(78-89)deserialize
(180-191)deserialize
(279-317)serialize
(55-61)serialize
(194-208)serialize
(320-329)update_cache
(210-225)update_cache
(332-341)Resources
(64-225)Config
(228-341)credentials
(253-255)resources
(259-261)region
(120-123)region
(126-128)region
(247-249)sebs/gcp/gcp.py (3)
initialize
(92-104)config
(73-75)name
(78-80)sebs/gcp/resources.py (1)
config
(26-28)sebs/cache.py (3)
Cache
(59-643)get_config
(119-126)update_config
(128-141)sebs/utils.py (4)
LoggingHandlers
(312-347)logging
(377-382)error
(286-290)info
(274-278)
sebs/gcp/datastore.py (5)
sebs/gcp/resources.py (2)
config
(26-28)cli_instance
(94-111)sebs/faas/nosql.py (9)
NoSQLStorage
(10-202)deployment_name
(19-26)cache_client
(29-31)region
(34-36)get_tables
(53-62)_get_table_name
(65-73)create_table
(140-157)clear_table
(180-192)remove_table
(195-202)sebs/gcp/cli.py (2)
GCloudCLI
(11-116)execute
(76-91)sebs/cache.py (3)
Cache
(59-643)update_nosql
(304-314)update
(18-35)sebs/gcp/config.py (2)
resources
(250-252)region
(235-237)
sebs/azure/config.py (4)
sebs/faas/config.py (15)
initialize
(161-176)initialize
(265-275)Credentials
(23-61)update_cache
(210-225)update_cache
(332-341)serialize
(55-61)serialize
(194-208)serialize
(320-329)Resources
(64-225)region
(120-123)region
(126-128)region
(247-249)credentials
(253-255)resources
(259-261)Config
(228-341)sebs/cache.py (2)
Cache
(59-643)update_config
(128-141)sebs/azure/cloud_resources.py (4)
account_name
(19-21)from_cache
(47-56)from_allocation
(59-84)CosmosDBAccount
(14-142)sebs/azure/cli.py (1)
AzureCLI
(12-142)
sebs/local/local.py (7)
sebs/faas/system.py (15)
name
(549-555)function_type
(98-104)config
(87-89)cache_client
(68-70)docker_client
(63-65)initialize_resources
(119-171)shutdown
(533-545)system_resources
(92-94)create_function
(225-245)update_function
(260-276)create_trigger
(510-518)cached_function
(248-257)update_function_configuration
(398-409)download_metrics
(486-507)enforce_cold_start
(473-483)sebs/faas/function.py (11)
name
(621-623)config
(616-618)benchmark
(626-628)FunctionConfig
(508-587)get
(305-316)Function
(590-706)trigger_type
(383-385)Trigger
(288-425)TriggerType
(298-316)triggers
(654-664)ExecutionResult
(196-285)sebs/local/config.py (4)
typename
(159-161)LocalConfig
(150-242)resources
(183-185)resources
(188-190)sebs/local/function.py (9)
typename
(25-27)typename
(156-158)LocalFunction
(77-213)container
(136-138)container
(141-143)url
(146-148)stop
(205-213)trigger_type
(30-32)HTTPTrigger
(10-74)sebs/storage/resources.py (3)
SelfHostedSystemResources
(171-277)storage_config
(44-46)get_nosql_storage
(245-277)sebs/utils.py (7)
logging_handlers
(385-387)logging_handlers
(390-425)logging
(377-382)info
(274-278)is_linux
(441-447)error
(286-290)warning
(280-284)sebs/local/deployment.py (1)
shutdown
(123-184)
sebs/storage/scylladb.py (7)
sebs/aws/dynamodb.py (8)
retrieve_cache
(57-74)update_cache
(76-88)get_tables
(90-97)_get_table_name
(99-113)write_to_table
(115-142)create_table
(144-224)clear_table
(226-235)remove_table
(237-246)sebs/storage/minio.py (8)
config
(58-60)config
(63-65)start
(90-146)stop
(191-205)configure_connection
(148-189)serialize
(498-504)_deserialize
(509-556)deserialize
(559-570)sebs/faas/nosql.py (8)
retrieve_cache
(76-85)update_cache
(88-94)get_tables
(53-62)_get_table_name
(65-73)write_to_table
(160-177)create_table
(140-157)clear_table
(180-192)remove_table
(195-202)sebs/storage/config.py (9)
ScyllaDBConfig
(144-205)serialize
(19-25)serialize
(102-111)serialize
(134-140)serialize
(199-205)deserialize
(84-100)deserialize
(186-197)update_cache
(66-81)update_cache
(173-183)sebs/cache.py (3)
Cache
(59-643)get_nosql_config
(265-273)update_nosql
(304-314)sebs/utils.py (2)
project_absolute_path
(21-28)info
(274-278)sebs/storage/resources.py (1)
_deserialize
(145-168)
sebs/sebs.py (10)
sebs/faas/system.py (5)
cache_client
(68-70)docker_client
(63-65)config
(87-89)name
(549-555)shutdown
(533-545)sebs/cache.py (2)
Cache
(59-643)shutdown
(151-166)sebs/experiments/experiment.py (3)
config
(31-33)Experiment
(11-55)name
(37-44)sebs/config.py (4)
SeBSConfig
(7-229)supported_architecture
(113-120)supported_container_deployment
(131-138)supported_package_deployment
(122-129)sebs/utils.py (4)
LoggingHandlers
(312-347)logging_handlers
(385-387)logging_handlers
(390-425)has_platform
(428-438)sebs/experiments/config.py (1)
Config
(6-123)sebs/faas/config.py (1)
Config
(228-341)sebs/benchmark.py (2)
deserialize
(94-108)Benchmark
(111-1059)sebs/types.py (2)
Storage
(24-31)NoSQLStorage
(34-41)sebs/storage/config.py (4)
PersistentStorageConfig
(11-35)MinioConfig
(39-123)NoSQLStorageConfig
(127-140)ScyllaDBConfig
(144-205)
sebs/faas/config.py (8)
sebs/utils.py (3)
LoggingBase
(350-425)LoggingHandlers
(312-347)serialize
(58-71)sebs/aws/config.py (16)
deserialize
(66-114)deserialize
(159-166)deserialize
(482-512)deserialize
(558-585)serialize
(124-131)serialize
(168-175)serialize
(438-456)serialize
(600-614)initialize
(56-63)initialize
(413-436)initialize
(545-555)update_cache
(116-122)update_cache
(458-479)update_cache
(587-598)credentials
(534-536)resources
(539-541)sebs/faas/system.py (3)
config
(87-89)name
(549-555)initialize
(173-184)sebs/cache.py (1)
Cache
(59-643)sebs/azure/config.py (10)
serialize
(142-149)serialize
(219-225)initialize
(91-99)initialize
(520-544)initialize
(619-629)update_cache
(151-157)update_cache
(506-517)update_cache
(661-672)credentials
(608-610)resources
(613-615)sebs/local/config.py (10)
serialize
(12-19)serialize
(63-73)serialize
(217-230)initialize
(76-90)initialize
(164-174)update_cache
(92-101)update_cache
(232-242)credentials
(178-180)resources
(183-185)resources
(188-190)sebs/gcp/config.py (9)
region
(235-237)initialize
(54-61)initialize
(152-165)initialize
(298-311)update_cache
(129-135)update_cache
(207-215)update_cache
(330-340)credentials
(245-247)resources
(250-252)sebs/openwhisk/config.py (5)
initialize
(94-108)update_cache
(152-164)update_cache
(315-336)credentials
(227-229)resources
(232-234)
sebs/experiments/environment.py (4)
sebs/azure/cli.py (1)
execute
(73-88)sebs/gcp/cli.py (1)
execute
(76-91)sebs/utils.py (1)
execute
(74-102)sebs/regression.py (1)
status
(570-616)
sebs/faas/storage.py (7)
sebs/utils.py (3)
LoggingBase
(350-425)logging
(377-382)info
(274-278)sebs/aws/s3.py (13)
deployment_name
(20-22)replace_existing
(25-27)replace_existing
(30-32)correct_name
(64-71)list_buckets
(213-224)_create_bucket
(73-133)download
(173-182)upload
(162-171)list_bucket
(197-211)exists_bucket
(184-195)clean_bucket
(226-235)remove_bucket
(237-243)uploader_func
(135-160)sebs/azure/blob_storage.py (11)
deployment_name
(20-22)correct_name
(69-77)list_buckets
(79-94)_create_bucket
(44-67)download
(125-136)upload
(138-149)list_bucket
(160-181)exists_bucket
(151-158)clean_bucket
(183-193)remove_bucket
(195-201)uploader_func
(96-123)sebs/gcp/storage.py (13)
deployment_name
(22-24)replace_existing
(27-29)replace_existing
(32-34)correct_name
(54-65)list_buckets
(190-201)_create_bucket
(67-119)download
(121-132)upload
(134-158)list_bucket
(177-188)exists_bucket
(160-175)clean_bucket
(216-232)remove_bucket
(203-213)uploader_func
(235-265)sebs/storage/minio.py (11)
deployment_name
(30-32)correct_name
(402-413)list_buckets
(467-478)_create_bucket
(224-270)download
(415-433)upload
(480-495)list_bucket
(445-465)exists_bucket
(436-443)clean_bucket
(366-385)remove_bucket
(388-399)uploader_func
(272-300)sebs/cache.py (3)
Cache
(59-643)get_storage_config
(255-263)update_storage
(292-302)sebs/faas/config.py (6)
region
(120-123)region
(126-128)region
(247-249)resources
(259-261)Resources
(64-225)StorageBucketType
(71-89)
sebs/storage/minio.py (10)
sebs/cache.py (2)
typename
(93-97)Cache
(59-643)sebs/local/local.py (3)
typename
(39-41)config
(49-51)name
(34-36)sebs/storage/scylladb.py (6)
typename
(27-29)config
(37-39)serialize
(254-261)_deserialize
(266-306)configure_connection
(162-213)deserialize
(309-320)sebs/aws/s3.py (12)
replace_existing
(25-27)replace_existing
(30-32)_create_bucket
(73-133)uploader_func
(135-160)clean_bucket
(226-235)remove_bucket
(237-243)correct_name
(64-71)download
(173-182)exists_bucket
(184-195)list_bucket
(197-211)list_buckets
(213-224)upload
(162-171)sebs/azure/blob_storage.py (10)
_create_bucket
(44-67)uploader_func
(96-123)clean_bucket
(183-193)remove_bucket
(195-201)correct_name
(69-77)download
(125-136)exists_bucket
(151-158)list_bucket
(160-181)list_buckets
(79-94)upload
(138-149)sebs/faas/storage.py (15)
cache_client
(40-42)replace_existing
(45-47)replace_existing
(50-52)_create_bucket
(118-132)uploader_func
(312-323)input_prefixes
(81-83)get_bucket
(276-309)clean_bucket
(190-196)remove_bucket
(199-205)correct_name
(91-98)download
(135-143)exists_bucket
(180-187)list_bucket
(159-167)list_buckets
(170-177)upload
(146-156)sebs/gcp/storage.py (12)
replace_existing
(27-29)replace_existing
(32-34)_create_bucket
(67-119)uploader_func
(235-265)clean_bucket
(216-232)remove_bucket
(203-213)correct_name
(54-65)download
(121-132)exists_bucket
(160-175)list_bucket
(177-188)list_buckets
(190-201)upload
(134-158)sebs/storage/config.py (7)
MinioConfig
(39-123)serialize
(19-25)serialize
(102-111)serialize
(134-140)serialize
(199-205)deserialize
(84-100)deserialize
(186-197)sebs/utils.py (6)
project_absolute_path
(21-28)is_linux
(441-447)logging
(377-382)error
(286-290)info
(274-278)serialize
(58-71)sebs/storage/resources.py (1)
_deserialize
(145-168)
sebs/faas/system.py (6)
sebs/utils.py (4)
LoggingBase
(350-425)logging
(377-382)error
(286-290)info
(274-278)sebs/cache.py (1)
Cache
(59-643)sebs/faas/resources.py (2)
SystemResources
(13-59)get_storage
(36-47)sebs/faas/function.py (17)
config
(616-618)Function
(590-706)deserialize
(57-66)deserialize
(87-96)deserialize
(119-128)deserialize
(181-193)deserialize
(271-285)deserialize
(418-425)deserialize
(435-446)deserialize
(459-470)deserialize
(494-501)deserialize
(555-571)deserialize
(697-706)benchmark
(626-628)trigger_type
(383-385)Trigger
(288-425)TriggerType
(298-316)sebs/faas/config.py (5)
Config
(228-341)initialize
(161-176)initialize
(265-275)resources
(259-261)Resources
(64-225)sebs/benchmark.py (8)
code_package
(150-155)Benchmark
(111-1059)functions
(158-163)code_location
(166-177)deserialize
(94-108)benchmark
(135-137)language
(213-215)language_version
(223-225)
sebs/cache.py (9)
sebs/utils.py (6)
LoggingBase
(350-425)logging
(377-382)error
(286-290)info
(274-278)serialize
(58-71)warning
(280-284)sebs/faas/system.py (4)
shutdown
(533-545)name
(549-555)update_function
(260-276)config
(87-89)sebs/aws/aws.py (5)
typename
(43-45)shutdown
(577-579)name
(38-40)update_function
(363-419)config
(53-55)sebs/benchmark.py (13)
typename
(130-132)benchmark
(135-137)language_version
(223-225)architecture
(243-245)language
(213-215)language_name
(218-220)container_deployment
(248-250)code_location
(166-177)serialize
(393-399)container_uri
(208-210)hash
(253-262)hash
(265-271)code_size
(203-205)sebs/local/local.py (5)
typename
(39-41)shutdown
(111-117)name
(34-36)update_function
(341-361)config
(49-51)sebs/openwhisk/openwhisk.py (5)
typename
(153-155)shutdown
(117-145)name
(148-150)update_function
(349-398)config
(113-115)sebs/faas/function.py (9)
get
(305-316)benchmark
(626-628)serialize
(408-414)serialize
(454-456)serialize
(485-491)serialize
(573-587)serialize
(677-693)name
(621-623)config
(616-618)sebs/azure/azure.py (4)
shutdown
(99-102)name
(39-41)update_function
(303-349)config
(44-46)sebs/local/deployment.py (1)
shutdown
(123-184)
sebs/openwhisk/openwhisk.py (7)
sebs/utils.py (7)
LoggingHandlers
(312-347)logging
(377-382)info
(274-278)error
(286-290)warning
(280-284)logging_handlers
(385-387)logging_handlers
(390-425)sebs/faas/system.py (21)
config
(87-89)System
(26-555)system_config
(58-60)cache_client
(68-70)docker_client
(63-65)initialize
(173-184)initialize_resources
(119-171)shutdown
(533-545)name
(549-555)function_type
(98-104)package_code
(187-222)system_resources
(92-94)create_function
(225-245)update_function
(260-276)create_trigger
(510-518)update_function_configuration
(398-409)is_configuration_changed
(411-455)cached_function
(248-257)default_function_name
(458-470)enforce_cold_start
(473-483)disable_rich_output
(520-525)sebs/openwhisk/function.py (5)
config
(109-111)OpenWhiskFunction
(89-155)OpenWhiskFunctionConfig
(12-86)typename
(114-116)from_benchmark
(71-86)sebs/openwhisk/config.py (5)
OpenWhiskConfig
(186-336)resources
(232-234)initialize
(94-108)initialize
(237-254)typename
(64-66)sebs/storage/resources.py (5)
SelfHostedSystemResources
(171-277)get_storage
(201-243)storage_config
(44-46)get_nosql_storage
(245-277)nosql_storage_config
(49-51)tools/openwhisk_preparation.py (1)
delete_cluster
(209-215)sebs/openwhisk/triggers.py (8)
typename
(79-80)typename
(90-91)LibraryTrigger
(10-80)trigger_type
(18-19)trigger_type
(94-95)HTTPTrigger
(83-111)wsk_cmd
(22-24)wsk_cmd
(27-28)
🪛 Pylint (3.3.7)
sebs/aws/config.py
[refactor] 134-134: Too many instance attributes (8/7)
(R0902)
sebs/local/deployment.py
[refactor] 123-123: Too many branches (13/12)
(R0912)
sebs/local/function.py
[refactor] 83-83: Too many arguments (8/5)
(R0913)
[refactor] 83-83: Too many positional arguments (8/5)
(R0917)
sebs/experiments/eviction_model.py
[refactor] 195-195: Too many arguments (6/5)
(R0913)
[refactor] 195-195: Too many positional arguments (6/5)
(R0917)
[refactor] 195-195: Too many local variables (17/15)
(R0914)
sebs/experiments/network_ping_pong.py
[refactor] 163-163: Too many local variables (21/15)
(R0914)
sebs/gcp/storage.py
[refactor] 198-201: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it
(R1705)
sebs/storage/resources.py
[error] 97-97: Undefined variable 'Dict'
(E0602)
[error] 97-97: Undefined variable 'Type'
(E0602)
[error] 97-97: Undefined variable 'Type'
(E0602)
[refactor] 125-138: Unnecessary "elif" after "return", remove the leading "el" from "elif"
(R1705)
[refactor] 178-178: Too many arguments (6/5)
(R0913)
[refactor] 178-178: Too many positional arguments (6/5)
(R0917)
sebs/config.py
[refactor] 187-190: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it
(R1705)
sebs/openwhisk/function.py
[error] 43-43: Class 'OpenWhiskFunctionConfig' has no 'dataclass_fields' member
(E1101)
sebs/experiments/invocation_overhead.py
[error] 90-90: Undefined variable 'settings_'
(E0602)
[refactor] 71-71: Too few public methods (1/2)
(R0903)
[refactor] 354-354: Too many local variables (25/15)
(R0914)
sebs/storage/config.py
[refactor] 39-39: Too many instance attributes (10/7)
(R0902)
[error] 75-75: Instance of 'MinioConfig' has no 'dataclass_fields' member
(E1101)
[error] 93-93: Class 'MinioConfig' has no 'dataclass_fields' member
(E1101)
[refactor] 144-144: Too many instance attributes (11/7)
(R0902)
[error] 182-182: Instance of 'ScyllaDBConfig' has no 'dataclass_fields' member
(E1101)
[error] 195-195: Class 'ScyllaDBConfig' has no 'dataclass_fields' member
(E1101)
sebs/faas/function.py
[refactor] 23-23: Too few public methods (1/2)
(R0903)
[refactor] 69-69: Too few public methods (1/2)
(R0903)
[refactor] 99-99: Too few public methods (1/2)
(R0903)
[error] 263-263: Instance of 'ExecutionResult' has no 'logging' member
(E1101)
[error] 266-266: Instance of 'ExecutionResult' has no 'logging' member
(E1101)
[error] 563-563: Class 'FunctionConfig' has no 'dataclass_fields' member
(E1101)
sebs/openwhisk/config.py
[refactor] 186-186: Too many instance attributes (8/7)
(R0902)
sebs/local/local.py
[refactor] 119-119: Too many arguments (8/5)
(R0913)
[refactor] 119-119: Too many positional arguments (8/5)
(R0917)
[refactor] 119-119: Too many local variables (21/15)
(R0914)
[refactor] 191-191: Too many local variables (21/15)
(R0914)
[error] 229-229: Undefined variable 'Any'
(E0602)
[refactor] 191-191: Too many branches (15/12)
(R0912)
[refactor] 277-282: Consider using 'with' for resource-allocating operations
(R1732)
[error] 401-401: Undefined variable 'HTTPTrigger'
(E0602)
[refactor] 420-420: Too many arguments (6/5)
(R0913)
[refactor] 420-420: Too many positional arguments (6/5)
(R0917)
sebs/sebs.py
[refactor] 117-117: Too many local variables (16/15)
(R0914)
sebs/faas/storage.py
[refactor] 21-21: Too many instance attributes (8/7)
(R0902)
sebs/aws/s3.py
[refactor] 221-224: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it
(R1705)
sebs/utils.py
[error] 38-38: Undefined variable 'Any'
(E0602)
[error] 38-38: Undefined variable 'Any'
(E0602)
[refactor] 45-55: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it
(R1705)
[error] 58-58: Undefined variable 'Any'
(E0602)
[refactor] 67-71: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it
(R1705)
[error] 105-105: Undefined variable 'Any'
(E0602)
[error] 205-205: Instance of 'RootLogger' has no 'loggerDict' member
(E1101)
[refactor] 312-312: Too few public methods (0/2)
(R0903)
sebs/faas/system.py
[refactor] 26-26: Too many public methods (24/20)
(R0904)
sebs/regression.py
[error] 68-68: Undefined variable 'List'
(E0602)
[error] 70-70: Undefined variable 'List'
(E0602)
[refactor] 91-91: Too many arguments (9/5)
(R0913)
[refactor] 91-91: Too many positional arguments (9/5)
(R0917)
[error] 96-96: Undefined variable 'List'
(E0602)
[error] 97-97: Undefined variable 'List'
(E0602)
[error] 98-98: Undefined variable 'List'
(E0602)
[error] 100-100: Undefined variable 'List'
(E0602)
[error] 315-315: Class 'AzureTestSequencePython' has no 'lock' member
(E1101)
[error] 317-317: Instance of 'AzureTestSequencePython' has no 'client' member
(E1101)
[error] 320-320: Instance of 'AzureTestSequencePython' has no 'client' member
(E1101)
[error] 372-372: Class 'AzureTestSequenceNodejs' has no 'lock' member
(E1101)
[error] 374-374: Instance of 'AzureTestSequenceNodejs' has no 'client' member
(E1101)
[error] 497-497: Undefined variable 'json'
(E0602)
[error] 497-497: Undefined variable 'json'
(E0602)
[error] 541-541: Undefined variable 'json'
(E0602)
[error] 541-541: Undefined variable 'json'
(E0602)
[refactor] 660-660: Too many local variables (18/15)
(R0914)
[refactor] 660-660: Too many branches (24/12)
(R0912)
[refactor] 660-660: Too many statements (61/50)
(R0915)
sebs/cache.py
[refactor] 49-54: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it
(R1705)
[refactor] 145-145: Consider using 'with' for resource-allocating operations
(R1732)
[refactor] 354-354: Too many local variables (23/15)
(R0914)
[refactor] 446-446: Too many local variables (21/15)
(R0914)
sebs/benchmark.py
[refactor] 172-177: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it
(R1705)
[refactor] 273-273: Too many arguments (8/5)
(R0913)
[refactor] 273-273: Too many positional arguments (8/5)
(R0917)
[refactor] 643-643: Too many local variables (26/15)
(R0914)
[error] 748-748: Undefined variable 'tarfile'
(E0602)
[error] 763-763: Undefined variable 'cmd'
(E0602)
[error] 779-779: Undefined variable 'tarfile'
(E0602)
[refactor] 643-643: Too many branches (14/12)
(R0912)
[refactor] 643-643: Too many statements (67/50)
(R0915)
[refactor] 890-890: Too many local variables (17/15)
(R0914)
[refactor] 1093-1093: Too many arguments (7/5)
(R0913)
[refactor] 1093-1093: Too many positional arguments (7/5)
(R0917)
sebs/openwhisk/openwhisk.py
[refactor] 175-175: Too many arguments (8/5)
(R0913)
[refactor] 175-175: Too many positional arguments (8/5)
(R0917)
[error] 228-228: Undefined variable 'zipfile'
(E0602)
[refactor] 545-554: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it
(R1705)
[refactor] 570-590: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it
(R1705)
sebs/gcp/gcp.py
[refactor] 37-37: Too many public methods (24/20)
(R0904)
[refactor] 371-371: Boolean condition "iam_error.resp.status == 400 and "Policy can't be set while the function is being updated"" may be simplified to "iam_error.resp.status == 400"
(R1726)
[refactor] 423-423: Too many local variables (16/15)
(R0914)
[refactor] 438-492: Unnecessary "elif" after "return", remove the leading "el" from "elif"
(R1705)
[refactor] 455-461: Unnecessary "else" after "break", remove the "else" and de-indent the code inside it
(R1723)
[refactor] 479-489: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it
(R1705)
[refactor] 639-639: Too many local variables (17/15)
(R0914)
[error] 669-669: Undefined variable 'Any'
(E0602)
[refactor] 741-741: Too many arguments (6/5)
(R0913)
[refactor] 741-741: Too many positional arguments (6/5)
(R0917)
[refactor] 741-741: Too many local variables (34/15)
(R0914)
[refactor] 741-741: Too many branches (14/12)
(R0912)
[refactor] 741-741: Too many statements (53/50)
(R0915)
[error] 770-770: No name 'logging' in module 'google.cloud'
(E0611)
[refactor] 1024-1027: Unnecessary "else" after "return", remove the "else" and de-indent the code inside it
(R1705)
[refactor] 1093-1093: Consider using 'with' for resource-allocating operations
(R1732)
🪛 Ruff (0.11.9)
sebs/local/function.py
203-203: Within an except
clause, raise exceptions with raise ... from err
or raise ... from None
to distinguish them from errors in exception handling
(B904)
sebs/gcp/storage.py
68-68: Do not use mutable data structures for argument defaults
Replace with None
; initialize within function
(B006)
258-261: Use a single if
statement instead of nested if
statements
(SIM102)
sebs/experiments/config.py
47-47: Use self._flags.get(key, False)
instead of an if
block
Replace with self._flags.get(key, False)
(SIM401)
sebs/storage/resources.py
97-97: Undefined name Dict
(F821)
97-97: Undefined name Type
(F821)
97-97: Undefined name Type
(F821)
sebs/experiments/invocation_overhead.py
90-90: Undefined name settings_
(F821)
sebs/azure/blob_storage.py
45-45: Do not use mutable data structures for argument defaults
Replace with None
; initialize within function
(B006)
sebs/storage/config.py
75-75: Use key in dict
instead of key in dict.keys()
Remove .keys()
(SIM118)
182-182: Use key in dict
instead of key in dict.keys()
Remove .keys()
(SIM118)
sebs/gcp/datastore.py
244-244: Within an except
clause, raise exceptions with raise ... from err
or raise ... from None
to distinguish them from errors in exception handling
(B904)
sebs/local/local.py
180-180: Loop control variable dirs
not used within loop body
Rename unused dirs
to _dirs
(B007)
229-229: Undefined name Any
(F821)
312-315: Within an except
clause, raise exceptions with raise ... from err
or raise ... from None
to distinguish them from errors in exception handling
(B904)
401-401: Undefined name HTTPTrigger
(F821)
sebs/statistics.py
29-32: Use ternary operator cv_val = np.nan if mean_val == 0 else std_val / mean_val * 100
instead of if
-else
-block
Replace if
-else
-block with cv_val = np.nan if mean_val == 0 else std_val / mean_val * 100
(SIM108)
97-97: Local variable low_idx
is assigned to but never used
Remove assignment to unused variable low_idx
(F841)
98-98: Local variable high_idx
is assigned to but never used
Remove assignment to unused variable high_idx
(F841)
sebs/faas/storage.py
119-119: Do not use mutable data structures for argument defaults
Replace with None
; initialize within function
(B006)
sebs/aws/s3.py
74-74: Do not use mutable data structures for argument defaults
Replace with None
; initialize within function
(B006)
sebs/utils.py
38-38: Undefined name Any
(F821)
38-38: Undefined name Any
(F821)
58-58: Undefined name Any
(F821)
89-92: Use ternary operator command_list = cmd.split() if not shell else cmd
instead of if
-else
-block
(SIM108)
105-105: Undefined name Any
(F821)
400-401: Use a single if
statement instead of nested if
statements
(SIM102)
sebs/faas/system.py
173-173: Do not use mutable data structures for argument defaults
Replace with None
; initialize within function
(B006)
327-327: Local variable code_location
is assigned to but never used
Remove assignment to unused variable code_location
(F841)
sebs/regression.py
68-68: Undefined name List
(F821)
70-70: Undefined name List
(F821)
96-96: Undefined name List
(F821)
97-97: Undefined name List
(F821)
98-98: Undefined name List
(F821)
100-100: Undefined name List
(F821)
242-242: Local variable log_file_name
is assigned to but never used
Remove assignment to unused variable log_file_name
(F841)
278-278: Local variable log_file_name
is assigned to but never used
Remove assignment to unused variable log_file_name
(F841)
422-422: Local variable log_file_name
is assigned to but never used
Remove assignment to unused variable log_file_name
(F841)
457-457: Local variable log_file_name
is assigned to but never used
Remove assignment to unused variable log_file_name
(F841)
497-497: Undefined name json
(F821)
497-497: Undefined name json
(F821)
502-502: Local variable log_file_name
is assigned to but never used
Remove assignment to unused variable log_file_name
(F841)
541-541: Undefined name json
(F821)
541-541: Undefined name json
(F821)
545-545: Local variable log_file_name
is assigned to but never used
Remove assignment to unused variable log_file_name
(F841)
642-644: Use a single if
statement instead of nested if
statements
(SIM102)
647-648: Use a single if
statement instead of nested if
statements
(SIM102)
651-653: Use a single if
statement instead of nested if
statements
(SIM102)
744-744: Do not call setattr
with a constant attribute value. It is not any safer than normal property access.
Replace setattr
with assignment
(B010)
745-745: Do not call setattr
with a constant attribute value. It is not any safer than normal property access.
Replace setattr
with assignment
(B010)
sebs/cache.py
421-421: Local variable new_entry_structure
is assigned to but never used
Remove assignment to unused variable new_entry_structure
(F841)
624-624: Loop control variable deployment_key
not used within loop body
Rename unused deployment_key
to _deployment_key
(B007)
sebs/benchmark.py
541-541: Local variable f
is assigned to but never used
Remove assignment to unused variable f
(F841)
694-694: f-string without any placeholders
Remove extraneous f
prefix
(F541)
748-748: Undefined name tarfile
(F821)
763-763: Undefined name cmd
(F821)
779-779: Undefined name tarfile
(F821)
1043-1044: Use a single with
statement with multiple contexts instead of nested with
statements
(SIM117)
sebs/openwhisk/openwhisk.py
16-16: sebs.gcp.function.GCPFunction
imported but unused
Remove unused import: sebs.gcp.function.GCPFunction
(F401)
100-100: Do not use mutable data structures for argument defaults
Replace with None
; initialize within function
(B006)
228-228: Undefined name zipfile
(F821)
333-333: Within an except
clause, raise exceptions with raise ... from err
or raise ... from None
to distinguish them from errors in exception handling
(B904)
337-337: Within an except
clause, raise exceptions with raise ... from err
or raise ... from None
to distinguish them from errors in exception handling
(B904)
394-394: Within an except
clause, raise exceptions with raise ... from err
or raise ... from None
to distinguish them from errors in exception handling
(B904)
398-398: Within an except
clause, raise exceptions with raise ... from err
or raise ... from None
to distinguish them from errors in exception handling
(B904)
427-427: Within an except
clause, raise exceptions with raise ... from err
or raise ... from None
to distinguish them from errors in exception handling
(B904)
430-430: Within an except
clause, raise exceptions with raise ... from err
or raise ... from None
to distinguish them from errors in exception handling
(B904)
562-562: Within an except
clause, raise exceptions with raise ... from err
or raise ... from None
to distinguish them from errors in exception handling
(B904)
565-565: Within an except
clause, raise exceptions with raise ... from err
or raise ... from None
to distinguish them from errors in exception handling
(B904)
sebs/gcp/gcp.py
92-92: Do not use mutable data structures for argument defaults
Replace with None
; initialize within function
(B006)
203-203: Local variable package_config_exclusions
is assigned to but never used
Remove assignment to unused variable package_config_exclusions
(F841)
378-378: Within an except
clause, raise exceptions with raise ... from err
or raise ... from None
to distinguish them from errors in exception handling
(B904)
640-640: Do not use mutable data structures for argument defaults
Replace with None
; initialize within function
(B006)
669-669: Undefined name Any
(F821)
🪛 Gitleaks (8.26.0)
sebs/gcp/storage.py
149-149: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
🔇 Additional comments (114)
sebs/__init__.py (1)
1-8
: Docstring addition looks good and comprehensive.The updated module-level docstring provides a clear one-line summary and a detailed description of the package’s purpose and included modules. No issues found.
sebs/experiments/startup_time.py (3)
6-11
: Docstring is clear and descriptive.The class-level docstring concisely explains the experiment’s purpose and notes its placeholder status. Perfect for maintainability.
13-17
: Constructor docstring is correctly formatted.Parameters are documented with Sphinx-style
:param:
annotations. No changes needed.
22-24
: Static method docstrings are concise and appropriate.Simple return descriptions are sufficient for these methods.
sebs/types.py (4)
5-8
: Enum classBenchmarkModule
docstring is clear.Describes purpose and usage of the enum values. Good job.
14-16
: Enum classPlatforms
docstring is well-written.Enumerates supported platforms succinctly.
25-27
: Enum classStorage
docstring is informative.Explains the storage types and their contexts.
35-37
: Enum classNoSQLStorage
docstring is comprehensive.Clearly documents the supported NoSQL services.
sebs/experiments/experiment.py (4)
12-17
: Abstract base class docstring is descriptive.Provides clear guidance on subclass responsibilities.
19-23
: Constructor docstring follows project conventions.Sphinx-style parameter annotation is correctly used.
31-33
: Propertyconfig
docstring is concise.Describes the return value clearly.
49-54
:typename()
docstring is clear.Describes expected format and return value properly.
sebs/azure/triggers.py (11)
9-14
: ClassAzureTrigger
docstring is comprehensive.Clearly outlines the purpose and context for Azure storage account usage.
16-20
: Constructor docstring is well-documented.Parameters are explained with correct Sphinx-style annotations.
26-29
: Propertydata_storage_account
docstring is appropriate.Specifies the return type and context clearly.
31-34
: Setter docstring is correctly formatted.Describes the setter functionality succinctly.
37-39
: ClassHTTPTrigger
docstring is clear.Summarizes its role and invocation mechanism.
41-46
: Constructor docstring follows conventions.All parameters are correctly annotated.
52-53
: Methodtrigger_type
docstring is concise.Describes the returned trigger type.
56-61
: Methodsync_invoke
docstring is well-described.Documents parameters and return type accurately.
65-72
: Methodasync_invoke
docstring is detailed.Explains threading behavior and return value clearly.
79-83
: Methodserialize
docstring is appropriate.Describes the serialization output clearly.
87-92
: Methoddeserialize
docstring is complete.Includes parameter requirements and return type.
sebs/local/measureMem.py (1)
35-46
: Indentation is inconsistent – potentialIndentationError
.
time_start = …
is on the same indentation level aswhile True:
instead of being nested inside it. Double-check spacing; the file might not run.sebs/openwhisk/container.py (1)
63-81
: Guard against missing registry URL fields.
registry_url = self.config.resources.docker_registry
assumesself.config.resources
is notNone
.
If the OpenWhisk configuration omits a docker registry section this will raise. Consider:- registry_url = self.config.resources.docker_registry + registry_url = getattr(self.config.resources, "docker_registry", None)sebs/azure/cloud_resources.py (7)
6-11
: Module docstring is clear and descriptive
The module-level docstring provides a concise summary and an extended overview, following PEP-257 guidelines.
15-17
: Class docstring accurately describes purpose
TheCosmosDBAccount
class docstring is succinct and informative, capturing its role and attributes.
19-31
: Property docstrings are precise
Each property (account_name
,url
,credential
) has a one-line docstring that clearly states its return value.
34-40
: Constructor docstring is thorough
__init__
doc covers all parameters and their meaning, matching the signature.
48-56
: Factory method docstrings cover params and return
Docstrings forfrom_cache
andfrom_allocation
enumerate parameters and describe returned instances.Also applies to: 62-70
88-95
: Query method docstrings are complete
query_url
andquery_credentials
docstrings explain the Azure CLI calls, parameters, and return types.Also applies to: 105-112
123-127
: Serialization docstrings are consistent
serialize
anddeserialize
methods have clear parameter and return value descriptions, aiding maintainability.Also applies to: 135-141
sebs/gcp/cli.py (6)
12-17
: Class docstring clearly defines purpose
TheGCloudCLI
class docstring explains its role and container-based approach succinctly.
19-21
: Typename docstring is appropriate
Thetypename
method has a precise one-line docstring matching its behavior.
26-36
: Constructor docstring is detailed
__init__
doc lists image pull behavior, parameters, and raised exceptions, aligning with implementation.
76-83
: Execute method docstring is accurate
The doc covers the command semantics, return type, and error handling for non-zero exit codes.
94-107
: Login method docstring is comprehensive
Covers authentication flow, credential mounting, project configuration, and interactive prompts.
113-117
: Shutdown method docstring is sufficient
Clearly indicates the action of stopping the Docker container.sebs/experiments/config.py (6)
7-13
: Class docstring effectively summarizes Config
Provides a one-line summary and extended description of experiment configuration responsibilities.
15-15
: Initializer docstring is concise
__init__
doc clearly states its role and default initialization behavior.
27-28
: Property docstrings are consistent
Docstrings forupdate_code
,update_storage
,runtime
,architecture
, andcontainer_deployment
are all precise and uniform.Also applies to: 37-38, 51-52, 55-57, 61-62
65-70
: Experiment settings docstring is clear
Describes the parameter and return value forexperiment_settings
accurately.
74-78
: Serialization docstring is complete
serialize
doc covers the method’s output structure, aiding caching and debugging.
93-102
: Deserialization docstring is thorough
Explains how aConfig
instance is reconstructed from a dict, listing parameters and return type.sebs/aws/resources.py (7)
17-17
: Class docstring concisely states responsibility
Summarizes the resource management role for AWS S3 and DynamoDB.
20-21
: Typename docstring matches return
Provides a clear description of thetypename
method’s output.
25-26
: Config property docstring is accurate
Clarifies thatconfig
returns the AWS-specific configuration.
36-42
: Constructor docstring is well-defined
Lists all parameters for__init__
and their roles in initializing AWS resources.
52-55
: Session initialization docstring is clear
Covers the purpose and parameter forinitialize_session
.
60-69
: get_storage docstring is comprehensive
Describes behavior, parameters, defaults, and return type for persistent storage retrieval.
89-94
: get_nosql_storage docstring is precise
Explains the method’s initialization logic and return type for DynamoDB client.sebs/gcp/function.py (6)
9-14
: Class docstring succinctly explains GCPFunction
Captures inheritance and GCP-specific extension details clearly.
23-31
: Constructor docstring covers all params
Describes name, benchmark, hash, config, and optional bucket parameter.
37-38
: Typename docstring is correct
Matches the static method’s output format.
41-47
: Serialize method docstring is complete
Details inclusion of base and GCP-specific fields in the output dict.
55-62
: Deserialize method docstring is informative
Describes the reconstruction process, parameters, and return object.
83-93
: Bucket assignment method docstring is clear
Explains the conditional logic for assigning or retrieving the bucket usingGCPStorage
.sebs/aws/triggers.py (3)
12-15
: LGTM!Clear and accurate class documentation.
17-22
: LGTM!Well-documented constructor parameters.
136-198
: Excellent documentation for HTTPTrigger class.All methods are well-documented with clear descriptions of parameters, return values, and behavior.
sebs/aws/container.py (1)
14-105
: Excellent documentation additions for ECRContainer.All methods are thoroughly documented with clear parameter descriptions and return value specifications. The
registry_name
method documentation is particularly comprehensive.sebs/azure/cli.py (1)
13-140
: Comprehensive documentation with valuable implementation notes.All methods are well-documented. The
upload_package
method docstring helpfully notes the current memory limitation and suggests potential solutions for handling large archives.sebs/aws/function.py (2)
9-74
: Well-documented LambdaFunction class.All methods have clear, accurate documentation describing their purpose, parameters, and return values.
98-110
: Verify the intended behavior of always reassigning the bucket.The docstring mentions "Get or assign the S3 bucket", but the implementation always reassigns
self.bucket
without checking if it's already set. This differs from the GCP implementation pattern that checksif not self.bucket:
before assignment.Is this intentional behavior, or should it follow the conditional assignment pattern like GCP?
sebs/statistics.py (1)
38-51
: Good edge case handling for insufficient samples.The addition of the check for fewer than 2 samples is appropriate for Student's t-distribution requirements.
sebs/azure/cosmosdb.py (1)
223-225
:FIXME
comment: choose action or create issueA
FIXME
indicates intentional technical debt. Either implement flexible ID key support or open a tracking issue so it doesn’t get lost.sebs/gcp/triggers.py (1)
60-67
: Busy-wait has no timeout
while not deployed:
loops forever if the function never becomes ACTIVE.
Add a max-wait or number-of-retries parameter to avoid an infinite block and
surface a clear error to the caller.sebs/experiments/eviction_model.py (1)
243-247
: Semaphore release on submit failure looks goodNice catch releasing the semaphore inside the
except
– prevents thread
starvation if submission fails.sebs/azure/blob_storage.py (2)
191-193
: Good refactoring of the clean_bucket method!The refactoring to use list comprehension improves readability and follows Python best practices.
149-149
: ```shell
#!/bin/bashInstall Azure Storage Blob SDK to inspect the upload_blob signature
pip install azure-storage-blob >/dev/null
python - << 'EOF'
import inspect
from azure.storage.blob import BlobClientsig = inspect.signature(BlobClient.upload_blob)
print("Signature of BlobClient.upload_blob:", sig)
EOF</details> <details> <summary>sebs/azure/config.py (2)</summary> `17-689`: **Excellent documentation improvements!** The comprehensive docstrings significantly improve code clarity and maintainability. The parameter descriptions, return types, and exception documentation are particularly helpful. --- `389-389`: ```shell #!/bin/bash # Find the execute method in AzureCLI to inspect its signature grep -R -n "def execute" sebs/azure/cli.py # Show the definition of the AzureCLI.execute method sed -n '1,200p' sebs/azure/cli.py | sed -n '1,50p'
sebs/faas/container.py (2)
144-144
: Good variable rename to avoid shadowing!Renaming
progress
toprogress_display
prevents shadowing theProgress
import and improves code clarity.
16-291
: Excellent documentation and type annotation improvements!The comprehensive docstrings and explicit typing of the
docker_client
parameter improve code clarity and type safety.sebs/local/config.py (1)
11-243
: Excellent documentation and robustness improvements!The comprehensive docstrings and improved caching logic significantly enhance code clarity and reliability. The explicit typing and better error handling are particularly valuable.
sebs/openwhisk/function.py (2)
13-26
: Excellent documentation improvements!The added docstrings are comprehensive, well-structured, and provide clear explanations of class and method purposes, parameters, and return values.
Also applies to: 34-41, 55-61, 71-80, 90-105, 110-110, 115-115, 119-125, 133-140
42-52
: Good defensive programming in deserialization.The filtering of input keys against known dataclass fields prevents errors when extra keys are present in the input data. The conditional deserialization of nested configs only when they're present and non-null is also appropriate.
sebs/storage/resources.py (2)
40-41
: Improved naming clarity, but note the breaking change.The variable names are now more explicit (
_object_storage
and_nosql_storage
), which improves code clarity. However, the serialization keys have also changed from "storage"/"nosql" to "object_storage"/"nosql_storage", which is a breaking change for existing cached configurations.Ensure that any existing cached configurations are migrated or that the system handles the old keys gracefully for backward compatibility.
Also applies to: 67-67, 70-70
83-90
: Good defensive type checking.The
isinstance
checks before callingupdate_cache
ensure that the storage configurations are of the expected types that have theupdate_cache
method.sebs/experiments/result.py (1)
12-17
: Comprehensive documentation and timing enhancements.The documentation additions are thorough and well-written. The new
begin_time
andend_time
instance variables with Optional[float] type annotations properly handle cases where timing might not be set.Also applies to: 26-34, 48-49, 52-52, 56-56, 59-66, 69-85, 98-138
sebs/azure/system_resources.py (1)
17-17
: Excellent documentation and lifecycle management clarification.The comprehensive docstrings clearly explain the purpose and behavior of each method. The comments about CLI lifecycle ownership (lines 131-132, 149) are particularly valuable for understanding resource management.
Also applies to: 20-20, 25-25, 36-44, 53-65, 80-86, 95-102, 121-128, 131-132, 138-147, 149-149, 155-160
sebs/config.py (3)
64-64
: Important type annotation fix.Correcting the return type from
Dict[str, str]
toDict[str, List[str]]
accurately reflects that module packages are lists of package strings.
187-190
: Improved registry validation.The truthiness check for
registry
now properly handles bothNone
and empty string cases, making the method more robust.
214-219
: Cleaner tag construction with improved readability.The refactored code uses descriptive variable names (
base_tag
,sebs_version_val
,full_tag
) and correctly callsself.version()
to get the SeBS version, making the tag construction logic clearer.sebs/experiments/perf_cost.py (1)
21-28
: Docstrings addition looks good – no behavioural change introduced.sebs/faas/nosql.py (1)
10-106
: Great API documentation upgrade – improves clarity without altering behaviour.sebs/azure/azure.py (1)
38-46
: Comprehensive docstrings added – looks fine.sebs/openwhisk/config.py (1)
129-140
: Nested resource deserialization reads the wrong dictionary levelInside
OpenWhiskResources.deserialize
,config
already refers to theresources
sub-dict passed by the caller, yet.get("resources", {})
is called again.
As a result, self-hosted storage is never initialized.- ret._deserialize(ret, config.get("resources", {}), cached_config.get("resources") if cached_config else None) + ret._deserialize(ret, config, cached_config.get("resources") if cached_config else None)Likely an incorrect or invalid review comment.
sebs/faas/storage.py (1)
207-275
: Excellent refactoring of the benchmark_data method!The refactored code is much clearer with:
- Explicit variable names and detailed comments
- Well-structured cache validation logic
- Clear separation of concerns
sebs/benchmark.py (2)
643-793
: Excellent improvements to Docker dependency installation!The refactored
install_dependencies
method includes:
- Robust fallback from versioned to unversioned Docker images
- Support for environments without volume mounting (docker_copy_build_files flag)
- Comprehensive error handling and logging
- Clear separation of logic for different scenarios
464-469
: Great addition of versioned package file support!The implementation properly handles:
- Versioned requirements.txt files for Python (e.g., requirements.txt.3.8)
- Versioned package.json files for Node.js (e.g., package.json.12)
- Fallback to standard filenames if versioned ones don't exist
- Creation of default files when none exist
Also applies to: 536-544, 573-583
sebs/utils.py (2)
47-50
: Good fix for JSONSerializer dict handling!Commenting out the dict to string conversion is correct - it would break standard JSON dict serialization. The detailed comment explaining the issue is helpful.
238-426
: Excellent addition of comprehensive logging infrastructure!The new logging classes provide:
- ColoredWrapper: Beautiful colored console output with millisecond-precision timestamps
- LoggingHandlers: Robust file logging with error handling
- LoggingBase: Standardized logging setup for all SeBS components
This is a well-architected solution that will improve debugging and monitoring capabilities.
sebs/experiments/environment.py (2)
134-170
: Excellent fix for Intel Turbo Boost control!The corrected implementation properly uses
/sys/devices/system/cpu/intel_pstate/no_turbo
path and includes comprehensive documentation explaining the intel_pstate driver behavior.
175-201
: Excellent documentation of intel_pstate frequency control behavior!The detailed comments explain:
- The relationship between min_perf_pct and frequency control
- How it interacts with no_turbo setting
- Potential for also setting max_perf_pct for precise control
This level of documentation is invaluable for understanding the complex CPU frequency scaling behavior.
sebs/sebs.py (1)
146-149
: Import path likely incorrect – verifysebs.azure
module structure
from sebs.azure.azure import Azure
assumes the provider class resides insebs/azure/azure.py
.
In the rest of the code-base the convention issebs.azure
→Azure
(single level).
If the path is wrong anImportError
will occur at runtime when the Azure platform is enabled.Please double-check the package layout.
sebs/gcp/gcp.py (1)
321-331
: Possible wrongentryPoint
for Python functions.The handler file is renamed to
main.py
, yetcreate_body
hard-codes"entryPoint": "handler"
.
For Python,entryPoint
should be the function name inside the module, not the original filename.
Double-check that a top-leveldef handler(request): ...
still exists inmain.py
; otherwise deployments will fail with “Function failed on loading user code”.sebs/aws/aws.py (17)
28-32
: Class docstring is clear and concise.
Accurately summarizes the AWS provider’s responsibilities and scope.
37-51
: Staticmethod docstrings adhere to one-line summary style.
Each@staticmethod
has a clear, actionable description and return details.
52-61
: Property docstrings are well-defined.
config
andsystem_resources
properties include succinct descriptions matching their return types.
70-78
:__init__
docstring covers parameters thoroughly.
Describes all injected dependencies; no missing entries.
113-119
:get_lambda_client
documentation is accurate.
Covers lazy initialization behavior.
199-204
:_map_architecture
docstring is concise and correct.
Covers the mapping logic without excess detail.
425-432
:update_function_configuration
docstring is clear.
Covers configuration updates and parameters precisely.
478-483
:default_function_name
docstring accurately describes behavior.
No further changes needed.
498-506
:format_function_name
documentation is precise.
Clearly explains transformation rules.
577-580
:shutdown
docstring is sufficient.
Matches the method’s simple behavior.
583-590
:get_invocation_error
docstring covers purpose.
Calls out parameters clearly; returningNone
is implied.
689-697
:create_trigger
docstring is comprehensive.
Includes:raises
for unsupported trigger types.
734-740
:_enforce_cold_start
docstring is clear.
Good description of helper behavior.
748-756
:enforce_cold_start
docstring covers process.
Accurately details counter increment and update loop.
767-772
:wait_function_active
documentation is accurate.
Describes waiter usage succinctly.
780-784
:wait_function_updated
docstring is appropriate.
Mirrors the active wait pattern.
792-794
:disable_rich_output
docstring is minimal but sufficient.
One-liner is acceptable for this setter.
def ci_le_boudec(alpha: float, times: List[float]) -> Tuple[float, float]: | ||
""" | ||
Calculate a non-parametric confidence interval based on Le Boudec's method. | ||
|
||
This method uses order statistics and is suitable for distributions that may | ||
not be normal. It requires a sufficient number of samples (related to z_value calculation). | ||
|
||
Reference: "Performance Evaluation of Computer and Communication Systems" by Le Boudec. | ||
|
||
:param alpha: The confidence level (e.g., 0.95 for 95% CI). | ||
:param times: A list of floating-point time measurements. | ||
:return: A tuple (lower_bound, upper_bound) of the confidence interval. | ||
Returns (nan, nan) if the number of samples is too small for the calculation. | ||
:raises AssertionError: If alpha is not one of the supported values (0.95, 0.99). | ||
""" | ||
if not times: | ||
return (np.nan, np.nan) | ||
|
||
sorted_times = sorted(times) | ||
n = len(times) | ||
|
||
# z(alfa/2) | ||
z_value = {0.95: 1.96, 0.99: 2.576}.get(alpha) | ||
assert z_value | ||
# z(alpha/2) - critical value from standard normal distribution | ||
# For a two-sided interval with confidence `alpha`, we need z_{1 - (1-alpha)/2} = z_{(1+alpha)/2} | ||
# However, the formula used by Le Boudec for indices is n/2 +- z * sqrt(n)/2 | ||
# The z_value here corresponds to z_{1 - (1-alpha)/2} | ||
z_critical_value = {0.95: 1.96, 0.99: 2.576}.get(alpha) | ||
assert z_critical_value is not None, f"Unsupported alpha value: {alpha}. Supported values are 0.95, 0.99." | ||
|
||
# Calculate ranks for lower and upper bounds of the CI for the median | ||
# (as per Le Boudec's method for quantiles, here applied to median implicitly) | ||
# Note: The formula in the original code seems to be for median CI. | ||
# low_pos = floor( (n - z * sqrt(n)) / 2 ) | ||
# high_pos = ceil( 1 + (n + z * sqrt(n)) / 2 ) | ||
# These indices are 0-based for the sorted list. | ||
|
||
sqrt_n = math.sqrt(n) | ||
if sqrt_n == 0: # Avoid division by zero if n=0, though caught by earlier check | ||
return (np.nan, np.nan) | ||
|
||
val_for_pos = z_critical_value * sqrt_n / 2.0 | ||
|
||
# Ensure low_pos and high_pos are within valid array bounds [0, n-1] | ||
# The formula can result in indices outside this range if n is too small. | ||
low_idx = math.floor(n / 2.0 - val_for_pos) | ||
high_idx = math.ceil(n / 2.0 + val_for_pos) # The original had 1 + n/2 + val_for_pos, usually it's n/2 + z*sqrt(n)/2 for upper rank. | ||
# Let's stick to a common interpretation of order statistic CIs. | ||
# The +1 in original might be for 1-based indexing conversion or specific formula variant. | ||
# For 0-based index, high_idx should be n - 1 - low_idx for symmetric CI around median. | ||
# Let's use a simpler, more standard approach for quantile CIs if that was the intent, | ||
# or stick to the provided formula if it's a specific known method. | ||
# Re-evaluating the original formula: | ||
# low_pos_orig = math.floor((n - z_critical_value * math.sqrt(n)) / 2) | ||
# high_pos_orig = math.ceil(1 + (n + z_critical_value * math.sqrt(n)) / 2) | ||
# These indices are 0-based. high_pos_orig includes an extra +1. | ||
# Let's assume the formula is as intended. | ||
# Need to ensure low_pos >=0 and high_pos < n | ||
|
||
low_pos_calculated = math.floor((n - z_critical_value * sqrt_n) / 2) | ||
# The `1 +` in high_pos seems to make it 1-based then implicitly 0-based by list access. | ||
# Or it's part of a specific formula variant. | ||
# If it's rank k, then index is k-1. | ||
# Let's ensure indices are valid. | ||
high_pos_calculated = math.ceil(1 + (n + z_critical_value * sqrt_n) / 2) | ||
|
||
# Clamp indices to valid range [0, n-1] | ||
final_low_idx = max(0, low_pos_calculated) | ||
final_high_idx = min(n - 1, high_pos_calculated -1) # -1 if high_pos_calculated was 1-based rank | ||
|
||
low_pos = math.floor((n - z_value * math.sqrt(n)) / 2) | ||
high_pos = math.ceil(1 + (n + z_value * math.sqrt(n)) / 2) | ||
if final_low_idx > final_high_idx or final_high_idx >= n or final_low_idx < 0: # Check validity | ||
# This happens if n is too small for the given alpha | ||
return (np.nan, np.nan) | ||
|
||
return (sorted_times[low_pos], sorted_times[high_pos]) | ||
return (sorted_times[final_low_idx], sorted_times[final_high_idx]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comprehensive improvements with minor cleanup needed.
Excellent documentation and robustness improvements to the Le Boudec method implementation. The detailed comments help understand the complex calculations.
Remove the unused variables flagged by static analysis:
- low_idx = math.floor(n / 2.0 - val_for_pos)
- high_idx = math.ceil(n / 2.0 + val_for_pos)
These calculations on lines 97-98 are redundant since the actual indices are recalculated on lines 111-116.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
def ci_le_boudec(alpha: float, times: List[float]) -> Tuple[float, float]: | |
""" | |
Calculate a non-parametric confidence interval based on Le Boudec's method. | |
This method uses order statistics and is suitable for distributions that may | |
not be normal. It requires a sufficient number of samples (related to z_value calculation). | |
Reference: "Performance Evaluation of Computer and Communication Systems" by Le Boudec. | |
:param alpha: The confidence level (e.g., 0.95 for 95% CI). | |
:param times: A list of floating-point time measurements. | |
:return: A tuple (lower_bound, upper_bound) of the confidence interval. | |
Returns (nan, nan) if the number of samples is too small for the calculation. | |
:raises AssertionError: If alpha is not one of the supported values (0.95, 0.99). | |
""" | |
if not times: | |
return (np.nan, np.nan) | |
sorted_times = sorted(times) | |
n = len(times) | |
# z(alfa/2) | |
z_value = {0.95: 1.96, 0.99: 2.576}.get(alpha) | |
assert z_value | |
# z(alpha/2) - critical value from standard normal distribution | |
# For a two-sided interval with confidence `alpha`, we need z_{1 - (1-alpha)/2} = z_{(1+alpha)/2} | |
# However, the formula used by Le Boudec for indices is n/2 +- z * sqrt(n)/2 | |
# The z_value here corresponds to z_{1 - (1-alpha)/2} | |
z_critical_value = {0.95: 1.96, 0.99: 2.576}.get(alpha) | |
assert z_critical_value is not None, f"Unsupported alpha value: {alpha}. Supported values are 0.95, 0.99." | |
# Calculate ranks for lower and upper bounds of the CI for the median | |
# (as per Le Boudec's method for quantiles, here applied to median implicitly) | |
# Note: The formula in the original code seems to be for median CI. | |
# low_pos = floor( (n - z * sqrt(n)) / 2 ) | |
# high_pos = ceil( 1 + (n + z * sqrt(n)) / 2 ) | |
# These indices are 0-based for the sorted list. | |
sqrt_n = math.sqrt(n) | |
if sqrt_n == 0: # Avoid division by zero if n=0, though caught by earlier check | |
return (np.nan, np.nan) | |
val_for_pos = z_critical_value * sqrt_n / 2.0 | |
# Ensure low_pos and high_pos are within valid array bounds [0, n-1] | |
# The formula can result in indices outside this range if n is too small. | |
low_idx = math.floor(n / 2.0 - val_for_pos) | |
high_idx = math.ceil(n / 2.0 + val_for_pos) # The original had 1 + n/2 + val_for_pos, usually it's n/2 + z*sqrt(n)/2 for upper rank. | |
# Let's stick to a common interpretation of order statistic CIs. | |
# The +1 in original might be for 1-based indexing conversion or specific formula variant. | |
# For 0-based index, high_idx should be n - 1 - low_idx for symmetric CI around median. | |
# Let's use a simpler, more standard approach for quantile CIs if that was the intent, | |
# or stick to the provided formula if it's a specific known method. | |
# Re-evaluating the original formula: | |
# low_pos_orig = math.floor((n - z_critical_value * math.sqrt(n)) / 2) | |
# high_pos_orig = math.ceil(1 + (n + z_critical_value * math.sqrt(n)) / 2) | |
# These indices are 0-based. high_pos_orig includes an extra +1. | |
# Let's assume the formula is as intended. | |
# Need to ensure low_pos >=0 and high_pos < n | |
low_pos_calculated = math.floor((n - z_critical_value * sqrt_n) / 2) | |
# The `1 +` in high_pos seems to make it 1-based then implicitly 0-based by list access. | |
# Or it's part of a specific formula variant. | |
# If it's rank k, then index is k-1. | |
# Let's ensure indices are valid. | |
high_pos_calculated = math.ceil(1 + (n + z_critical_value * sqrt_n) / 2) | |
# Clamp indices to valid range [0, n-1] | |
final_low_idx = max(0, low_pos_calculated) | |
final_high_idx = min(n - 1, high_pos_calculated -1) # -1 if high_pos_calculated was 1-based rank | |
low_pos = math.floor((n - z_value * math.sqrt(n)) / 2) | |
high_pos = math.ceil(1 + (n + z_value * math.sqrt(n)) / 2) | |
if final_low_idx > final_high_idx or final_high_idx >= n or final_low_idx < 0: # Check validity | |
# This happens if n is too small for the given alpha | |
return (np.nan, np.nan) | |
return (sorted_times[low_pos], sorted_times[high_pos]) | |
return (sorted_times[final_low_idx], sorted_times[final_high_idx]) | |
@@ def ci_le_boudec(alpha: float, times: List[float]) -> Tuple[float, float]: | |
val_for_pos = z_critical_value * sqrt_n / 2.0 | |
- low_idx = math.floor(n / 2.0 - val_for_pos) | |
- high_idx = math.ceil(n / 2.0 + val_for_pos) | |
# Ensure low_pos and high_pos are within valid array bounds [0, n-1] | |
# The formula can result in indices outside this range if n is too small. | |
low_pos_calculated = math.floor((n - z_critical_value * sqrt_n) / 2) | |
high_pos_calculated = math.ceil(1 + (n + z_critical_value * sqrt_n) / 2) |
🧰 Tools
🪛 Ruff (0.11.9)
97-97: Local variable low_idx
is assigned to but never used
Remove assignment to unused variable low_idx
(F841)
98-98: Local variable high_idx
is assigned to but never used
Remove assignment to unused variable high_idx
(F841)
🤖 Prompt for AI Agents
In sebs/statistics.py between lines 54 and 126, remove the redundant
calculations of low_idx and high_idx around lines 97-98, as these variables are
not used later and the actual indices are recalculated and used in lines
111-116. This cleanup will eliminate unused variables flagged by static analysis
without affecting the function's logic.
if self._cli_instance is None: | ||
self._cli_instance = GCloudCLI( | ||
self.config.credentials, self._system_config, self._docker_client | ||
) | ||
self._cli_instance_stop = True | ||
self._cli_instance_stop = True # This instance manages the CLI lifecycle | ||
|
||
self._cli_instance.login(self.config.credentials.project_name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrap cli_instance
creation/login with a try/except
to prevent container leaks
_cli_instance_stop
is set to True
before the login()
call. If GCloudCLI.login()
raises, the Docker container stays alive and will never be stopped because the exception aborts execution before shutdown()
can be reached. Surround the creation + login block with a try/except
and call shutdown()
on the unfinished container to avoid orphaned containers.
- if self._cli_instance is None:
- self._cli_instance = GCloudCLI(
- self.config.credentials, self._system_config, self._docker_client
- )
- self._cli_instance_stop = True # This instance manages the CLI lifecycle
-
- self._cli_instance.login(self.config.credentials.project_name)
+ if self._cli_instance is None:
+ self._cli_instance = GCloudCLI(
+ self.config.credentials, self._system_config, self._docker_client
+ )
+ self._cli_instance_stop = True
+ try:
+ self._cli_instance.login(self.config.credentials.project_name)
+ except Exception:
+ # Ensure we don’t leave the container running on failure
+ self._cli_instance.shutdown()
+ self._cli_instance = None
+ self._cli_instance_stop = False
+ raise
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
if self._cli_instance is None: | |
self._cli_instance = GCloudCLI( | |
self.config.credentials, self._system_config, self._docker_client | |
) | |
self._cli_instance_stop = True | |
self._cli_instance_stop = True # This instance manages the CLI lifecycle | |
self._cli_instance.login(self.config.credentials.project_name) | |
if self._cli_instance is None: | |
self._cli_instance = GCloudCLI( | |
self.config.credentials, self._system_config, self._docker_client | |
) | |
self._cli_instance_stop = True | |
try: | |
self._cli_instance.login(self.config.credentials.project_name) | |
except Exception: | |
# Ensure we don’t leave the container running on failure | |
self._cli_instance.shutdown() | |
self._cli_instance = None | |
self._cli_instance_stop = False | |
raise |
🤖 Prompt for AI Agents
In sebs/gcp/resources.py around lines 104 to 110, the creation and login of
_cli_instance is not protected against exceptions, which can cause Docker
containers to remain running if login() fails. Wrap the entire block that
creates _cli_instance, sets _cli_instance_stop, and calls login() in a
try/except block. In the except clause, call shutdown() on the partially created
_cli_instance to clean up the container and then re-raise the exception to avoid
orphaned containers.
pool = concurrent.futures.ThreadPoolExecutor() | ||
fut = pool.submit(self.sync_invoke, payload) | ||
return fut |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Use a context-manager to prevent thread-pool leakage
ThreadPoolExecutor
is instantiated but never shut down.
Without an explicit shutdown()
the worker threads linger for the lifetime of the interpreter, leading to resource leaks during long-running benchmarks.
- pool = concurrent.futures.ThreadPoolExecutor()
- fut = pool.submit(self.sync_invoke, payload)
- return fut
+ with concurrent.futures.ThreadPoolExecutor() as pool:
+ return pool.submit(self.sync_invoke, payload)
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
pool = concurrent.futures.ThreadPoolExecutor() | |
fut = pool.submit(self.sync_invoke, payload) | |
return fut | |
with concurrent.futures.ThreadPoolExecutor() as pool: | |
return pool.submit(self.sync_invoke, payload) |
🤖 Prompt for AI Agents
In sebs/local/function.py around lines 54 to 56, the ThreadPoolExecutor is
created without using a context manager, causing thread pool leakage. To fix
this, wrap the ThreadPoolExecutor instantiation and usage inside a with
statement to ensure it is properly shut down after use, preventing lingering
worker threads and resource leaks.
# Determine URL based on OS | ||
if is_linux(): | ||
self._url = "{IPAddress}:{Port}".format( | ||
IPAddress=networks["bridge"]["IPAddress"], Port=port | ||
) | ||
if not self._url: | ||
self.logging.error( | ||
f"Couldn't read the IP address of container from attributes " | ||
f"{json.dumps(self._instance.attrs, indent=2)}" | ||
) | ||
raise RuntimeError( | ||
f"Incorrect detection of IP address for container with id {self._instance_id}" | ||
) | ||
else: | ||
bridge_network = networks.get("bridge", {}) | ||
ip_address = bridge_network.get("IPAddress") | ||
if not ip_address: # Fallback or error if IPAddress is empty or not found | ||
# Try to get gateway if IPAddress is empty, common in some Docker versions/networks | ||
ip_address = bridge_network.get("Gateway") | ||
if not ip_address: | ||
self.logging.error( | ||
f"Couldn't read IPAddress or Gateway for container {self._instance_id} " | ||
f"from attributes: {json.dumps(self._instance.attrs, indent=2)}" | ||
) | ||
raise RuntimeError( | ||
f"Incorrect detection of IP address for container {self._instance_id}" | ||
) | ||
self._url = f"{ip_address}:{port}" | ||
else: # For non-Linux (e.g., Docker Desktop on macOS/Windows), localhost is typically used | ||
self._url = f"localhost:{port}" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
URL misses scheme and fails for non-bridge networks
- IP detection is hard-coded to the
bridge
network. Containers started with a
custom network (default on Docker Compose ordocker network create
) will
raise aRuntimeError
even though an IP is available. - The generated URL lacks the
http://
scheme, so_http_invoke
will throw
“unsupported protocol” errors.
- bridge_network = networks.get("bridge", {})
- ip_address = bridge_network.get("IPAddress")
+ # Prefer bridge first, then take the *first* network that exposes an IP.
+ bridge_network = networks.get("bridge", {})
+ ip_address = bridge_network.get("IPAddress")
+ if not ip_address:
+ for net in networks.values():
+ ip_address = net.get("IPAddress") or net.get("Gateway")
+ if ip_address:
+ break
- self._url = f"{ip_address}:{port}"
+ self._url = f"http://{ip_address}:{port}"
...
- self._url = f"localhost:{port}"
+ self._url = f"http://localhost:{port}"
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
# Determine URL based on OS | |
if is_linux(): | |
self._url = "{IPAddress}:{Port}".format( | |
IPAddress=networks["bridge"]["IPAddress"], Port=port | |
) | |
if not self._url: | |
self.logging.error( | |
f"Couldn't read the IP address of container from attributes " | |
f"{json.dumps(self._instance.attrs, indent=2)}" | |
) | |
raise RuntimeError( | |
f"Incorrect detection of IP address for container with id {self._instance_id}" | |
) | |
else: | |
bridge_network = networks.get("bridge", {}) | |
ip_address = bridge_network.get("IPAddress") | |
if not ip_address: # Fallback or error if IPAddress is empty or not found | |
# Try to get gateway if IPAddress is empty, common in some Docker versions/networks | |
ip_address = bridge_network.get("Gateway") | |
if not ip_address: | |
self.logging.error( | |
f"Couldn't read IPAddress or Gateway for container {self._instance_id} " | |
f"from attributes: {json.dumps(self._instance.attrs, indent=2)}" | |
) | |
raise RuntimeError( | |
f"Incorrect detection of IP address for container {self._instance_id}" | |
) | |
self._url = f"{ip_address}:{port}" | |
else: # For non-Linux (e.g., Docker Desktop on macOS/Windows), localhost is typically used | |
self._url = f"localhost:{port}" | |
# Determine URL based on OS | |
if is_linux(): | |
# Prefer bridge first, then take the *first* network that exposes an IP. | |
bridge_network = networks.get("bridge", {}) | |
ip_address = bridge_network.get("IPAddress") | |
if not ip_address: | |
for net in networks.values(): | |
ip_address = net.get("IPAddress") or net.get("Gateway") | |
if ip_address: | |
break | |
if not ip_address: # Fallback or error if IPAddress is empty or not found | |
# Try to get gateway if IPAddress is empty, common in some Docker versions/networks | |
ip_address = bridge_network.get("Gateway") | |
if not ip_address: | |
self.logging.error( | |
f"Couldn't read IPAddress or Gateway for container {self._instance_id} " | |
f"from attributes: {json.dumps(self._instance.attrs, indent=2)}" | |
) | |
raise RuntimeError( | |
f"Incorrect detection of IP address for container {self._instance_id}" | |
) | |
self._url = f"http://{ip_address}:{port}" | |
else: # For non-Linux (e.g., Docker Desktop on macOS/Windows), localhost is typically used | |
self._url = f"http://localhost:{port}" |
🤖 Prompt for AI Agents
In sebs/local/function.py around lines 114 to 132, the code only checks the
"bridge" network for the container IP, which fails for containers on custom
networks, and the generated URL lacks the "http://" scheme causing protocol
errors. To fix this, modify the IP detection to iterate over all container
networks to find a valid IP address or gateway instead of hardcoding "bridge".
Also, prepend "http://" to the URL string to include the scheme and avoid
unsupported protocol errors.
pool = concurrent.futures.ThreadPoolExecutor() | ||
fut = pool.submit(self.sync_invoke, payload) | ||
return fut |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Same thread-pool leak as in local trigger
Wrap the executor in with
to guarantee shutdown and free threads.
🤖 Prompt for AI Agents
In sebs/gcp/triggers.py around lines 172 to 174, the ThreadPoolExecutor is
created without a context manager, causing a thread-pool leak. Fix this by
wrapping the ThreadPoolExecutor instantiation and usage inside a `with`
statement to ensure it is properly shut down and threads are freed after use.
def _wait_for_operation_done(self, operation_request): | ||
"""Helper to wait for a Google Cloud API operation to complete.""" | ||
# Operations API client might be needed if operation_request.execute() doesn't block | ||
# or if we need to poll. For Cloud Functions, create/update often return an operation | ||
# that needs polling. Assuming execute() blocks or we handle polling elsewhere if needed. | ||
# For simplicity, if execute() is synchronous for its main effect, this is a placeholder. | ||
# If it returns an operation object, one would poll operation.name with operations.get. | ||
self.logging.info("Waiting for operation to complete...") | ||
# Placeholder: actual Google API operations might require polling. | ||
# Example: | ||
# op_service = build('cloudfunctions', 'v1').operations() | ||
# while True: | ||
# op_result = op_service.get(name=operation_name_from_response).execute() | ||
# if op_result.get('done'): | ||
# if op_result.get('error'): raise Exception(op_result['error']) | ||
# break | ||
# time.sleep(5) | ||
time.sleep(10) # Generic wait, replace with actual polling if needed. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Placeholder _wait_for_operation_done
does not poll the operation.
The current implementation blindly sleeps 10 s and returns, risking race conditions when the operation is still RUNNING.
Use the Operations API to poll until done == true
or propagate a timeout.
while True:
op = operations.get(name=op_name).execute()
if op['done']: break
time.sleep(backoff)
Without this, later IAM-policy calls frequently fail with 400 Policy can't be set while the function is being updated
.
🤖 Prompt for AI Agents
In sebs/gcp/gcp.py around lines 403 to 421, the _wait_for_operation_done method
currently only sleeps for 10 seconds without polling the operation status, which
can cause race conditions if the operation is still running. To fix this,
implement a polling loop using the Google Cloud Operations API to repeatedly
check the operation status by calling
operations.get(name=operation_name).execute(), and continue polling with a delay
(e.g., exponential backoff) until the operation's 'done' field is true or a
timeout occurs. If the operation returns an error, raise an exception
accordingly. Replace the fixed sleep with this polling logic to ensure the
operation completes before proceeding.
updated_config = gcp_function.config | ||
|
||
patch_body: Dict[str, Any] = { | ||
"availableMemoryMb": updated_config.memory, | ||
"timeout": f"{updated_config.timeout}s", | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any
is undefined.
patch_body: Dict[str, Any]
uses Any
but the symbol isn’t imported; this raises NameError
at runtime.
-from typing import cast, Dict, Optional, Tuple, List, Type
+from typing import cast, Dict, Optional, Tuple, List, Type, Any
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
updated_config = gcp_function.config | |
patch_body: Dict[str, Any] = { | |
"availableMemoryMb": updated_config.memory, | |
"timeout": f"{updated_config.timeout}s", | |
} | |
-from typing import cast, Dict, Optional, Tuple, List, Type | |
+from typing import cast, Dict, Optional, Tuple, List, Type, Any |
🧰 Tools
🪛 Ruff (0.11.9)
669-669: Undefined name Any
(F821)
🪛 Pylint (3.3.7)
[error] 669-669: Undefined variable 'Any'
(E0602)
🤖 Prompt for AI Agents
In sebs/gcp/gcp.py around lines 667 to 672, the type hint uses `Any` without
importing it, causing a NameError. To fix this, import `Any` from the `typing`
module at the top of the file along with `Dict`. This will ensure the type
annotations are recognized and prevent runtime errors.
def initialize(self, config: Dict[str, str] = {}, resource_prefix: Optional[str] = None): | ||
""" | ||
Initialize the GCP system. | ||
|
||
:param config: systems-specific parameters | ||
""" | ||
Initializes the Google Cloud Functions API client and system resources. | ||
After this call, the GCP system should be ready to allocate functions, | ||
manage storage, and invoke functions. | ||
|
||
def initialize(self, config: Dict[str, str] = {}, resource_prefix: Optional[str] = None): | ||
:param config: System-specific parameters (not currently used by GCP implementation). | ||
:param resource_prefix: Optional prefix for naming/selecting resources. | ||
""" | ||
self.function_client = build("cloudfunctions", "v1", cache_discovery=False) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Avoid mutable default arguments.
initialize
uses config: Dict[str, str] = {}
.
Default-mutable values are shared between invocations and are a well-known source of bugs.
- def initialize(self, config: Dict[str, str] = {}, resource_prefix: Optional[str] = None):
+ def initialize(self, config: Optional[Dict[str, str]] = None, resource_prefix: Optional[str] = None):
...
- self.function_client = build("cloudfunctions", "v1", cache_discovery=False)
+ if config is None:
+ config = {}
+ self.function_client = build("cloudfunctions", "v1", cache_discovery=False)
Consider the same fix for update_function_configuration(env_variables: dict = {})
.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
def initialize(self, config: Dict[str, str] = {}, resource_prefix: Optional[str] = None): | |
""" | |
Initialize the GCP system. | |
:param config: systems-specific parameters | |
""" | |
Initializes the Google Cloud Functions API client and system resources. | |
After this call, the GCP system should be ready to allocate functions, | |
manage storage, and invoke functions. | |
def initialize(self, config: Dict[str, str] = {}, resource_prefix: Optional[str] = None): | |
:param config: System-specific parameters (not currently used by GCP implementation). | |
:param resource_prefix: Optional prefix for naming/selecting resources. | |
""" | |
self.function_client = build("cloudfunctions", "v1", cache_discovery=False) | |
def initialize(self, config: Optional[Dict[str, str]] = None, resource_prefix: Optional[str] = None): | |
""" | |
Initialize the GCP system. | |
Initializes the Google Cloud Functions API client and system resources. | |
After this call, the GCP system should be ready to allocate functions, | |
manage storage, and invoke functions. | |
:param config: System-specific parameters (not currently used by GCP implementation). | |
:param resource_prefix: Optional prefix for naming/selecting resources. | |
""" | |
if config is None: | |
config = {} | |
self.function_client = build("cloudfunctions", "v1", cache_discovery=False) |
🧰 Tools
🪛 Ruff (0.11.9)
92-92: Do not use mutable data structures for argument defaults
Replace with None
; initialize within function
(B006)
🤖 Prompt for AI Agents
In sebs/gcp/gcp.py around lines 92 to 103, the initialize method uses a mutable
default argument config set to an empty dictionary, which can lead to shared
state bugs. Change the default value of config to None and inside the method,
set config to an empty dictionary if it is None. Apply the same pattern to the
update_function_configuration method's env_variables parameter by defaulting it
to None and initializing it to an empty dictionary within the method if None.
# Move files not part of package_config (handler, deps) into 'function/' subdirectory | ||
# This is an unusual step for GCP, usually all code is at root. | ||
# Re-evaluating: the code moves handler.py/js to main.py/index.js *at the root*. | ||
# Other files are moved to function_dir. | ||
# This structure means the zip will have main.py (or index.js) at root, | ||
# and other benchmark files inside a 'function' folder. | ||
|
||
# Rename the SeBS handler to GCP expected name (e.g., handler.py -> main.py) | ||
# This renamed file will be at the root of the zip. | ||
sebs_handler_name, gcp_handler_name = HANDLER_RENAMES[language_name] | ||
shutil.move(os.path.join(directory, sebs_handler_name), os.path.join(directory, gcp_handler_name)) | ||
|
||
# Zip the entire directory content for deployment. | ||
# The `recursive_zip` creates a zip where paths are relative to `directory`. | ||
benchmark_archive_path = os.path.join(directory, f"{benchmark}.zip") | ||
GCP.recursive_zip(directory, benchmark_archive_path) | ||
logging.info(f"Created {benchmark_archive_path} archive") | ||
|
||
bytes_size = os.path.getsize(benchmark_archive_path) | ||
mbytes = bytes_size / 1024.0 / 1024.0 | ||
logging.info("Zip archive size {:2f} MB".format(mbytes)) | ||
logging.info(f"Zip archive size {mbytes:.2f} MB") | ||
|
||
# rename the main.py back to handler.py | ||
shutil.move(new_path, old_path) | ||
# Rename handler back for consistency within SeBS's local file structure after packaging. | ||
shutil.move(os.path.join(directory, gcp_handler_name), os.path.join(directory, sebs_handler_name)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
File renaming logic can corrupt the workspace on failure.
shutil.move
renames the handler twice with no try/…finally
guard.
If zipping or any later step raises, the handler remains renamed, breaking subsequent runs.
- shutil.move(os.path.join(directory, sebs_handler_name), os.path.join(directory, gcp_handler_name))
- ...
- GCP.recursive_zip(directory, benchmark_archive_path)
- ...
- shutil.move(os.path.join(directory, gcp_handler_name), os.path.join(directory, sebs_handler_name))
+ src = os.path.join(directory, sebs_handler_name)
+ dst = os.path.join(directory, gcp_handler_name)
+ shutil.move(src, dst)
+ try:
+ GCP.recursive_zip(directory, benchmark_archive_path)
+ finally:
+ # Always restore original file name
+ shutil.move(dst, src)
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In sebs/gcp/gcp.py around lines 225 to 248, the handler file is renamed twice
using shutil.move without a try/finally block, which risks leaving the handler
renamed if an error occurs during zipping or later steps. To fix this, wrap the
renaming and zipping operations in a try block and ensure the handler is renamed
back in a finally block, guaranteeing the workspace is restored to its original
state even if an exception is raised.
""" | ||
Parse an AWS Lambda report log. | ||
|
||
Accepts AWS report after function invocation. | ||
Returns a dictionary filled with values with various metrics such as | ||
time, invocation time and memory consumed. | ||
|
||
:param log: Decoded log from CloudWatch or from synchronous invocation. | ||
:param requests: ExecutionResult object or dictionary of request IDs to ExecutionResult objects. | ||
:return: Request ID parsed from the log. | ||
""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Docstring mismatch in parse_aws_report
.
The summary says it “Returns a dictionary filled with metrics” but the method actually returns the request ID string. Update the summary to reflect the correct return value.
🤖 Prompt for AI Agents
In sebs/aws/aws.py around lines 541 to 551, the docstring summary incorrectly
states that the function returns a dictionary with metrics, but it actually
returns the request ID string. Update the summary in the docstring to accurately
describe that the function returns the request ID parsed from the log instead of
a dictionary.
✅ Actions performedReviews paused. |
✅ Actions performedReviews resumed. |
Generated with Jules
Summary by CodeRabbit