About PythonPropertyValue
Class
nififapi.properties.PythonPropertyValue
Instance of this class is returned by ProcessContext getProperty()
method.
Attributes
Name | Type | Description |
---|---|---|
value | String | A string representation of the property |
property_value | Java PropertyValue interface | |
getValue() | Callable | Returns a string representation of the property |
isSet() | Callable | Returns bool ;The value is not None |
isExpressionLanguagePresent() | Callable | Returns bool ;The property value needs to be evaluated |
asInteger() | Callable | Returns int | None ;If value is set, return it as an integer; Raises ValueError |
asBoolean() | Callable | Returns bool | None ;If value is set, return it as a boolean |
asFloat() | Callable | Returns float | None ;If value is set, return it as a float; Raises ValueError |
evaluateAttributeExpressions() | Callable | Returns PythonPropertyValue ;Evaluate the expression Language, if one enabled, and present; Accepts optional parameter of type AttributeMap ;See evaluateAttributeExpressions |
asTimePeriod(TimeUnit) | Callable | Returns int | None ;If value is set, return it as an integer representation of a specified time unit; See asTimePeriod |
asDataSize(DataUnit) | Callable | Returns float | None ;If value is set, return it as a float representation of a specified size unit; See asDataSize |
asResource() | Callable | Returns ResourceReference Java Proxy object;See ResourceReference |
asResources() | Callable | Returns ResourceReferences Java Proxy object;See ResourceReferences |
evaluateAttributeExpressions
The evaluateAttributeExpressions
method, checks for a presence and support of NiFi Expression Language in the property value, and if EL is both present and enabled it will attempt to evaluate.
Evaluated value will be accessible through the value
attribute and further evaluation will be blocked.
Example of a property evaluation:
from nifiapi.properties import (
PropertyDescriptor,
StandardValidators,
ExpressionLanguageScope
)
EL_PROPERTY = PropertyDescriptor(
name="EL Property",
description='''
This property is expected to be a valid expression.
''',
default_value='${literal("0xF"):toNumber()}',
validators=[StandardValidators.NON_EMPTY_EL_VALIDATOR],
expression_language_scope=ExpressionLanguageScope.ENVIRONMENT
)
# Get the value of EL_PROPERTY property and evaluate it.
# i.e. "15" if default value was unchanged
value = context.getProperty(EL_PROPERTY) \
.evaluateAttributeExpressions() \
.getValue()
asTimePeriod
This method is used to interpret and convert a property value into an integer representing the time duration in a specified unit. The desired unit must be represented as an attribute of nifiapi.properties.TimeUnit
enum. Allowed units:
NANOSECONDS
MICROSECONDS
MILLISECONDS
SECONDS
MINUTES
HOURS
DAYS
See TIME_PERIOD_VALIDATOR for details on acceptable property values.
Example:
from nifiapi.properties import (
PropertyDescriptor,
StandardValidators,
TimeUnit
)
TIME_PROPERTY = PropertyDescriptor(
name="Time Period",
description='''
A test of time-period validator.
''',
default_value="1 min",
validators=[StandardValidators.TIME_PERIOD_VALIDATOR],
)
# Get the value of TIME_PROPERTY property represented in second,
# i.e. 60 if default value was unchanged.
value = context.getProperty(TIME_PROPERTY) \
.asTimePeriod(TimeUnit.SECONDS)
asDataSize
This method is used to interpret and convert a property value into a float representing the data size in a specified unit. Desired unit must be represented as an attribute of nifiapi.properties.DataUnit
enum. Allowed units:
B
KB
MB
GB
TB
See DATA_SIZE_VALIDATOR for details on acceptable property values.
Example:
from nifiapi.properties import (
PropertyDescriptor,
StandardValidators,
DataUnit
)
DATA_SIZE_PROPERTY = PropertyDescriptor(
name="Time Period",
description='''
A test of time-period validator.
''',
default_value="100 Kb",
validators=[StandardValidators.DATA_SIZE_VALIDATOR],
)
# Get the value of DATA_SIZE_PROPERTY property represented in number of Mb,
# i.e. 0.09765625 if default value was unchanged.
value = context.getProperty(DATA_SIZE_PROPERTY) \
.asTimePeriod(DataUnit.MB)
Evaluating with FlowFile
If the Expression Language scope is set to FLOWFILE_ATTRIBUTES
for a given property, evaluation should be done inside of transform
method.
See ExpressionLanguageScope for more.
e.g.:
value = context.getProperty(PROPERTY.name) \
.evaluateAttributeExpressions(flow_file) \
.getValue()
Extending FlowFile Attribute Map
Manipulating the AttributeMap
directly will result in failure, as it is immutable. The Python API provides an alternative way of declaring and modifying FlowFile attributes.
See FlowFileSourceResult and FlowFileTransformResult for more.
If the modification of the FlowFile attribute map is not expected to propagate outside the scope of the evaluation, an alternate map might be provided. To understand how an alternate map can be implemented, see the Java AttributeMap
interface:
public interface AttributeMap {
String getAttribute(String attributeName);
Map<String, String> getAttributes();
}
Based on the AttributeMap
interface we can then define a custom implementation of dict
class:
class AttributeDict(dict):
def __init__(self, *args, **kw):
super(AttributeDict, self).__init__(*args, **kw)
def getAttribute(self, key):
return self[key]
def getAttributes(self):
return self
Example of extending the FlowFile attribute map with a flowfile_contents
attribute:
from nifiapi.flowfiletransform import (
FlowFileTransform,
FlowFileTransformResult,
)
from nifiapi.properties import (
ProcessContext,
PropertyDescriptor,
StandardValidators,
ExpressionLanguageScope
)
class AttributeDict(dict):
def __init__(self, *args, **kw):
super(AttributeDict, self).__init__(*args, **kw)
def getAttribute(self, key):
return self[key]
def getAttributes(self):
return self
class Processor(FlowFileTransform):
EL_PROPERTY = PropertyDescriptor(
name="EL Property",
description='''
Property value can contain Expression Language;
Scope of the language includes attributes referencing FlowFile
attributes.
''',
validators=[StandardValidators.NON_EMPTY_EL_VALIDATOR],
expression_language_scope=ExpressionLanguageScope.FLOWFILE_ATTRIBUTES,
)
(...)
def transform(
self, context: ProcessContext, flow_file
) -> FlowFileTransformResult:
'''
Parameters:
context (ProcessContext)
flow_file
Returns:
FlowFileTransformResult
'''
attribute_dict = self.get_extended_attribute_map(flow_file)
value = context.getProperty(self.EL_PROPERTY) \
.evaluateAttributeExpressions(attribute_dict) \
.getValue()
return FlowFileTransformResult("success")
def get_extended_attribute_map(self, flow_file) -> AttributeDict:
'''
If possible inject 'flowfile_contents' attribute to FlowFile
attribute map.
Parameters:
flow_file
Returns:
AttributeDict
'''
extended = AttributeDict(dict(flow_file.getAttributes()))
# If the FlowFile content is a UTF-8 encoded string, push the decoded
# value to the attribute map.
try:
extended["flowfile_contents"] = flow_file.getContentsAsBytes()\
.decode("utf-8")
except ValueError:
pass
return extended
Working with a Resource Reference
Properties utilizing a resource can be accessed through the ProcessContext
. The PythonPropertyValue
class provides two methods for accessing resources: asResource
and asResources
.
The asResource
method returns an instance of the Java ResourceReference
class, while the asResources
method returns a ResourceReferences
object. The former provides an interface for interacting with a single resource, whereas the latter represents a collection of resource interfaces.
See ResourceReference and ResourceReferences for details.
# Get an instance of a Java ResourceReference class
one_resource = context.getProperty(SINGLE_RESOURCE).asResource()
# Get an instance of a Java ResourceReferences class
many_resources = context.getProperty(MULTI_RESOURCE).asResources()