Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[bug] Environment.dumps() write prepended variable in reverse order. #17859

Open
todorico opened this issue Feb 26, 2025 · 5 comments · May be fixed by #17863
Open

[bug] Environment.dumps() write prepended variable in reverse order. #17859

todorico opened this issue Feb 26, 2025 · 5 comments · May be fixed by #17863
Assignees

Comments

@todorico
Copy link

todorico commented Feb 26, 2025

Describe the bug

Environment details: Windows, Conan 2.12.2, Python 3.10.11

I use Environment.dumps() to create profiles that I can reuse later. However, I noticed that all variables that prepend paths using those generated profiles were in the reverse order.

How to reproduce it

Create a conanfile and generate a dummy environment:

def generate(self):
        env = Environment()
        env.prepend_path("DUMMY_ENV", "should finish last")
        env.prepend_path("DUMMY_ENV", "should finish first")
        print(env.dumps())
        env.vars(self).save_script("dummy_env")

Check the resulting environment script:

rem we are in the generated dummy_env.bat

set "DUMMY_ENV=should finish first;should finish last;%DUMMY_ENV%"

Now in comparison create a profile with the dumped environment:

# we are in the created dummy_env.profile

[buildenv]
DUMMY_ENV=+(path)should finish first
DUMMY_ENV=+(path)should finish last

If we use this profile to generate the environment instead of the environment script, the variable will be set in the wrong order:

rem we are in the generated conanbuild*.bat

set "DUMMY_ENV=should finish last;should finish first%DUMMY_ENV%"
@memsharded memsharded self-assigned this Feb 26, 2025
@memsharded
Copy link
Member

Hi @todorico

It seems this is not a bug. You are reversing the order, the order in the profile is the opposite one than in the conanfile.
It should be the same order, change it to:

[buildenv]
DUMMY_ENV=+(path)should finish last
DUMMY_ENV=+(path)should finish first

So it is the same order as the one in the generate() method and you will get the expected order.

@todorico
Copy link
Author

todorico commented Feb 27, 2025

Hi @memsharded,

Thanks for your response. My issue is that I don't control the order; I reuse the output of Environment.dumps(), which I believe should be consistent with the original environment values.

The problem arises when loading the serialized environment, but only if the original environment contains prepended values.

Here's a code example to illustrate:

# No prepended values, so no assertion error:

env = Environment()
env.define("DEFINED", "defined")
# env.prepend_path("PREPENDED", "prepend_0")
# env.prepend_path("PREPENDED", "prepend_1")
env.append_path("APPENDED", "append_0")
env.append_path("APPENDED", "append_1")
env_vars = env.vars(self)

profile_env = ProfileEnvironment.loads(env.dumps()).get_profile_env("*/*")

for var, profile_value in profile_env.vars(self).items():
    assert env_vars.get(var) == profile_value, f"mismatch {env_vars.get(var)} != {profile_value}"
# Uncommenting the prepended values causes an assertion error:
#        assert env_vars.get(var) == profile_value, f"mismatch {env_vars.get(var)} != {profile_value}"
#        AssertionError: mismatch prepend_1;prepend_0 != prepend_0;prepend_1

env = Environment()
env.define("DEFINED", "defined")
env.prepend_path("PREPENDED", "prepend_0")
env.prepend_path("PREPENDED", "prepend_1")
env.append_path("APPENDED", "append_0")
env.append_path("APPENDED", "append_1")
env_vars = env.vars(self)

profile_env = ProfileEnvironment.loads(env.dumps()).get_profile_env("*/*")

for var, profile_value in profile_env.vars(self).items():
    assert env_vars.get(var) == profile_value, f"mismatch {env_vars.get(var)} != {profile_value}"

It is surprising to me because I was expecting that the loading of the serialization of an environment would be the same as the environment, but it's not always true.

@memsharded
Copy link
Member

I see, thanks for the feedback, I am having a look into it, I'll let you know asap.

In any case, I'd like to raise the awareness that the dumped profile in command line output is exclusively informational.
It is not designed to be used as round-trip input, and as the stability commitment reads:

The output streams stdout, stderr, i.e. the terminal output can change at any time. Do not parse the terminal output for automation.

Likewise the ProfileEnvironment class is not public API, it is not documented and it cannot be used anywhere, it is internal for Conan usage too.

@memsharded memsharded linked a pull request Feb 27, 2025 that will close this issue
@memsharded
Copy link
Member

I am doing #17863 that will fix the prepend order for dumps(), for next Conan 2.14.

@todorico
Copy link
Author

That's awesome, thank you very much !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants