Skip to main content
Open

python caller user parameters automatically prefixed

Related products:Transformers
  • December 16, 2015
  • 8 replies
  • 80 views
k_murai
vlroyrenn
siennaatsafe
david_r
danilo_fme
+23
  • k_murai
    k_murai
  • vlroyrenn
    vlroyrenn
  • siennaatsafe
    siennaatsafe
  • david_r
    david_r
  • danilo_fme
    danilo_fme
  • jdh
    jdh
  • warrendev
    warrendev
  • tcrossman
    tcrossman
  • thijsknapen
    thijsknapen
  • fgiron
    fgiron
  • fhilding
  • jeroenstiers
  • carstenotto
    carstenotto
  • rkay
  • aarongeppert
    aarongeppert
  • sonya
  • mbv
  • aquee
    aquee
  • ekkischeffler
    ekkischeffler
  • felipeverdu
    felipeverdu
  • danielkroon
    danielkroon
  • jwarren
    jwarren
  • jpvo
    jpvo
  • thejando
    thejando
  • kweller
    kweller
  • nilsur
    nilsur
  • alan_nre_tas
  • ray

jdh
Contributor
  • Contributor

According to safe: Tthe user parameters behave a little bit differently inside a custom transformer. They are in fact prefixed with the name of the custom transformer to avoid collisions with the main workspace parameters. Example: if you have a custom transformer called "custtransf" with a published parameter called "custparam", you will have to refer to it like this.

value = FME_MacroValues["custtransf_custparam"] The issue is that a user can change the name of the custom transformer in the main canvas, or could have multiple copies ("custtransd_2") and the reference breaks. Ideally I would like to just refer to the user parameter without prefixing anything, and have FME figure it out when interpreting the python. If that's not possible, then having the ability to insert a "transformer name" into the python call would also work. value = FME_MacroValues[transformerName + "_custparam"]

8 replies

david_r
Celebrity
  • December 17, 2015

I agree this is a hassle, would be nice if we could get an elegant solution in the API that does not require a ParameterFetcher.


kweller
Contributor
Forum|alt.badge.img+8
  • Contributor
  • October 10, 2016

The current behavior breaks encapsulation.


ekkischeffler
Contributor
Forum|alt.badge.img+5

I agree. At the moment I am strictly using parameter fetchers within custom transformers to bypass this issue. However, this creates additional attributes that I need to clean up (which might interfere with input attributes).


thejando
Contributor
Forum|alt.badge.img+4
  • Contributor
  • June 29, 2022

This is a big problem for current development work in my organisation. I have an Esri Geodatabase Writer inside a custom transformer and I need to define the values of the Feature Operation and Truncate Existing parameters using Python. I need to be able to define the Feature Operation and Truncate Existing parameters based on the value of a Published Parameter, but as stated above, when using a Scripted Private Parameter I cannot access the value of the Published Parameter value because the name of the Published Parameter has been changed by FME. The ParameterFetcher work-around will not work because these settings in the Writer cannot be linked to an Attribute Value.


vlroyrenn
Supporter
Forum|alt.badge.img+12
  • Supporter
  • August 16, 2023

This makes PythonCaller extremely brittle and unreliable when used inside custom transformers (where they seem to be very common), and affects not only published parameter use, but also feature type matching (since features created inside a custom transformer are also prefixed by instance), which makes it harder to deal with PythonCaller's lack of additionnal input ports.


vlroyrenn
Supporter
Forum|alt.badge.img+12
  • Supporter
  • April 3, 2024

It’s not especially clean, but there is a way of handling this quirk programatically:
 

import fmeobjects

ACTUAL_TRANSFORMER_NAME = "MyPythonCaller"

class FeatureCreator(object):
    def __init__(self):
        pass

    def get_local_parameter(self, user_param_name):
        assert hasattr(self, "factory_name"), "factory_name does not exist during __init__()"

        if not hasattr(self, "scope_name"):
            # factory_name: MyCustomTransformerInstanceName_MyPythonCaller
            scope_prefix = self.factory_name.removesuffix(ACTUAL_TRANSFORMER_NAME)

            if scope_prefix != self.factory_name and scope_prefix.endswith("_"):
                self.scope_name = scope_prefix.removesuffix("_") # MyCustomTransformerInstanceName
            else:
                self.scope_name = None

        if self.scope_name:
            local_param_name = f'{self.scope_name}_{user_param_name}'
        else:
            local_param_name = user_param_name

        local_param_value = FME_MacroValues[local_param_name]
        print(f"{local_param_name}: {local_param_value}")
        return local_param_value



    def input(self, feature):
        self.get_local_parameter("MY_USER_PARAM")
        self.get_local_parameter("OTHER_USER_PARAM")

        newFeature = fmeobjects.FMEFeature()
        self.pyoutput(newFeature)

    def close(self):
        pass

I’m not sure in which FME release self.factory_name was added, but its at least there in FME 2023 and 2022.

As highlighted by the assertion at the start, that doesn’t work inside __init__(), and you need to make sure ACTUAL_TRANSFORMER_NAME always matches the Transformer Name of the PythonCaller/PythonCreator that code exists within.

I would still prefer a properly supported way of handling this, but this looks like a reasonably robust self-contained workaround (as opposed to using an upstream ParameterFetcher or an AttributeCreator to add the parameters to all features).


nordpil
Supporter
Forum|alt.badge.img+10
  • Supporter
  • April 22, 2024

I consider it best practice to not refer to parameters outside the CT, any data/values to be passed in should go through custom transformer parameters or attributes.


vlroyrenn
Supporter
Forum|alt.badge.img+12
  • Supporter
  • June 11, 2024
nordpil wrote:

I consider it best practice to not refer to parameters outside the CT, any data/values to be passed in should go through custom transformer parameters or attributes.

I believe you misunderstand: all Custom Transformer parameters in FME_MacroValues are prefixed with the instance name of the transformer, which is fine on its own (even tough, like you said, using parameters from outside the CT is kind of an anti-pattern), but you have no documented mean of knowing what prefix your PythonCaller is running out of, and therefore no way of reliably getting these parameters from Python. What I suggested above works, but it’s definitely a hack and I certainly wouldn’t expect authors of custom transformers to have to use it all the time.


Reply


Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings