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

Extracted json saving and loading #10216

Merged
merged 1 commit into from
Nov 1, 2017
Merged

Conversation

molobrakos
Copy link
Contributor

@molobrakos molobrakos commented Oct 29, 2017

Description:

Many components use json files to store custom configuration data.
All implements their own very basic code for loading and saving dicts as JSON files (with open(filename) as f: json.loads(f)). Some do error checking (checking if file exists or not), some do not. Some catch relevant exceptions, some do not.

It is obvious that in most places, the exact same logic is taking place, and in many places the same code is duplicated (a 20-line function config_from_file(filename, config=None) seems to be copied around a lot).

This PR provides basic functionality for loading and saving dicts as JSON (load_json, save_json, analogous with load_yaml) in core.

Benefits: Less code duplication, hopefully somewhat better error handling, better reporting in the logs, and easier testing/mocking.

The PR only contain changes in one component (media_player/plex.py) to use load_json and save_json, but at least the places mentioned in #10269 could possibly also benefit from this change.

Related issue (if applicable): fixes #

Pull request in home-assistant.github.io with documentation (if applicable): home-assistant/home-assistant.github.io#<home-assistant.github.io PR number goes here>

Example entry for configuration.yaml (if applicable):

Checklist:

If user exposed functionality or configuration variables are added/changed:

If the code communicates with devices, web services, or third-party tools:

  • Local tests with tox run successfully. Your PR cannot be merged unless tests pass
  • New dependencies have been added to the REQUIREMENTS variable (example).
  • New dependencies are only imported inside functions that use them (example).
  • New dependencies have been added to requirements_all.txt by running script/gen_requirements_all.py.
  • New files were added to .coveragerc.

If the code does not interact with devices:

  • Local tests with tox run successfully. Your PR cannot be merged unless tests pass
  • Tests have been added to verify that the new code works.

@ggravlingen
Copy link
Contributor

"""
try:
with open(filename, 'w', encoding='utf-8') as fdesc:
fdesc.write(json.dumps(config, sort_keys=True, indent=4))
Copy link
Member

Choose a reason for hiding this comment

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

We should json dump to a string before opening the file. That way, when dumping fails we don't truncate the file.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point!

try:
with open(filename, 'w', encoding='utf-8') as fdesc:
fdesc.write(json.dumps(config, sort_keys=True, indent=4))
return True
Copy link
Member

Choose a reason for hiding this comment

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

Inconsistent return .

@@ -116,6 +121,38 @@ def get_random_string(length=10):
return ''.join(generator.choice(source_chars) for _ in range(length))


def load_json(filename: str) -> Union[List, Dict]:
Copy link
Member

Choose a reason for hiding this comment

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

Let's move these files to their own package util.json

except FileNotFoundError:
_LOGGER.debug('JSON file not found: %s', filename)
except ValueError:
_LOGGER.warning('Could not parse JSON content: %s', filename)
Copy link
Member

Choose a reason for hiding this comment

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

This error is pretty bad, we should probably just blow up?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You are right. I didn't want to change the behavior much from what was currently in place/use.
I'll raise a HomeAsssistantError, analogous to load_yaml, instead.

Copy link
Contributor

Choose a reason for hiding this comment

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

This means that we do no longer support empty files?

except ValueError:
_LOGGER.warning('Could not parse JSON content: %s', filename)
except OSError as error:
_LOGGER.warning('JSON file reading failed: %s (%s)',
Copy link
Member

Choose a reason for hiding this comment

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

This error is pretty bad, we should probably just blow up?

with open(filename, 'w', encoding='utf-8') as fdesc:
fdesc.write(json.dumps(config, sort_keys=True, indent=4))
return True
except OSError as error:
Copy link
Member

Choose a reason for hiding this comment

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

Same here, should we blow up to make sure that both user and code knows it did not manage to save anything.

@balloob
Copy link
Member

balloob commented Oct 30, 2017

This is a great initiative! Especially config_from_file(filename, config=None) was pretty bad as it was conflating the concerns of reading and writing.

"""
try:
with open(filename, 'w', encoding='utf-8') as fdesc:
data = json.dumps(config, sort_keys=True, indent=4)
Copy link
Member

Choose a reason for hiding this comment

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

We should do this before opening the file, otherwise the file has already been truncated.

Copy link
Member

@balloob balloob left a comment

Choose a reason for hiding this comment

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

Ok to merge when last comment addressed 🐬 🌮 thanks!

@molobrakos molobrakos deleted the json branch November 12, 2017 15:27
@home-assistant home-assistant locked and limited conversation to collaborators Mar 2, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants