This is a known issue / challenge / problem (depending on how you look at it). Your workaround using e.g. an AttributeCreator + AttributeRemover is currently the simplest and most robust solution, so that's what I'd recommend.
Bit late probably, but have you tried out my workaround (as discussed here)? It might do the trick fetching the right macro value, but you will have to export/link your custom transformer as an FMX.
In your case, you could try adding the following function at the "global" level of your Python code:
def get_macro_value(param_name, default=None):
    context = FME_MacroValues.get('WB_CURRENT_CONTEXT')
    for key, value in FME_MacroValues.items():
        if key.endswith(param_name):
            if not context or (context and key.startswith(context)):
                return value
    return default
Then, you can replace the first 4 lines in your code above with:
parameter_name = 'codeLength'
mv_codeLength = get_macro_value(parameter_name)
Specifying the custom transformer name is irrelevant here, since the function fetches that from the WB_CURRENT_CONTEXT macro value, which always exists within a custom transformer and returns the current name of the transformer. This is why it only works for linked custom transformers: WB_CURRENT_CONTEXT is empty for embedded transformers.
Let me know if that works out for you!
Â
Btw, I would replace lines 6-13 in your code with (to make it a little more robust):
codeLength = 0
try:Â
    if mv_codeLength.startswith(('@Value', '@Evaluate')):
        codeLength = int(feature.performFunction(mv_codeLength))
    elif mv_codeLength.isdigit():
        codeLength = int(mv_codeLength)
except (TypeError, AttributeError, ValueError) as e:
    # Can happen when mv_codeLength is not a string orÂ
    # when the feature function output can not be cast to an integer.
    # You could log this error or do something else here.
    pass
Â
Finally, there actually is a way to fetch the name of the current custom transformer name from within (even if it is embedded), but you will have to use a PythonCaller with a FeatureProcessor class. When instantiated, a property called self.factory_name is set, which starts with the name of the custom transformer, followed by the name of the PythonCaller (and concatenated by an underscore)!
Bit late probably, but have you tried out my workaround (as discussed here)? It might do the trick fetching the right macro value, but you will have to export/link your custom transformer as an FMX.
In your case, you could try adding the following function at the "global" level of your Python code:
def get_macro_value(param_name, default=None):
    context = FME_MacroValues.get('WB_CURRENT_CONTEXT')
    for key, value in FME_MacroValues.items():
        if key.endswith(param_name):
            if not context or (context and key.startswith(context)):
                return value
    return default
Then, you can replace the first 4 lines in your code above with:
parameter_name = 'codeLength'
mv_codeLength = get_macro_value(parameter_name)
Specifying the custom transformer name is irrelevant here, since the function fetches that from the WB_CURRENT_CONTEXT macro value, which always exists within a custom transformer and returns the current name of the transformer. This is why it only works for linked custom transformers: WB_CURRENT_CONTEXT is empty for embedded transformers.
Let me know if that works out for you!
Â
Btw, I would replace lines 6-13 in your code with (to make it a little more robust):
codeLength = 0
try:Â
    if mv_codeLength.startswith(('@Value', '@Evaluate')):
        codeLength = int(feature.performFunction(mv_codeLength))
    elif mv_codeLength.isdigit():
        codeLength = int(mv_codeLength)
except (TypeError, AttributeError, ValueError) as e:
    # Can happen when mv_codeLength is not a string orÂ
    # when the feature function output can not be cast to an integer.
    # You could log this error or do something else here.
    pass
Â
Finally, there actually is a way to fetch the name of the current custom transformer name from within (even if it is embedded), but you will have to use a PythonCaller with a FeatureProcessor class. When instantiated, a property called self.factory_name is set, which starts with the name of the custom transformer, followed by the name of the PythonCaller (and concatenated by an underscore)!
Thanks, lot's of good comments on my code. The code is indeed enclosed in a Python Class that is called by the PythonCaller. Don't know if I think it is worth it to make the code only work Linked not Embedded.