Module: Decorators

Important

App decorators have been updated with breaking changes in TcEx 2.0.

The ThreatConnect TcEx App Framework provides multiple Python decorators to help in setup of task that are common in Apps. Using multiple decorators on a single method is common.

Fail on Output

The FailOnOutput() decorator is useful in decorating methods that should have a valid and/or specific output. The decorator can be enabled/disable directly by the App developer or based on a user input (e.g., Boolean input value in install.json).

The following example adds the FailOnOutput decorator to a method that takes a single IP Address input. If the fail_on_false input is enabled and an invalid IP Address is provided the App will exit with the provided fail_msg. This decorator provides a decent amount of flexibility, provides consistent functionality, and reduces redundant code in the App.

 1import ipaddress
 2from tcex import FailOnOutput
 3
 4@FailOnOutput(
 5    fail_enabled='fail_on_false',  # references input value fail_on_false
 6    fail_msg='App failed due to invalid ip address',  # exit message
 7    fail_on=[False],  # invalid return values
 8    write_output=True,  # regardless of pass/fail write output variables
 9)
10def is_ip_address(self, ip_address):
11    """Return True if input is a valid ipv4 address."""
12    try:
13        ipaddress.ip_address('192.168.0.1')
14    except ValueError:
15        return False
16    return True

Iterate On Arg

The IterateOnArg() decorator is useful in decorating methods that process a single and array input. This decorator can be very useful in action based Apps. This decorator accepts validators and transforms in the same manner as ReadArg(), please see that section for details.

The following example adds the IterateOnArg decorator to a method that takes a String or StringArray input and returns the value capitalized. The decorator will call the method one time for each item in the input array (a single String input value would be automatically converted to an StringArray). If the fail_enabled input is enabled and any supplied validators fail, the App would then exit using the fail_msg string provided. This decorator provides a decent amount of flexibility, provides consistent functionality, and reduces redundant code in the App.

 1from tcex import IterateOn
 2
 3@IterateOnArg(
 4    arg='colors',
 5    default=None,
 6    fail_enabled='fail_on_error,
 7    fail_msg='Failed to capitalize string input.',
 8    fail_on=['None' ''],
 9)
10def capitalize(self, colors):
11    """Return capitalized string."""
12    return colors.capitalize()

On Exception

The OnException() decorator is useful in decorating methods that may have an exception that needs to be handled consistently.

The following example adds the OnException decorator to a method that processes an input. The decorator will catch any Exception and write an exit message. If the fail_on_error input is enabled and an exception is caught, the App would then exit using the exit_msg string provided. This decorator provides a decent amount of flexibility, provides consistent functionality, and reduces redundant code in the App.

 1from tcex import OnException
 2
 3@OnException(
 4    exit_msg='Failed to capitalize input.',
 5    exit_enabled='fail_on_error',
 6    write_output=False
 7)
 8def capitalize(self, colors):
 9    """Return capitalized string."""
10    return colors.capitalize()

On Success

The OnSuccess() decorator is useful in decorating methods with a predefined exit message on successfully execution.

The following example adds the OnSuccess decorator to a method that processes an input. The decorator set the exit message of the App when the method successfully completes.

1from tcex import OnSuccess
2
3@OnSuccess(exit_msg='Successfully capitalized input.')
4def capitalize(self, colors):
5    """Return capitalized string."""
6    return colors.capitalize()

Output

The Output() decorator is useful in decorating methods that provide output that will be used during the write_output() method.

The following example adds the Output decorator to a method that processes an input. The decorator will add the output of the method to the attribute provided to the decorator. This method is helpful when using the IterateOn() decorator. For each execution of the method the return data is appended/extended to the provided attribute. This decorator provides a decent amount of flexibility, provides consistent functionality, and reduces redundant code in the App.

 1from tcex import Output
 2
 3def __init__(self):
 4    """Initialize class properties."""
 5    self.output_data = None
 6
 7@Output(attribute='output_data', overwrite=False)
 8def capitalize(self, colors):
 9    """Return capitalized string."""
10    return colors.capitalize()

Read Arg

The ReadArg() decorator is useful in decorating methods that use a user input.

The following example adds the ReadArg decorator to a method that takes a String. The decorator will call the method passing the value of the append_chars input. If the fail_on_error input is enabled and the input matches a value in the fail_on array, the App would then exit using the fail_msg string provided. This decorator provides a decent amount of flexibility, provides consistent functionality, and reduces redundant code in the App.

 1from tcex.decorators import ReadArg
 2
 3@ReadArg(
 4    arg='append_chars',
 5    fail_enabled='fail_on_error,
 6    fail_on=['None' ''],
 7)
 8def append(self, string, append_chars):
 9    """Return string with appended characters."""
10    return f'{string}{append_chars}'

The ReadArg() decorator includes several built-in transforms that modify the value of the input and validators that perform checks on the input but do not change its value.

The following built-in transforms are available:

  • to_bool

  • to_float

  • to_int

The following built-in validators are available:

  • equals

  • in_range

  • greater_than

  • greater_than_or_equal

  • less_than

  • less_than_or_equal

  • not_in (this is equivalent to fail_on)

Transforms are run, in the order they are passed, before validators, which are also run in the order they are passed.

 1from tcex.decorators import ReadArg
 2
 3@ReadArg(
 4    arg='confidence',
 5    fail_enabled='fail_on_error,
 6    fail_on=['None' ''],
 7    to_int=True,
 8    in_range={'min': 0, 'max': 100}
 9)
10def append(self, confidence):
11    """Return string with appended characters."""
12    return f'{confidence}'

Custom validators and transforms can be defined using the validators and transforms arguments. Both validators and transforms are callables that accept the input value and input name and raise a tcex.validators.ValidationError if the input is invalid. Validators do not return a value, but transforms should return a new value for the input.

 1from tcex.decorators import ReadArg
 2from tcex.validators import ValidationError
 3
 4def to_email(value, arg_name):
 5    """This is a transform that takes a name and returns the associated email address"""
 6    name_to_email = {
 7        'Bob': '[email protected]',
 8        'Sally': '[email protected]'
 9    }
10
11    if value in name_to_email:
12        return name_to_email.get(value)
13
14    raise ValidationError(f'no email found for {value}.')
15
16def is_valid_label(value, arg_name):
17    valid_labels = ['High', 'Medium', 'Low']
18    if value not in valid_labels:
19        raise ValidationError(f'{arg_name} must be High, Medium, or Low')
20
21@ReadArg(
22    arg='email_to',
23    transforms=[to_email]
24)
25@ReadArg(
26    arg='label',
27    validators=[is_valid_label]
28)
29def append(self, email_to, label):
30    """Return string with appended characters."""
31    return f'{email_to}  - {label}'