acre icon indicating copy to clipboard operation
acre copied to clipboard

unsolved token crash

Open antirotor opened this issue 5 years ago • 5 comments

I've run into curious bug:

data = {'A': 'A', 'B': '{A}', 'C': '{C[x]}'}
result = acre.compute(data)

expected result is:

{'A': 'A', 'B': 'A', 'C': '{C[x]}'}

C should be unresolved and stay the same. But:

>>> data = {'A': 'A', 'B': '{A};B', 'C': '{C[x]}'}
>>> a = acre.compute(data)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:/Users/annat/Documents/pype/pype-setup/vendor/python/acre\acre\core.py", line 71, in compute
    env[key] = lib.partial_format(env[key], data=data)
  File "C:/Users/annat/Documents/pype/pype-setup/vendor/python/acre\acre\lib.py", line 45, in partial_format
    return formatter.vformat(s, (), mapping)
  File "C:\Users\annat\Documents\pype\docker\volume\bin\windows\python36\lib\string.py", line 190, in vformat
    result, _ = self._vformat(format_string, args, kwargs, used_args, 2)
  File "C:\Users\annat\Documents\pype\docker\volume\bin\windows\python36\lib\string.py", line 230, in _vformat
    obj, arg_used = self.get_field(field_name, args, kwargs)
  File "C:\Users\annat\Documents\pype\docker\volume\bin\windows\python36\lib\string.py", line 303, in get_field
    obj = obj[i]
TypeError: string indices must be integers

This could be fixed with: https://github.com/BigRoy/acre/blob/ce6cb34610dda1976a5489dddba954b3941dac8f/acre/lib.py#L45

to:

try:
      f = formatter.vformat(s, (), mapping)
except ValueError:
      return s
except TypeError:
      return s
return f

antirotor avatar May 06 '20 11:05 antirotor

In fact the fix doesn't work as I thought because it will then left whole string unformatted. Damn.

antirotor avatar May 06 '20 12:05 antirotor

Well the issue isn't so much in the recursive formatting but in the fact that you're actually indexing the C variable with x? Is that your intent? If so, what is that x supposed to be? This shouldn't work in any case, unless x is an integer which it clearly isn't since you accessing it with the character x.

# valid
"{C[0]}".format(C="value")
# invalid
"{C[x]}".format(C="value")

What are you trying to achieve?

Note that you can "escape" the formatting with double parentheses: "{{C[x]}}".format(C="derp") meaning that the string here actually does not contain anything that should be formatted at all so it's ignored.

BigRoy avatar May 06 '20 13:05 BigRoy

Sorry, I've noticed your comment just now.

What are you trying to achieve?

We just need to keep strings like {C[x]} unformatted. That they'll pass through acre.compute() just as raw string and not crash it.

antirotor avatar May 06 '20 15:05 antirotor

Technically the value is erroneous for string formatting and I'd be inclined to keep things simple and stay as close as possible to default string formatting.

When specifically did you need to include such a value? Is it a "hash" value that just happens to have those characters or are you writing the value explicitly, and if so... why? :)

Of course if it's a logical use case we should get things patched up. I am just wary of the confusion of random string formatting variables who fail to format to pass formatting without any message whatsoever.

BigRoy avatar May 07 '20 05:05 BigRoy

Don't look at it as formatting string. Look at it as raw data - environment variables can have whatever you want inside and I think acre should be able to deal with it. Consider you have this environment file:

{
    "MAYA_2020": "/path/to/maya/{version}",
    "SOME_RANDOM_STRING": "aksgaksgasg{sdgasgsags[dg]}"
}

This of course is extreme example but I guess in some edge cases possible (imagine storing some random hash/key/password non base64 encoded including those formatting characters.

But we actually run into this when impementing multiroots for Pype. We want to use strings like:

SOME_PATH="{root[work]}/foo/bar/baz"

Those will be later translated to correct path root. It is even possible to use formatting string like this in plain python:

>>> print("some string {foo[bar]}".format(**{"foo": {"bar": "1"}}))
some string 1

so I suppose this is not something too esoteric.

antirotor avatar May 07 '20 09:05 antirotor