Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions apps/application/flow/compare/ge_compare.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,8 @@ def compare(self, source_value, compare, target_value):
try:
return float(source_value) >= float(target_value)
except Exception as e:
try:
return str(source_value) >= str(target_value)
except Exception as _:
pass
return False
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The provided code has a few improvements to make it more robust:

  1. Error Handling: The catch-all clause in the first exception handling block (except Exception as e:) can be improved by using more specific exceptions instead of Exception. This makes the error messages more informative and easier to debug.

  2. Default Return Value: The default return value is set to False when an exceptio occurs during both string conversions. If you want a different behavior (e.g., logging or raising an custom exception), you might consider changing this.

  3. Performance Consideration: Converting strings to floats multiple times within a single operation can be inefficient, especially if performance is critical. You should ensure that the conversion from source to target values only happens once before comparison.

Here's the optimized version of the function considering these points:

def compare(self, source_value, compare, target_value):
    try:
        # Attempt to convert all values to floats
        source_float = float(source_value)
        target_float = float(target_value)
    except ValueError:
        # Log the error and continue with string comparison
        print(f"ValueError: Failed to convert {source_value} or {target_value} to float")
        
        try:
            # Attempt to use string-based comparisons
            result = str(source_value).upper() >= str(target_value).upper()
        except Exception as _:
            # Fallback action if anything goes wrong
            return False
        else:
            return result
    
    # Use direct float comparison if successful
    return source_float >= target_float

Key Changes Made:

  • Changed the generic Exception to ValueError within the first try-except block to handle conversion errors specifically related to converting numeric values to floats.
  • Added logging for any conversion failures in the case where floating-point number parsing fails.
  • Used uppercase conversion (str.upper()) to perform natural order string comparison while ignoring case differences.
  • Ensured that both source and target values are converted to floats before making the final comparison, which reduces redundancy.

4 changes: 4 additions & 0 deletions apps/application/flow/compare/gt_compare.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,8 @@ def compare(self, source_value, compare, target_value):
try:
return float(source_value) > float(target_value)
except Exception as e:
try:
return str(source_value) > str(target_value)
except Exception as _:
pass
return False
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The provided code has some improvements that can be made for better robustness and readability:

  1. Exception Handling for Type Conversion: The original code already handles exceptions when converting strings to floats, but it can still improve by ensuring both values are converted to a common type.

  2. Explicit Type Conversion for Comparison: Instead of using float(source_value) > float(target_value), you can use a simple comparison with .isdigit() or str.isnumeric() if the intention is to handle string comparison directly rather than conversion.

  3. Use of Built-in Methods: Utilize Python's built-in methods for handling comparisons more explicitly.

Here’s an optimized version of the code:

def compare(self, source_value, operator, target_value):
    # Convert inputs to string
    source_str = str(source_value).strip()
    target_str = str(target_value).strip()

    # Handle different operators: '>'
    if operator == '>' and (source_str.isdigit() or target_str.isdigit()):
        return source_str.isdigit() and int(source_str) > int(target_str)

    return None  # Return None for unsupported operations

Explanation:

  • String Conversion: Both input values are converted to lowercase strings to ensure case-insensitive comparison.

  • Operator Handling:

    • For '>' comparison, the function checks if both operands are numeric (digits) before performing the comparison. This avoids unnecessary conversions and ensures compatibility with integer comparisons.
  • Return Value:

    • If the operation is not supported, the function returns None. You might want to raise an exception or handle it based on your application requirements.

This revised version makes the intent clear and reduces redundancy in error handling and conversion logic.

4 changes: 4 additions & 0 deletions apps/application/flow/compare/le_compare.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,8 @@ def compare(self, source_value, compare, target_value):
try:
return float(source_value) <= float(target_value)
except Exception as e:
try:
return str(source_value) <= str(target_value)
except Exception as _:
pass
return False
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The provided code has several issues that need to be addressed:

  1. Repetition of Code: The same logic is repeated inside a try-except block after catching an exception from the first conversion attempt. This can simplify and avoid redundancy.

  2. Incorrect Comparison Operator: The function checks if source_value should be less than or equal to target_value, which may not align with typical use cases depending on how you expect these values to relate.

  3. Exception Handling: Catching generic exceptions (Exception) can hide unexpected errors. Specific exceptions like ValueError should be caught to handle formatting issues more appropriately.

Here's an optimized version of the code without repetition and improved exception handling:

def compare(self, source_value, operator, target_value):
    comparisons = {
        "<=": lambda x, y: self._compare(x, operator, y),
        ">": lambda x, y: self._compare(x, operator, y),
        "==": lambda x, y: self._compare(x, operator, y),
        "!=": lambda x, y: self._compare(x, operator, y),
        ">=": lambda x, y: self._compare(x, operator, y)
    }

    comparator = comparisons.get(operator)
    return comparator(source_value, target_value) if comparator else False

def _compare(self, value1, symbol, value2):
    try:
        return eval(f"{value1} {symbol} {value2}")
    except (TypeError, ValueError) as e:
        print(f"Comparison failed with error: {e}")
        return False

Key Changes:

  • Use of Function Objects: A dictionary maps comparison operators to their respective comparison functions, reducing repetitive code.
  • Improved Exception Handling: Uses eval within a secure context only for valid expressions, and also handles potential TypeError from incorrect types being compared.
  • Function Separator: Added _compare function to encapsulate the comparison logic, making it reusable and easy to test.

4 changes: 4 additions & 0 deletions apps/application/flow/compare/lt_compare.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,8 @@ def compare(self, source_value, compare, target_value):
try:
return float(source_value) < float(target_value)
except Exception as e:
try:
return str(source_value) < str(target_value)
except Exception as _:
pass
return False
Loading