Skip to content

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Conversation

mcopik
Copy link
Collaborator

@mcopik mcopik commented Jun 17, 2025

Generated with Jules

Summary by CodeRabbit

  • Documentation
    • Added comprehensive docstrings and improved documentation throughout the user-facing interfaces, including cloud provider integrations, storage backends, experiment modules, and utility functions.
    • Enhanced clarity and maintainability of the codebase by detailing class and method purposes, parameters, return values, and error conditions.
    • Improved type annotations and comments for better usability and understanding.
  • Refactor
    • Refined error handling, naming conventions, and logging for improved robustness and user feedback.
    • Minor logic adjustments for clarity and correctness, without altering core behaviors.
  • Style
    • Standardized code formatting and naming for consistency across modules.

Copy link

coderabbitai bot commented Jun 17, 2025

Walkthrough

This 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

File(s) / Module(s) Change Summary
sebs/__init__.py Expanded module-level docstring to provide a detailed multi-line explanation of SeBS and its components.
sebs/aws/* Added comprehensive docstrings to all classes, methods, and properties in AWS modules; improved type annotations.
sebs/azure/* Added detailed docstrings to all Azure classes and methods; clarified logic and improved error messages.
sebs/benchmark.py Refactored with extensive docstrings, type annotations, improved error handling, and clarified method logic.
sebs/cache.py Enhanced with type hints, detailed docstrings, robust error handling, and clarified cache update logic.
sebs/config.py Added docstrings, corrected type annotations, and improved string formatting logic.
sebs/experiments/* Added comprehensive docstrings to all experiment classes and methods; improved error handling and statistics.
sebs/faas/* Added detailed docstrings to all abstract base classes and methods; clarified serialization/deserialization.
sebs/gcp/* Added comprehensive docstrings, improved error handling, clarified resource lifecycle management.
sebs/local/* Added docstrings, clarified container/network logic, improved error handling, and standardized naming.
sebs/openwhisk/* Added detailed docstrings, improved error handling, clarified Docker registry and trigger management.
sebs/regression.py Refactored with explicit type annotations, docstrings, improved test filtering, and enhanced result reporting.
sebs/sebs.py Added detailed docstrings, improved type specificity, clarified error messages, and standardized method names.
sebs/statistics.py Enhanced with docstrings, input validation, and improved calculation logic for statistics and confidence intervals.
sebs/storage/* Added detailed docstrings, clarified serialization/deserialization, improved error handling, and naming.
sebs/types.py Added docstrings and inline comments to all enums and members for clarity.
sebs/utils.py Added comprehensive docstrings, type annotations, improved logging infrastructure, and utility functions.

Sequence Diagram(s)

Omitted—changes are documentation and refactoring only, with no new or modified control flow.

Possibly related PRs

Poem

🐇✨
In fields of code, I hop with glee,
Docstrings bloom from A to Z!
Type hints sprout in every class,
Errors handled—none shall pass.
With comments clear and logic bright,
SeBS now shines in morning light.
Let's benchmark on, from left to right!
✨🐇

✨ Finishing Touches
  • 📝 Generate Docstrings

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need 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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@mcopik
Copy link
Collaborator Author

mcopik commented Jun 17, 2025

@coderabbitai pause

@mcopik mcopik requested a review from Copilot June 17, 2025 15:53
Copy link

@Copilot Copilot AI left a 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

@mcopik
Copy link
Collaborator Author

mcopik commented Jun 17, 2025

@coderabbitai resume

Copy link

@coderabbitai coderabbitai bot left a 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: Avoid assert for runtime validation of trigger types.

assert statements are stripped with Python’s -O flag, silently turning the branch into a None 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 of subprocess & 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 remove shell=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 bare except 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 loss

If all recvfrom calls time-out, message is never set, yet it’s decoded
unconditionally, raising UnboundLocalError.

-        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() references self._cache_client, but the correct attribute name (defined by NoSQLStorage / Cache setup) is self.cache_client.
This will raise an AttributeError 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 duplicate else block – SyntaxError

Lines 93-101 contain two consecutive else: clauses, which will raise a SyntaxError.

-        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 variable
sebs/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 to minio_data_path but then uses minio_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 and json 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 variable f.

-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 in name() 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 for function_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_storage
sebs/faas/resources.py (1)

36-46: Docstring default contradicts signature.

replace_existing defaults to None, 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) * 100
sebs/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 factory

The 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

  1. for key_name in self.__dataclass_fields__: is clearer and satisfies Ruff SIM118.
  2. 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 in deserialize

-        known_keys = list(MinioConfig.__dataclass_fields__.keys())
+        known_keys = MinioConfig.__dataclass_fields__

This change also applies to ScyllaDBConfig.deserialize.


64-65: Consider renaming field type to avoid shadowing built-in

Using type as an attribute can confuse static analysis and readers. A common alternative is kind or storage_type.


182-183: Repeat of .keys() issue in ScyllaDBConfig.update_cache

Apply the same iteration simplification here to silence SIM118.

sebs/faas/config.py (3)

78-90: Use ValueError instead of generic Exception in StorageBucketType.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 implemented

Marking the method @abstractmethod while providing usable logic forces every subclass to re-implement or explicitly call super().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 schema

Good addition of the None check; however, if future versions of the JSON omit storage entirely, a KeyError will be raised earlier when you access input_data["inputs"] and ["functions"]. Consider .get() with defaults to make deserialization forwards-compatible.

sebs/azure/cosmosdb.py (2)

256-258: Inconsistent indentation

Line 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 explicit

Calling 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-raising

Ruff 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 e
sebs/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 exception

Same 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: Redundant else branch

After a return the else 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 overruns sleep_time. You already use max(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 after return 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-raising

Use 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 e
sebs/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 requested name, 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 checking os.path.isfile(...). A simple existence check would provide a
clearer error before the later open() 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 file
sebs/faas/system.py (2)

313-319: Remove stray triple-quoted literal

The 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 later configure_connection sets address to ip: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 parsing

Splitting on "https://" and then manually re-adding protocol/.json is brittle.
Consider using regex or urlparse 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 a bucket_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 exists

If no setter exists, consider adding one to the LocalFunction class.

sebs/cache.py (3)

48-56: Unnecessary else branch after early return

In update_dict.map_keys_recursive, the else is unreachable because the return 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 val

Removes dead code and satisfies pylint R1705.


419-422: new_entry_structure is dead code

The 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 the if updated: break is unreachable after the preceding break.

-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 updated

Cleans 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, triggering F841.
Delete the assignment or put it to use; otherwise it’s dead code.


1070-1103: Use context manager for ZipFile 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 redundant is_zipfile call.

sebs/aws/aws.py (8)

91-98: Document initialize parameters usage.
The docstring notes that config 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: Enhance create_function exception documentation.
You catch ResourceNotFoundException 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 returns None. 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: Remove FIXME from docstring.
The FIXME: does not clean the cache. belongs in a # TODO comment in the body or an issue tracker, not the docstring.


635-644: download_metrics unused metrics parameter.
The docstring and signature include metrics but it isn’t used. Consider removing it or documenting its intended role.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2d68834 and 1ef1233.

📒 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 class BenchmarkModule docstring is clear.

Describes purpose and usage of the enum values. Good job.


14-16: Enum class Platforms docstring is well-written.

Enumerates supported platforms succinctly.


25-27: Enum class Storage docstring is informative.

Explains the storage types and their contexts.


35-37: Enum class NoSQLStorage 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: Property config 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: Class AzureTrigger 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: Property data_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: Class HTTPTrigger docstring is clear.

Summarizes its role and invocation mechanism.


41-46: Constructor docstring follows conventions.

All parameters are correctly annotated.


52-53: Method trigger_type docstring is concise.

Describes the returned trigger type.


56-61: Method sync_invoke docstring is well-described.

Documents parameters and return type accurately.


65-72: Method async_invoke docstring is detailed.

Explains threading behavior and return value clearly.


79-83: Method serialize docstring is appropriate.

Describes the serialization output clearly.


87-92: Method deserialize docstring is complete.

Includes parameter requirements and return type.

sebs/local/measureMem.py (1)

35-46: Indentation is inconsistent – potential IndentationError.

time_start = … is on the same indentation level as while 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 assumes self.config.resources is not None.
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
The CosmosDBAccount 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 for from_cache and from_allocation enumerate parameters and describe returned instances.

Also applies to: 62-70


88-95: Query method docstrings are complete
query_url and query_credentials docstrings explain the Azure CLI calls, parameters, and return types.

Also applies to: 105-112


123-127: Serialization docstrings are consistent
serialize and deserialize 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
The GCloudCLI class docstring explains its role and container-based approach succinctly.


19-21: Typename docstring is appropriate
The typename 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 for update_code, update_storage, runtime, architecture, and container_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 for experiment_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 a Config 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 the typename method’s output.


25-26: Config property docstring is accurate
Clarifies that config 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 for initialize_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 using GCPStorage.

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 checks if 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 issue

A 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 good

Nice 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/bash

Install 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 BlobClient

sig = 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 to progress_display prevents shadowing the Progress 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 calling update_cache ensure that the storage configurations are of the expected types that have the update_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 and end_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] to Dict[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 both None 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 calls self.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 level

Inside OpenWhiskResources.deserialize, config already refers to the resources
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 – verify sebs.azure module structure

from sebs.azure.azure import Azure assumes the provider class resides in sebs/azure/azure.py.
In the rest of the code-base the convention is sebs.azureAzure (single level).
If the path is wrong an ImportError will occur at runtime when the Azure platform is enabled.

Please double-check the package layout.

sebs/gcp/gcp.py (1)

321-331: Possible wrong entryPoint for Python functions.

The handler file is renamed to main.py, yet create_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-level def handler(request): ... still exists in main.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 and system_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; returning None 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.

Comment on lines 54 to +126
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])
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

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.

Suggested change
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.

Comment on lines 104 to 110
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)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

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.

Suggested change
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.

Comment on lines 54 to 56
pool = concurrent.futures.ThreadPoolExecutor()
fut = pool.submit(self.sync_invoke, payload)
return fut
Copy link

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.

Suggested change
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.

Comment on lines +114 to 132
# 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}"

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

URL misses scheme and fails for non-bridge networks

  1. IP detection is hard-coded to the bridge network. Containers started with a
    custom network (default on Docker Compose or docker network create) will
    raise a RuntimeError even though an IP is available.
  2. 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.

Suggested change
# 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.

Comment on lines 172 to 174
pool = concurrent.futures.ThreadPoolExecutor()
fut = pool.submit(self.sync_invoke, payload)
return fut
Copy link

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.

Comment on lines +403 to 421
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.

Copy link

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.

Comment on lines +667 to +672
updated_config = gcp_function.config

patch_body: Dict[str, Any] = {
"availableMemoryMb": updated_config.memory,
"timeout": f"{updated_config.timeout}s",
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

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.

Suggested change
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.

Comment on lines +92 to 103
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)
Copy link

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.

Suggested change
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.

Comment on lines +225 to +248
# 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))
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

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.

Comment on lines +541 to +551
"""
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.
"""
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

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.

Copy link

coderabbitai bot commented Jun 17, 2025

✅ Actions performed

Reviews paused.

Copy link

coderabbitai bot commented Jun 17, 2025

✅ Actions performed

Reviews resumed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant