Skip to main content

About PythonPropertyValue

Class nififapi.properties.PythonPropertyValue

Instance of this class is returned by ProcessContext getProperty() method.

Attributes

NameTypeDescription
valueStringA string representation of the property
property_valueJava PropertyValue interface
getValue()CallableReturns a string representation of the property
isSet()CallableReturns bool;

The value is not None
isExpressionLanguagePresent()CallableReturns bool;

The property value needs to be evaluated
asInteger()CallableReturns int | None;

If value is set, return it as an integer;

Raises ValueError
asBoolean()CallableReturns bool | None;

If value is set, return it as a boolean
asFloat()CallableReturns float | None;

If value is set, return it as a float;

Raises ValueError
evaluateAttributeExpressions()CallableReturns PythonPropertyValue;

Evaluate the expression Language, if one enabled, and present;

Accepts optional parameter of type AttributeMap;

See evaluateAttributeExpressions
asTimePeriod(TimeUnit)CallableReturns int | None;

If value is set, return it as an integer representation of a specified time unit;

See asTimePeriod
asDataSize(DataUnit)CallableReturns float | None;

If value is set, return it as a float representation of a specified size unit;

See asDataSize
asResource()CallableReturns ResourceReference Java Proxy object;

See ResourceReference
asResources()CallableReturns 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

caution

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