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

Adds 'try_parsing' option for Environment #137

Merged
merged 10 commits into from May 8, 2021

Conversation

joelgallant
Copy link
Collaborator

@joelgallant joelgallant commented Apr 29, 2020

This can be particularly helpful for MY_SERVER_PORT=4334 cargo run

I know that serde's hints should do this because of the deserialize_* functions, but there are cases where it uses deserialize_any (for me this happened when refactoring to a nested struct in an enum). Maybe there's a better serde pattern for that/this?

@joelgallant joelgallant changed the title Adds 'parse_numbers' options for Environment Adds 'try_parsing' option for Environment May 3, 2020
tests/env.rs Outdated

let values = environment.collect().unwrap();

assert_eq!(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe a beginner question, as I did not do much dev in this crate, but what is added value of this PR if you still have to use into_int().ok(), so parse it again to retrieve final value?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, on the surface it looks like that for sure. Only reason I had to do this is that tests in the crate don't expose the int directly, at least as far as I understand it. Seems to be because the Value type exposed doesn't allow access to it's ValueKind. It's possible I could make a test that does deserialization with struct using serde instead?

Not that it's any consolation, but I have used this patch for projects of my own with success.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I need to dig deeper in the code to fully grasp the added value then ;) Hope I'll find time to do it, this crate seems really nice and it would be good to ressurect it.

@matthiasbeyer
Copy link
Collaborator

Are you still interested in this?

If yes, I created a maintenance fork (read here).
Feel free to submit your patches! 😄

@joelgallant
Copy link
Collaborator Author

I think @johnb8 would be interested.

@johnb8
Copy link
Contributor

johnb8 commented Mar 17, 2021

Yeah I'm still interested in getting this merged. @matthiasbeyer looks like you're a maintainer here now so your fork isn't needed anymore?

@matthiasbeyer
Copy link
Collaborator

matthiasbeyer commented Mar 17, 2021

Yep, that's right. I'd like to wait for #175 and then ask to rebase this, and go from there.

@matthiasbeyer
Copy link
Collaborator

Please rebase.

@johnb8
Copy link
Contributor

johnb8 commented Mar 17, 2021

Rebased on latest master

Copy link
Collaborator

@matthiasbeyer matthiasbeyer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, this looks good. But, I would like to see more tests for this kind of functionality.

First of all: Could you please split the added test into three test cases? This would be the first step. Don't worry about code duplication - I consider a certain level of code duplication in tests as necessity!
Second: Could you add more tests where the parsing is configured differently or fails entirely? Some where parsing fails, some where types do not match, some where types match and parsing is disabled... and so on!

Either way: Thanks for contributing to this crate!

@johnb8
Copy link
Contributor

johnb8 commented Mar 23, 2021

Added some more environment variable parsing tests. Let me know if there's any more you want to see, I'm happy to add them. Thanks for stepping in to maintain this crate!

Copy link
Collaborator

@matthiasbeyer matthiasbeyer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, so another review for you here. I hope you don't mind my concerns.

src/env.rs Outdated
if let (true, Ok(parsed)) = (
value.to_lowercase() == "true" || value.to_lowercase() == "false",
string_value.clone().into_bool(),
) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This if condition is rather hard to parse IMO. Can you rewrite it, so that the first part of the condition is a variable that is used in the if? This way, this could fit into one line, which would make it way easier to parse for humans.

src/env.rs Outdated
Value::new(Some(&uri), ValueKind::String(value)),
);
let value = if self.try_parsing {
let string_value = Value::new(Some(&uri), ValueKind::String(value.clone()));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a lot of clone()ing involved here. Can we somehow reduce it?

This line clones, and later we clone the string_value variable again in each if-let ... so in the worst-case, there are 5 clone() calls. I bet this can be improved!

@johnb8
Copy link
Contributor

johnb8 commented Apr 12, 2021

@matthiasbeyer I've implemented both of your suggestions. I don't mind your concerns, definitely agree with the excessive cloning

@matthiasbeyer
Copy link
Collaborator

Overall I like these changes here and I am looking forward on merging them. Two things, though:

  1. Please rebase to master, because this has merge conflicts, but also because I'd like to see the history cleaned up (don't forget to give attribution to all authors using git trailers).
  2. I am not entirely sure, but maybe we can work and improve the situation about the try-to-parse loop in the Source for Environment implementation.
    Right now it tries to parse the string value into bool, i64 and f64, trying the next one if the previous one fails.
    I'm not sure how this can be improved, but I guess there is a way with some type inference from the users site.
    Because, after all, we know to what we deserialize because the user gives a type to the API, right?

I guess the Source trait has to be altered quite a bit for this change, and I am willing to let the changes from this PR be merged without such an improvement, because it is a good start. And also because altering the Source trait is (IMO) out of scope for this PR. But I'd really like to see some work with type inference here, which would greatly improve runtime of the parsing (three try-parsing steps in worst case vs. none).

Maybe you could add a # Note comment about the runtime of the impl Source for Environment on the try_parsing() function?

Also, if we think this PR one step further, we might give the user the option to add own parsing functions - consider they want to pass something like FOO=bar=42, which is not that uncommon IMO (consider the normal rust debug env vars: RUST_LOG=module=debug. Also lists are possible, or even other things. I don't want to define the parsing for those for the user, but give them the option to provide own parsers.

@johnb8
Copy link
Contributor

johnb8 commented May 4, 2021

Rebased to latest master and added performance note to try_parsing.

Yeah I don't think we can do type inference with the way the Source trait is setup now, since collect doesn't know anything about what type the user is expecting. I think fixing that's out of scope for this too.

I'll look into list parsing and try and get something working before we merge this

@matthiasbeyer
Copy link
Collaborator

Finally got around to review this. Looks good IMO, will merge now.

@matthiasbeyer matthiasbeyer merged commit 79883ff into mehcode:master May 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants